<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.2">Jekyll</generator><link href="https://davidjguru.github.io//feed.xml" rel="self" type="application/atom+xml" /><link href="https://davidjguru.github.io//" rel="alternate" type="text/html" /><updated>2023-01-03T14:32:34+00:00</updated><id>https://davidjguru.github.io//feed.xml</id><title type="html">davidjguru.github.io</title><subtitle>the sketchbook for www.therussianlullaby.com</subtitle><entry><title type="html">Drupal Tips: Avoid infinite loop in user login</title><link href="https://davidjguru.github.io//blog/drupal-tips-avoid-infinite-loop-in-user-login" rel="alternate" type="text/html" title="Drupal Tips: Avoid infinite loop in user login" /><published>2023-01-03T00:00:00+00:00</published><updated>2023-01-03T00:00:00+00:00</updated><id>https://davidjguru.github.io//blog/drupal-tips-avoid-infinite-loop-in-user-login</id><content type="html" xml:base="https://davidjguru.github.io//blog/drupal-tips-avoid-infinite-loop-in-user-login">&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_avoid_infinite_loop_in_user_login.jpg&quot; alt=&quot;Picture from Unsplash, by user @tine999&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Picture from Unsplash, user &lt;a href=&quot;https://unsplash.com/@tine999&quot;&gt;Tine Ivanič, @tine999&lt;/a&gt;&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Last week I had to perform an intervention in a Drupal installation due to an unexpected bug. It was a problem that I hadn’t seen in Drupal for a long time… But the key really is that I was the one who created the issue so I think I’m ready to explain how it happened (my own code generated it) and how to fix it… I am very pleased to join you today to share with you my latest ridiculous mistake: the infinite login redirection in Drupal (and how to solve it)!… &lt;br /&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;Well, actually and to be fair, the title should be something like “what did I do to cause an infinite loop” or maybe “How I generated an endless loop of redirections in Drupal”, but it didn’t work well as a title (marketing issues) so better that way.&lt;/p&gt;

&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h2&gt;

&lt;p&gt;This post was composed from my current position as Senior Drupal Developer at &lt;a href=&quot;https://ffwagency.com/&quot;&gt;FFW Agency&lt;/a&gt;, one of the biggest companies oriented to Open Source in the world and specifically focused in Drupal.&lt;/p&gt;

&lt;h2 id=&quot;checking-the-node--entity-access&quot;&gt;Checking the node / entity access&lt;/h2&gt;

&lt;p&gt;My little problem started from a very simple model. In fact my starting idea was quite simple: to check the visibility of certain types of nodes for some users based on some taxonomy terms, that is, depending on the taxonomy term (group 1, group 2, group 3, group 4) applied to a user (group 2), this user could only see nodes labeled with the same taxonomy term (group 2), and for this, better centralize the activity using well known Drupal hooks: &lt;a href=&quot;https://api.drupal.org/api/drupal/core%21modules%21node%21node.api.php/function/hook_node_access/8.8.x&quot;&gt;hook_node_access&lt;/a&gt; for 8.x or &lt;a href=&quot;https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21entity.api.php/function/hook_entity_access/9.4.x&quot;&gt;hook_entity_access&lt;/a&gt; for 9.x and above.  I was looking for something that can be summarized in the following image:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_avoid_infinite_loop_in_login_user_one.png&quot; alt=&quot;Managing node access by matching taxonomy terms&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Managing node access by matching taxonomy terms&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;For those unfamiliar with its use, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hook_entity_access&lt;/code&gt; works like an updated version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hook_node_access&lt;/code&gt;,  more generalized for entities and with some restrictions on the parameters of CRUD operations to be processed (create, delete, update, view) respect to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hook_node_access&lt;/code&gt;. But in fact both share a similar scheme of work:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The hooks will receive some item-to-check related params:  entity/node, operation and user account.&lt;/li&gt;
  &lt;li&gt;The hooks will return an access result based in &lt;a href=&quot;https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Access%21AccessResultInterface.php/interface/AccessResultInterface/8.8.x&quot;&gt;AccessResultInterface&lt;/a&gt;: allowed, forbidden, neutral…&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is a comparison between these two access hooks:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_avoid_infinite_loop_in_login_user_two.png&quot; alt=&quot;Entity Access and Node Access comparison&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Entity Access and Node Access comparison&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;So I started using the version &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hook_node_access()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/**
 * Implements hook_node_access().
 */
function my_custom_module_access_node_access(NodeInterface $node, $op, AccountInterface $account) {
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And by the way, I’m only concerned about specific types using the selected vocabulary as field:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$specific_content_types = [
  'content_type_one',
  'content_type_two',
];
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then I’m getting the whole entity for the current user:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$current_user_entity = \Drupal::entityTypeManager()-&amp;gt;getStorage('user')-&amp;gt;load($account-&amp;gt;id());
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I would like to think about permissions, checking all scenarios where we will be neutral in access:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;If is another content type then is not our business.&lt;/li&gt;
  &lt;li&gt;We’re only interested in management of views of nodes.&lt;/li&gt;
  &lt;li&gt;Node has not associated value in taxonomy term field.&lt;/li&gt;
  &lt;li&gt;Being a registered user the account has not value in taxonomy term field.&lt;/li&gt;
  &lt;li&gt;Current User has permissions to bypass access restrictions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I could generate some control like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#1  if ((!in_array($node-&amp;gt;bundle(), $specific_content_types_content_types)) || 
#2     ($op != 'view') || 
#3     ($node-&amp;gt;get('field_groups')-&amp;gt;isEmpty()) ||
#4     (($account-&amp;gt;isAuthenticated()) &amp;amp;&amp;amp; ($current_user_entity-&amp;gt;get('field_vocabulary')-&amp;gt;isEmpty())) ||
#5     ($account-&amp;gt;hasPermission('bypass content access'))) {

        return AccessResult::neutral();
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But what about other scenarios? I’m interested in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forbidden&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;allowed&lt;/code&gt; cases. For instance, when the node could have loaded taxonomy terms in the key field (or maybe not) but user is not authenticated:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if ($account-&amp;gt;isAnonymous()) {
  return AccessResult::forbidden();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And finally, the main key scenario and its derivatives: user and node have loaded values in the taxonomy term field and we have to look for a possible match between them, looping all the possible array of values. Here the user is authenticated and as a first step, we have to get the existing values in taxonomy term field:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$terms_node = $node-&amp;gt;get('field_vocabulary')-&amp;gt;getValue();
$terms_user = $current_user_entity-&amp;gt;get('field_vocabulary')-&amp;gt;getValue();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And as sub-case, we have to check if user is just registered but there is no value associated with the taxonomy field. In a hurry and without thinking too much, I chose this way of extracting the value of the field, being an entity reference field:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if ($account-&amp;gt;isAuthenticated() &amp;amp;&amp;amp; ($current_user_entity-&amp;gt;get('field_vocabulary')-&amp;gt;getValue()[0]['target_id'] == 0)) {
  return AccessResult::neutral();
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You know, if any of the taxonomy terms from the node items is equal to any of the user account then we’ll have granted access to the node:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// Third: existing terms in node and user we'll match between terms.
foreach ($terms_node as $node_target) {
  foreach ($terms_user as $user_target) {
    if ($node_target['target_id'] == $user_target['target_id']) {
      return AccessResult::allowed();
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And finally, while you’re a non-allowed user for the node we will redirect you to the home node:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// 101 is the ID of the node marked as home page.  
$url = Url::fromRoute('entity.node.canonical', ['node' =&amp;gt; 101]);
$redirect = new RedirectResponse($url-&amp;gt;toString());
$redirect-&amp;gt;send();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;These ideas, these implementations that seem to have a certain logic… did not take long to cause serious problems after the deployment of the website and testing… after a while, several colleagues started to raise the alarm.&lt;/p&gt;

&lt;h2 id=&quot;the-issue&quot;&gt;The Issue&lt;/h2&gt;

&lt;p&gt;As I  said in a previous paragraph, these changes caused bugs immediately after deployment in testing environments. The most obvious one was that after the user login, with the user already registered, visiting the nodes resulted in an infinite loop of redirection that prevented access to the website:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_avoid_infinite_loop_in_user_login_three.png&quot; alt=&quot;Infinite loop of redirection causing issues by blocking access&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Infinite loop of redirection causing blocking access&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;At first glance, this problem can be recognised with a trained Drupal troubleshooting eye: the user is already logged in, an access is attempted and denied (forbidden) and a redirect is triggered, which will contain the login screen. But the user is already logged in, so it redirects endlessly until the login is closed.&lt;/p&gt;

&lt;p&gt;So you have to stop, review and debug the code until you find the bugs… so please enable your xdebug configuration, F5 (in my VSCode installation) and go to run a debugging… in my case I found two main problems:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The way I’m getting the taxonomy terms values.&lt;/li&gt;
  &lt;li&gt;The way I’m executing redirection.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s check the issues.&lt;/p&gt;

&lt;h3 id=&quot;1-the-way-im-getting-the-taxonomy-terms-values&quot;&gt;1. The way I’m getting the taxonomy terms values&lt;/h3&gt;

&lt;p&gt;The first issue was how I was getting the taxonomy term values from the different sources in order to look for a match. You know, I’m talking about the values from the Entity Reference Field (Taxonomy Term in the Drupal standard field is Entity Reference).  At some point in my code I’m just checking if any value was set in the taxonomy term field:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;($current_user_entity-&amp;gt;get('field_groups')-&amp;gt;isEmpty())
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And this expression was avoiding the pass when the field wasn’t filled, passing the action to the next &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;else&lt;/code&gt; clause ordering the redirection:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$url = Url::fromRoute('entity.node.canonical', ['node' =&amp;gt; $return_page]);
$redirect = new RedirectResponse($url-&amp;gt;toString());
$redirect-&amp;gt;send();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We said that the field was not set, but this is not really true, due to the value being zero, and not empty. From this point of view, may can be more useful check values in a different way:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;($current_user_entity-&amp;gt;get('field_groups')-&amp;gt;getvalue()[0]['target_id'] == 0)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;But while that’s true the response is an array of values -being the taxonomy term field a multivalue field-, if the field was not filled then the response can be an unique value that you can check in a more single way using less expressions and reducing your code:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;($current_user_entity-&amp;gt;get('field_groups')-&amp;gt;target_id == 0)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And remember you can obtain some more taxonomy terms related info if you need by using something like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$terms = $node-&amp;gt;get('field_vocabulary')-&amp;gt;referencedEntities();
foreach ($terms as $term) {
  $name = $term-&amp;gt;getName();
  $tid = $term-&amp;gt;id();
  $some_field_values = $term-&amp;gt;get('specific_field_of_the_vocabulary_term')-&amp;gt;getValue();
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we have a more controlled processing of the value for taxonomy terms, checking it and giving permissions on access.&lt;/p&gt;

&lt;h3 id=&quot;2-the-way-im-executing-redirection&quot;&gt;2. The way I’m executing redirection&lt;/h3&gt;

&lt;p&gt;The second issue (well, is not really an issue but something at risk of becoming technical debt). Now I’m talking about the redirection.Remember that when you want to redirect the user’s navigation, you can use various approaches. Let’s see…&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Calling for the 403 system page&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;system.403:
  path: '/system/403'
  defaults:
    _controller: '\Drupal\system\Controller\Http4xxController:on403'
    _title: 'Access denied'
  requirements:
    _access: 'TRUE'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And so you can use a redirection based in the internal system route:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$url = Url::fromRoute('system.403');
$response = new RedirectResponse($url-&amp;gt;toString());
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Loading the related node ID for redirection
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$url = Url::fromRoute('entity.node.canonical', ['node' =&amp;gt; 101]);
$redirect = new RedirectResponse($url-&amp;gt;toString());
$redirect-&amp;gt;send();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;What was my initial approach?&lt;/strong&gt; I thought I’d go and ask the system what page it had loaded for redirects. Something like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$site_config = \Drupal::config('system.site');
if (is_null($site_config-&amp;gt;get('page')['403'])) {
  // If a 403 error page is not configured then we will redirect to /home.
  $return_page = (int) filter_var($site_config-&amp;gt;get('page')['front'], FILTER_SANITIZE_NUMBER_INT);
}
else {
  // If 403 page exists we will redirect to error page.
  $return_page = (int) filter_var($site_config-&amp;gt;get('page')['403'], FILTER_SANITIZE_NUMBER_INT);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And finally I’ll load the return page for redirection:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$url = Url::fromRoute('entity.node.canonical', ['node' =&amp;gt; $return_page]);
$redirect = new RedirectResponse($url-&amp;gt;toString());
$redirect-&amp;gt;send();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;What was the problem here?&lt;/strong&gt; Well firstly, we have to avoid sending responses directly (this can be problematic due to conflicts with two responses, one from you and another from the Drupal system by itself), Then I have to think about the context: while I’m in a Drupal multisite installation, I’m not pretty sure if every single site has been registered with a specific error page, so maybe a source of errors. I need some more neutral, more… “delegated”…
So for me the solution was to use &lt;a href=&quot;https://github.com/symfony/symfony/blob/6.3/src/Symfony/Component/HttpKernel/Exception/AccessDeniedHttpException.php&quot;&gt;Symfony AccessDeniedHttpException&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  // Fourth: As you're a non-allowed user for this node we'll redirect you.
  throw new AccessDeniedHttpException();
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will pass the default value “403” to its parent’ constructor and so, the HttpException will be called and it will generate an autonomous response. This can be a more clean solution ;-)&lt;/p&gt;

&lt;h2 id=&quot;read-more&quot;&gt;Read More&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://drupal.stackexchange.com/questions/215627/programmatically-redirect-users-to-the-default-access-restricted&quot;&gt;Redirect users to the default “access restricted”&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.drupal.org/project/permissions_by_term/issues/3009470#comment-12834686&quot;&gt;Permissions by term&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.drupal.org/files/issues/2018-10-29/3009470-403-url-settings-ignored.patch&quot;&gt;403 settings ignored patch&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/symfony/symfony/blob/6.3/src/Symfony/Component/HttpKernel/Exception/AccessDeniedHttpException.php&quot;&gt;The AccessDeniedHttpException&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;wq&quot;&gt;:wq!&lt;/h2&gt;

&lt;h3 id=&quot;recommended-song-qué-he-sacado-con-quererte-aka-violeta-parra---guadalupe-plata&quot;&gt;Recommended song: Qué he sacado con quererte AKA Violeta Parra - Guadalupe Plata&lt;/h3&gt;

&lt;div class=&quot;embed-container&quot;&gt;
    &lt;iframe src=&quot;https://www.youtube.com/embed/eoHhdrqtYho&quot; width=&quot;700&quot; height=&quot;480&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;
    &lt;/iframe&gt;
  &lt;/div&gt;</content><author><name>davidjguru</name></author><category term="Drupal Tips" /><summary type="html">Picture from Unsplash, user Tine Ivanič, @tine999 Last week I had to perform an intervention in a Drupal installation due to an unexpected bug. It was a problem that I hadn’t seen in Drupal for a long time… But the key really is that I was the one who created the issue so I think I’m ready to explain how it happened (my own code generated it) and how to fix it… I am very pleased to join you today to share with you my latest ridiculous mistake: the infinite login redirection in Drupal (and how to solve it)!…</summary></entry><entry><title type="html">Tooling: Python2 error in SASS building frontend</title><link href="https://davidjguru.github.io//blog/tooling-python2-error-in-sass-building-frontend" rel="alternate" type="text/html" title="Tooling: Python2 error in SASS building frontend" /><published>2022-09-16T00:00:00+00:00</published><updated>2022-09-16T00:00:00+00:00</updated><id>https://davidjguru.github.io//blog/tooling-python2-error-in-sass-building-frontend</id><content type="html" xml:base="https://davidjguru.github.io//blog/tooling-python2-error-in-sass-building-frontend">&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_drupal_tooling_python2_in_SASS_errors_building_frontend_main.jpg&quot; alt=&quot;Picture from Unsplash, by @markuswinkler&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Picture from Unsplash, user &lt;a href=&quot;https://unsplash.com/@markuswinkler&quot;&gt;Markus Winkler, @markuswinkler&lt;/a&gt;&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Now in my current context I’m working on a multisite Drupal installation with several internal sites (more than a hundred sites) and among other experiences, I’m facing new issues that I had not experienced before. This little post is about that: a very specific error that can be common and how to solve it.&lt;br /&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;Well, now I’m working in a different stack from what I’m used to: I’m using &lt;a href=&quot;https://docksal.io/&quot;&gt;Docksal&lt;/a&gt;, a software virtualization tool for containers and &lt;a href=&quot;https://github.com/acquia/blt&quot;&gt;Acquia BLT&lt;/a&gt; (or Acquia Build and Launch Tool), a resource for automatization of tasks, deploys and testing. The combination of both allows to build Docker container networks in your local environment and to have pre-configured different tasks for the daily management of Drupal-based websites.&lt;/p&gt;

&lt;p&gt;I recommend you to try them, although for containers I prefer &lt;a href=&quot;https://ddev.readthedocs.io/en/stable/&quot;&gt;DDEV&lt;/a&gt; -that’s true- but I think that experiencing a containerization tool (Docksal, DDEV, &lt;a href=&quot;https://github.com/wodby/docker4drupal&quot;&gt;Docker4Drupal&lt;/a&gt;, &lt;a href=&quot;https://github.com/shaal/ddev-gitpod&quot;&gt;Gitpod&lt;/a&gt;…) and a maintenance and development task management tool (Acquia BLT, &lt;a href=&quot;https://robo.li/&quot;&gt;Robo&lt;/a&gt; / &lt;a href=&quot;https://github.com/Ymbra/Drobo&quot;&gt;Drobo&lt;/a&gt;, &lt;a href=&quot;https://deployer.org/docs/7.x/recipe/drupal8&quot;&gt;Deployer&lt;/a&gt; is a MUST for any Drupal developer.&lt;/p&gt;

&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h2&gt;

&lt;p&gt;This post was composed from my current position as Senior Drupal Developer at &lt;a href=&quot;https://ffwagency.com/&quot;&gt;FFW Agency&lt;/a&gt;, one of the biggest companies oriented to Open Source in the world and specifically focused in Drupal.&lt;/p&gt;

&lt;h2 id=&quot;the-issue&quot;&gt;The Issue&lt;/h2&gt;

&lt;p&gt;When I want to build up the frontend of a site, I execute a combined Docksal + BLT instruction, something like using the classical @alias/naming of a site:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; fin blt frontend --site=one.of.my.sites.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;At some point, I’m getting this error message:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;error /var/www/docroot/themes/custom/xxx_yyy_base_theme/node_modules/node-sass: Command failed.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And then in the same trace:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gyp verb check python checking for Python executable &quot;python2&quot; in the PATH
gyp verb `which` failed Error: not found: python2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And then the process is stopped and it is not possible to build the frontend of the required site… You can see the complete trace in the next screenshot:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_drupal_tooling_python2_in_SASS_errors_building_frontend_one.png&quot; alt=&quot;Getting python2 error in a frontend buil up&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Python2 error while we’re building up the frontend&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;So what I do is first of all, check the version numbers of each element involved in the Issue, using command line for the first items and then reviewing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt; file and getting some versions, or by using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yarn&lt;/code&gt; with subcommands just like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ yarn list --pattern &quot;node-sass&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And so I get all the values I am interested in, since I will have to google the status of each one, looking for issues, known bugs or deprecated code ;-) :&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;node -v: v16.16.0
npm -v: 8.11.0
node-sass:  4.14.1
node-gyp: 3.8.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;fixin&quot;&gt;Fixin’&lt;/h2&gt;

&lt;p&gt;Ok, let’s try to get a good understanding of what is happening throughout this process since we execute the frontend startup commands. As I said, when I’m running my current configuration in CLI, mixin’ docksal commands + Acquia tooling, I’m trying to run the build up for theming by usings something like this:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ fin blt frontend --site=one.of.my.sites.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Essentially I’m launching related scripting, diverse stuff as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setup.sh&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build.sh&lt;/code&gt;. And within these scripts (normally) you’re only running basic yarn specific and custom sub-commands, just like: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yarn run build:sass&lt;/code&gt;. Ok, and what does it means? traveling to every &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt; file, you can see the common scripts block:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;scripts&quot;: {
  ...
  &quot;clean&quot;: &quot;rm -rf node_modules pattern-lab&quot;,
  &quot;build:sass&quot;: &quot;node-sass src/_patterns -o src/_patterns --include-path breakpoint-sass/stylesheets&quot;,
  ...
},
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;So finally, when you (or your scripts) launch &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yarn run build:sass&lt;/code&gt;  finally you’re using the command:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;node-sass src/_patterns -o src/_patterns --include-path ./node_modules/breakpoint-sass/stylesheets
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Just in order to transpiling the CSS files in theming from SCSS syntax to processed CSS, marking source, the destiny folder (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-o /folder/&lt;/code&gt;) and other resources to integrate in the process (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--include-path&lt;/code&gt;) as usual.&lt;/p&gt;

&lt;p&gt;Ok, &lt;strong&gt;What’s the problem?&lt;/strong&gt; Well, the first key here: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node-sass&lt;/code&gt;. I’ve discovered the dependency is marked as deprecated from more than two years ago (nothing interesting from my side, just the magic of the hyperlink and a little of Google)… It causes problems and errors because nodejs compatibility with the current version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node-sass&lt;/code&gt; installed. &lt;a href=&quot;https://www.npmjs.com/package/node-sass&quot;&gt;You can see the current status of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node-sass&lt;/code&gt; here&lt;/a&gt; or &lt;a href=&quot;https://www.drupal.org/project/varbase/issues/3271850&quot;&gt;in tickets from some Drupal distributions like Varbase&lt;/a&gt;. This issue has been detected by me at least in a pair of themes of my current multisite structure, think about theme_one and theme_two. So, we’ll need a new resource instead the deprecated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node-sass&lt;/code&gt;. Ok, but, &lt;strong&gt;what’s the solution?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can use &lt;a href=&quot;https://sass-lang.com/dart-sass&quot;&gt;dart-sass&lt;/a&gt; instead. The movement requires changes at some levels, just like those (follow the next steps):&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Connect to your selected docker container and move to your theme folder:
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ fin bash
docker@cli:/var/www$ cd docroot/themes/custom/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Remove deprecated dependencies using yarn and delete &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node-sass&lt;/code&gt; from requirements.
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker@cli:/var/www/docroot/themes/custom/theme_one$ yarn remove node-sass
docker@cli:/var/www/docroot/themes/custom/theme_two$ yarn remove node-sass
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Install new dependencies.
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker@cli:/var/www/docroot/themes/custom/theme_one$ yarn add --dev sass sass-loader
docker@cli:/var/www/docroot/themes/custom/theme_two$ yarn add --dev sass sass-loader
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Remove &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node_modules&lt;/code&gt; folder in every theme directory and regenerate it using the new dependencies (dart-sass as just “sass” resource).
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker@cli:/var/www/docroot/themes/custom/theme_one$ rm -rf node_modules
docker@cli:/var/www/docroot/themes/custom/theme_one$ yarn install
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;Review and execute small adjustments and changes in commands, sub-commands and flags or params used from internal scripts (e.g  build.sh or setup.sh in some themes but executing scripting orders compiled in package.json files from every theme). So we have to ensure that after the executed changes, the commands are modified also in order to execute the same steps when building frontend.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For instance, while in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node-sass&lt;/code&gt; you had flags like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-o&lt;/code&gt; in order to set the output folder, now you don’t need the item in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dart-sass&lt;/code&gt;. Or param &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--include-path&lt;/code&gt; is changed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--load-path&lt;/code&gt;in the new library.&lt;/p&gt;

&lt;p&gt;So in your scripting block you had:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;build:sass&quot;: &quot;node-sass src/_patterns -o src/_patterns --include-path ./node_modules/breakpoint-sass/stylesheets&quot;,
&quot;build:pl-sass&quot;: &quot;node-sass --importer node_modules/node-sass-glob-importer/dist/cli.js src/sass/ -o src/css --include-path ./node_modules/breakpoint-sass/stylesheets&quot;,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And now we have:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;build:sass&quot;: &quot;sass src/_patterns:src/_patterns --load-path ./node_modules/breakpoint-sass/stylesheets&quot;,
&quot;build:pl-sass&quot;: &quot;sass --importer node_modules/node-sass-glob-importer/dist/cli.js src/sass/  src/css --load-path ./node_modules/breakpoint-sass/stylesheets&quot;,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Pay attention in your code cause you can get some warnings after switching to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dart-sass&lt;/code&gt;. For instance, after switching from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node-sass&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dart-sass&lt;/code&gt;, there are some deprecated expressions that may cause you receive some warning messages. See:&lt;/li&gt;
&lt;/ol&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_drupal_tooling_python2_in_SASS_errors_building_frontend_two.png&quot; alt=&quot;Getting some warnings from dart-sass deprecated code&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Deprecations warnings from dart-sass&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Before:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;span {
  box-sizing: border-box;
  max-width: 40px;
  padding: $space / 2;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;After:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;span {
  box-sizing: border-box;
  max-width: 40px;
  padding: math.div($space, 2);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once you have these adjustments made to your .scss files, you are ready to have a completely clean and updated frontend startup. That’s it.&lt;/p&gt;

&lt;h2 id=&quot;warning&quot;&gt;Warning&lt;/h2&gt;

&lt;p&gt;It was only repaired in some themes of a large set of themes and subthemes in a multisite installation… I mean, if it is your scenario, may be necessary to make similar changes to other existing themes which, at this stage, you have not yet tested. Think that if your internal multisite structure looks like the one I’m using now, then each theme / subtheme has its own build up process, with its own resources and dependencies (package.json, yarn.lock, assets, etc.).&lt;/p&gt;

&lt;h2 id=&quot;read-more&quot;&gt;Read More&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.npmjs.com/package/node-sass&quot;&gt;npmjs: node-sass&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/sass/node-sass/issues/2952&quot;&gt;github: node-sass related issue&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://sass-lang.com/blog/libsass-is-deprecated&quot;&gt;sass-lang: libsass is deprecated&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/65594119/node-sass-usage-is-deprecated-and-will-be-removed-in-a-future-major-version&quot;&gt;stackoverflow: node-sass deprecated&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://dev.to/ccreusat/migrating-from-node-sass-to-sass-dart-sass-with-npm-3g3c&quot;&gt;dev.to: migrating from node-sass to dart-sass&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/68850056/switching-from-node-sass-to-dart-sass-in-vue-styleguidist-project&quot;&gt;stackoverflow: switching node-sass to dart-sass&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;wq&quot;&gt;:wq!&lt;/h2&gt;

&lt;h3 id=&quot;recommended-song-in-spain-we-call-it-soledad---rigoberta-bandini&quot;&gt;Recommended song: In Spain we call it Soledad - Rigoberta Bandini&lt;/h3&gt;

&lt;div class=&quot;embed-container&quot;&gt;
    &lt;iframe src=&quot;https://www.youtube.com/embed/bYA81QfWSsw&quot; width=&quot;700&quot; height=&quot;480&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;
    &lt;/iframe&gt;
  &lt;/div&gt;</content><author><name>davidjguru</name></author><category term="Tooling" /><summary type="html">Picture from Unsplash, user Markus Winkler, @markuswinkler Now in my current context I’m working on a multisite Drupal installation with several internal sites (more than a hundred sites) and among other experiences, I’m facing new issues that I had not experienced before. This little post is about that: a very specific error that can be common and how to solve it.</summary></entry><entry><title type="html">Drupal Tips: Changing session lifetime for users</title><link href="https://davidjguru.github.io//blog/drupal-tips-changing-session-lifetime-for-users" rel="alternate" type="text/html" title="Drupal Tips: Changing session lifetime for users" /><published>2022-03-30T00:00:00+00:00</published><updated>2022-03-30T00:00:00+00:00</updated><id>https://davidjguru.github.io//blog/drupal-tips-changing-session-lifetime-for-users</id><content type="html" xml:base="https://davidjguru.github.io//blog/drupal-tips-changing-session-lifetime-for-users">&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_changing_session_lifetime_for_users_main.jpg&quot; alt=&quot;Picture from Unsplash, by @malvestida&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Picture from Unsplash, user &lt;a href=&quot;https://unsplash.com/@malvestida&quot;&gt;Malvestida, @malvestida&lt;/a&gt;&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The Session time management is an important aspect in any type of application: it allows to determine under which processes the user login will be performed, how the user session will be managed and how the user logout will take place. In the case of Drupal, as in other technologies, it is essential to know the most important aspects of sessions and also, if the architecture is “decoupled”, we will have to take them into account to connect sessions opened from the frontend but managed in the backend. This only increases its complexity and importance.&lt;br /&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;That is why we are going to share some concepts and ideas. Unfortunately, as I don’t have all the necessary time and it would be a more extensive subject, &lt;strong&gt;I’m going to focus only on Drupal session management as a monolith&lt;/strong&gt;. The “decoupled” variant is more extensive and complex and involves more intermediate tools, such as token management, SAML, etc. Perhaps for a more advanced article in &lt;a href=&quot;https://www.therussianlullaby.com/&quot;&gt;www.therussianlullaby.com&lt;/a&gt; in the future. For now, just a sketch here.&lt;/p&gt;

&lt;h2 id=&quot;acknowledgments&quot;&gt;&lt;strong&gt;Acknowledgments&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;This post was composed from my current position as Senior Drupal Developer at &lt;a href=&quot;https://www.digitalist.se/english&quot;&gt;Digitalist Sweden&lt;/a&gt;, one of the biggest companies oriented to Open Source in Europe and specifically focused in Drupal.&lt;/p&gt;

&lt;h2 id=&quot;goals-and-basic-concepts&quot;&gt;Goals and basic concepts&lt;/h2&gt;

&lt;p&gt;A Drupal installation uses the built-in PHP session mechanism, which is based essentially on a cookie. &lt;strong&gt;The cookie name is SESS and is followed by a long string of characters&lt;/strong&gt;, and its value is another long string of characters, as you can see in the next caption from a new Drupal local deploy based in &lt;a href=&quot;https://www.digitalocean.com/community/tutorials/how-to-develop-a-drupal-9-website-on-your-local-machine-using-docker-and-ddev&quot;&gt;DDEV tooling&lt;/a&gt;:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_changing_session_lifetime_for_users_1.png&quot; alt=&quot;Cookie values for session in Drupal installation&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Cookie values for sessions in a Drupal installation&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;PHP can inspect this cookie and makes it available to Drupal’s session implementation&lt;/strong&gt;, using the database table sessions for storage, with the value of the cookie as the key session identification (sid). Then the session entry is also saving records using the current user ID. In the Drupal bootstrap sequence the session is loaded with the related user object, and is used to manage access to resources and other stuff, using the user’s roles and other specific attributes. Here are the mechanics.&lt;/p&gt;

&lt;p&gt;The stored Data in the PHP global array $_SESSION will be transferred and saved to the current session’s database entry in the Drupal backend at the end of a single page request. Such a process can be observed to store important data such as items in a shopping cart and/or other related stuff.&lt;/p&gt;

&lt;p&gt;By the way (and as it is very logical): &lt;strong&gt;You can work using other cookies that can be saved and retrieved by code. of course&lt;/strong&gt;. In addition, it is also important to know that cookies with an expiry time of 0 are also often know as “session cookies”, cause these are deleted when you close your browser. &lt;strong&gt;This will be part of our goals in this case: to get session cookies&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For this case, we have only a couple of basic goals:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Identify the time session management in backend (Drupal)&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Make sure the user is logged out when close tab / window / session&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For which we will first need to understand some basic concepts:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gc_maxlifetime
cookie_lifetime
gc_probability
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What do they mean? Let’s see…&lt;/p&gt;

&lt;h3 id=&quot;gc_maxlifetime&quot;&gt;GC_MAXLIFETIME&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;This value is for the server:&lt;/strong&gt; It is a setting for Session Garbage Collection. Initially If the user’s last visit happened before 200,000s then this session is eligible for garbage collection.
Since it is GC, the session value may be discarded and not compulsory. If a GC action happens after the session was made eligible for the GC, it will be deleted.&lt;/p&gt;

&lt;h3 id=&quot;garbage-collector-gc-values&quot;&gt;GARBAGE COLLECTOR (GC values)&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The &lt;a href=&quot;https://tideways.com/profiler/blog/what-is-garbage-collection-in-php-and-how-do-you-make-the-most-of-it&quot;&gt;PHP’s Garbage Collector&lt;/a&gt; is an internal system that allows PHP to keep the memory clean&lt;/strong&gt;. You can enable or disable the associated functions using some parameters from code or from internal config files. &lt;strong&gt;How it works?&lt;/strong&gt; Well, we already know that a variable in PHP is stored in &lt;a href=&quot;https://www.php.net/manual/en/features.gc.refcounting-basics.php&quot;&gt;a container called “zval” (Zend Value), from C language&lt;/a&gt;. &lt;a href=&quot;https://www.zend.com/basic-php-structures&quot;&gt;This is a data structure implemented in C&lt;/a&gt; and it represents any PHP value (number, string, array, etc.). Here we’re storing also the type of variable, its value and some pieces of info:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;If the variable is part of the reference set.&lt;/li&gt;
  &lt;li&gt;If the variable is referenced from another places.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, periodically, some algorithms are reviewing the variables and resources, deleting the unused registers. For Garbage Collection, we have some params available in php.ini file: &lt;a href=&quot;https://www.php.net/manual/en/session.configuration.php&quot;&gt;php.net/session.configuration.php&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In general terms, we’re configuring this in the php.ini file:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;session.gc_maxlifetime = 3600
session.gc_probability = 1
session.gc_divisor = 1000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;But in the Drupal context, we can change these values from a Drupal installation, inside the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default.services.yml&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;web/sites/default/&lt;/code&gt; or in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.services.yml&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;web/core/&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;parameters:
  session.storage.options:
    gc_probability: 1
    gc_divisor: 100
    gc_maxlifetime: 200000
    cookie_lifetime: 2000000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;As you can see expanded in the original block: from  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default.services.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;session.storage.options:
    # Default ini options for sessions.
    #
    # Some distributions of Linux (most notably Debian) ship their PHP
    # installations with garbage collection (gc) disabled. Since Drupal depends
    # on PHP's garbage collection for clearing sessions, ensure that garbage
    # collection occurs by using the most common settings.
    # @default 1
    gc_probability: 1
    # @default 100
    gc_divisor: 100
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gc_probability&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gc_divisor&lt;/code&gt; are two interrelated values that defines the probability that the gc (garbage collection) process is started on every session initialization. The probability is calculated doing: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gc_probability/gc_divisor&lt;/code&gt; (1/100 for us) and it means there is a 1% chance that the GC process starts on each request.&lt;/p&gt;
&lt;h3 id=&quot;cookie_lifetime&quot;&gt;COOKIE_LIFETIME&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;This value is for the browser:&lt;/strong&gt; This is the absolute maximum time till which a browser can keep this cookie active. A 0 value here will means immediate or when the browser will be closed.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_changing_session_lifetime_for_users_2.png&quot; alt=&quot;Cookie values for creation and expiration dates&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Cookie values for creation and expiration dates&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;By default is set with 2,000,000 seconds, equals to almost 24 days. See the previous caption with creation and expiration date, so for a cookie created on March 27th, we can see an expiration date of April 19th, which is just a 23-day life cycle, the marked 2,000,000 seconds. You can think about change this data in service.yml files, but It’s true that these kind of files is out of control for Git so your changes will not be shared with your team, and it won’t be recreated in common environments (stage, preprod, prod, live, etc). You’ll need a more “structural” and persistent solution, so we will need to create a new custom module in next steps.&lt;/p&gt;

&lt;h2 id=&quot;addressing-session-cookie-management-in-drupal&quot;&gt;Addressing session cookie management in Drupal&lt;/h2&gt;

&lt;p&gt;The two main values related to sessions are coming from a static way in a services.yml file, generated in a Drupal installation from Composer. When I launch the build of a new Drupal site, I’m getting a set of values marked by-default. This file is setting the session lifetime with 200,000 seconds =&amp;gt; 55.55 hours =&amp;gt; 2.31 days. And the cookie lifetime by default with 2,000,000 seconds =&amp;gt; 555.55 hours =&amp;gt; 23,15 days.&lt;/p&gt;

&lt;p&gt;They are the values setted in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default.services.yml&lt;/code&gt; file as you can see for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gc_lifetime&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cookie_lifetime&lt;/code&gt; values in your Drupal installation:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    # Set session lifetime (in seconds), i.e. the grace period for session
    # data. Sessions are deleted by the session garbage collector after one
    # session lifetime has elapsed since the user's last visit. When a session
    # is deleted, authenticated users are logged out, and the contents of the
    # user's session is discarded.
    # @default 200000
    gc_maxlifetime: 200000
    #
    # Set session cookie lifetime (in seconds), i.e. the time from the session
    # is created to the cookie expires, i.e. when the browser is expected to
    # discard the cookie. The value 0 means &quot;until the browser is closed&quot;.
    # @default 2000000
    cookie_lifetime: 2000000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As we have already said, these values are in the default configuration of the Drupal installation. Besides this is part of the Container in Drupal, so can only be overwriting from a custom Drupal module using a pair of classes. We need something like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gc_maxlifetime: 3600 (only one hour of lifetime for the session).
cookie_lifetime: 0 (deleted when user close the browser tab).
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;overwriting-default-values-by-switching-service-class&quot;&gt;Overwriting default values by switching service class&lt;/h2&gt;

&lt;p&gt;Well, it seems that the default configuration used by the service responsible for managing sessions does not work for me and I need modifications from the container… &lt;strong&gt;What can I do?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The bad news&lt;/strong&gt; is that the above values are statically part of the service container after a Drupal installation, and cannot be modified “dynamically”. And these previous values are in the by-default configuration of the Drupal installation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The good news&lt;/strong&gt; is that we can add others values by switching with another class to replace the service provision.This is part of the Container in Drupal, so it can only be changed from a custom Drupal module using a pair of classes. We can do something like add the next values:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gc_maxlifetime: 3600&lt;/code&gt; (only one hour of lifetime for the session, and then make the session available for the garbage collector).&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cookie_lifetime: 0 &lt;/code&gt; (deleted when user closes the browser tab).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And here we can “decorating” existing service for overriding an existing service, as in Symfony (see “Read More” section with links) or we can provide another Service class and do the switch. To modify existing services, we have to implement a class extending ServiceProviderBase, a new Service class and the alter() method. In short, all we need is only change the class responsible for the sessions management, used in service &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;session_configuration&lt;/code&gt; as described in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core.services.yml&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; session_configuration:
    class: Drupal\Core\Session\SessionConfiguration
    arguments: ['%session.storage.options%']
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From a ServiceProvider class, by linking the service to our new custom class:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;ContainerBuilder&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$definition&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$container&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getDefinition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'session_configuration'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$definition&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;setClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'Drupal\custom_session_manager\StSessionConfiguration'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here you can see and download &lt;a href=&quot;https://gitlab.com/davidjguru/drupal-custom-modules-examples/-/tree/master/custom_session_manager&quot;&gt;the custom module implemented as example and uploaded to my Gitlab repository&lt;/a&gt;. Check out the code and test the feature! (not for production - live environments, please).
.&lt;/p&gt;

&lt;p&gt;So now:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// Allows the cookie to be destroyed when closing browser.
$options['cookie_lifetime'] = 0;            
// Allows the session to be aligned with the frontend session.     
$options['gc_maxlifetime'] = 3600; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And just enabling this new custom module, you will have a key change here: now the max-age of the session cookie will be set for expiring by session, see:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_changing_session_lifetime_for_users_3.png&quot; alt=&quot;Max-Age for cookie set to Session&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Max-Age for cookie set to Session&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Now when you close your browser, the session cookie will be deleted, the user logout will be executed and on the next URL load, the user session will still be closed.&lt;/p&gt;

&lt;h2 id=&quot;session-data--garbage-collector--cron&quot;&gt;Session data &amp;amp; Garbage Collector &amp;amp; Cron&lt;/h2&gt;

&lt;p&gt;You can load the session time with the values you want. But this only let available the session data for the Garbage Collector of Drupal/PHP. It means that from 1 hour the session can be opened until the Garbage Collector was executed. Who’s executing the Garbage Collector? essentially, the cron in system. The “Automated Cron” core module can be enabled and set to 1 hours. It means that really, the inactive sessions (more than 1 hour without activity) will be deleted every 1 hour now, just when cron runs and launches the Garbage Collector.&lt;/p&gt;

&lt;p&gt;But perhaps, we need a little more “granularity.” that is, to launch the cron only for these specific tasks, because launching it completely and for everything very frequently may not be the good idea we were thinking of. We need to be able to filter tasks associated with the cron in a more atomic way. For this we can rely on certain Drupal contributed modules that can provide us with functionality.&lt;/p&gt;

&lt;h3 id=&quot;useful-modules&quot;&gt;Useful Modules&lt;/h3&gt;

&lt;p&gt;Useful Drupal contrib modules we can use for more control over the session timing, roles and garbage collector from cron executions:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Session Limit: &lt;a href=&quot;https://www.drupal.org/project/session_limit&quot;&gt;drupal.org/session_limit&lt;/a&gt;. You can limit the number of sessions available for a role / user in different environments.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Automated Logout: &lt;a href=&quot;https://www.drupal.org/project/autologout&quot;&gt;drupal.org/autologout&lt;/a&gt;. You can configure sessions settings values in order to force the logout in users.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Ultimate Cron: &lt;a href=&quot;https://www.drupal.org/project/ultimate_cron&quot;&gt;drupal.org/ultimate_cron&lt;/a&gt;. It Allows refinement in cron timing and execution’s tasks.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Futhermore, we can create some specific cron-tab tasks on the server by prompt, if we need more control over the session data. Cron is a time-based job scheduling daemon in Linux Operating Systems. You can learn more about how to configure tasks in background using cron in the next section.&lt;/p&gt;

&lt;h2 id=&quot;read-more&quot;&gt;Read More&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://symfony.com/doc/current/service_container/service_decoration.html&quot;&gt;How to Decorate Services in Symfony&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.drupal.org/docs/drupal-apis/services-and-dependency-injection/altering-existing-services-providing-dynamic&quot;&gt;Altering existing services, providing dynamic services&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.previousnext.com.au/blog/overriding-services-drupal-8-advanced-cases&quot;&gt;Overriding services in Drupal 8 - advanced cases&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://codimth.com/blog/web/drupal/overriding-services-drupal-8-serviceprovidebase&quot;&gt;Overriding Services in Drupal 8 with ServiceProvideBase&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.geeksforgeeks.org/how-to-setup-cron-jobs-in-ubuntu/&quot;&gt;How to setup cron jobs in Ubuntu&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.digitalocean.com/community/tutorials/how-to-use-cron-to-automate-tasks-ubuntu-1804&quot;&gt;How To Use Cron to Automate Tasks on Ubuntu&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://serverspace.io/support/help/automate-tasks-with-cron-ubuntu-20-04/&quot;&gt;How to Automate Regular Tasks with Cron on Ubuntu&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;wq&quot;&gt;:wq!&lt;/h2&gt;

&lt;h3 id=&quot;recommended-song-i-feel-so-good---joanna-connor&quot;&gt;Recommended song: I Feel So Good - Joanna Connor&lt;/h3&gt;

&lt;div class=&quot;embed-container&quot;&gt;
    &lt;iframe src=&quot;https://www.youtube.com/embed/JUj5-MAcoiY&quot; width=&quot;700&quot; height=&quot;480&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;
    &lt;/iframe&gt;
  &lt;/div&gt;</content><author><name>davidjguru</name></author><category term="Drupal Tips" /><summary type="html">Picture from Unsplash, user Malvestida, @malvestida The Session time management is an important aspect in any type of application: it allows to determine under which processes the user login will be performed, how the user session will be managed and how the user logout will take place. In the case of Drupal, as in other technologies, it is essential to know the most important aspects of sessions and also, if the architecture is “decoupled”, we will have to take them into account to connect sessions opened from the frontend but managed in the backend. This only increases its complexity and importance.</summary></entry><entry><title type="html">Decrease noise, gain focus: Reduce your stress level</title><link href="https://davidjguru.github.io//blog/decrease-noise-gain-focus-reduce-your-stress-level" rel="alternate" type="text/html" title="Decrease noise, gain focus: Reduce your stress level" /><published>2022-02-01T00:00:00+00:00</published><updated>2022-02-01T00:00:00+00:00</updated><id>https://davidjguru.github.io//blog/decrease-noise-gain-focus-reduce-your-stress-level</id><content type="html" xml:base="https://davidjguru.github.io//blog/decrease-noise-gain-focus-reduce-your-stress-level">&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_decrease_noise_gain_focus_reduce_your_stress_level_main.jpg&quot; alt=&quot;Picture from Unsplash, by @nikkotations&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Picture from Unsplash, user &lt;a href=&quot;https://unsplash.com/@nikkotations&quot;&gt;Nikko Macaspac, @nikkotations&lt;/a&gt;&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Pandemic times have increased our stress levels, without a doubt. A very strange time that gradually stabilizes (it does not disappear, but becomes constant, inescapable and already installed in our daily lives). During this time, we have added new layers of concerns to our lives. We have said Goodbye to many loved ones. We have become (somewhat) more aware of the dangers of our consumerist way of life, seeing the risks of global warming and how this is intertwined, creating new serious problems that travel fast in our interconnected “world-system”…&lt;br /&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;And furthermore, it’s just as true that before these days, we were living in a roller coaster of tasks, worries and rush - a great deal of rush -. A whole life inserted in the guidelines of the so-called “late capitalism”, a turbo-version agitated between the sources of a meritocracy that does not exist, the crazy consumerism and the thousands of daily injustices and arbitrariness. It is in this context that we have recently (and very closely) seen the true fragility of life and the real engines that govern it (and none of them really belong to us).&lt;/p&gt;

&lt;p&gt;Strange times in which the old aspiration “to dream life, to change history” is beginning to reappear. But to begin to think we must remove the scabs of nostalgia and eliminate the noise and gain focus. Only then will we be able to reduce our stress and be able to think more clearly: anxiety, fatigue and stress are our enemies that prevent us from dreaming well.&lt;br /&gt;
How can we reduce our anxiety and stress level? There are some interesting ideas from some diverse contexts that can be useful to improve our inner state as a previous phase to be able to better reflect on what life (and what world) we want to have.&lt;/p&gt;

&lt;h2 id=&quot;first-simplify-your-daily-life&quot;&gt;First: Simplify your daily life&lt;/h2&gt;

&lt;p&gt;To begin with, we must understand one of the basic tensions of our daily life: the relationship between what is important and what is accessory, what is key and what is secondary… in order to be able to order well how we consume our time.&lt;/p&gt;

&lt;p&gt;Some oriental philosophies call our occidental mind &lt;a href=&quot;https://www.psychologytoday.com/us/blog/the-empowerment-diary/201709/calming-the-monkey-mind&quot;&gt;“The monkey mind”&lt;/a&gt;: our brain is passing quickly from one stimulus to another and then, connecting to another new input. This has been seen as a role model since ancient times, but what were neon lights decades ago are now mostly redirected to the Internet environment: Social Media, links after links, colours, ads… Instagram has a notification to let you know that you’re already up to date on your entire timeline (Ok, I’m sure you know it) but did you know Instagram also has &lt;a href=&quot;https://help.instagram.com/195902884574087&quot;&gt;an option to estimate the time you have consumed using the app&lt;/a&gt;? …so we can ask ourselves a few questions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;How much time are you spending chasing digital stimulus?&lt;/li&gt;
  &lt;li&gt;Are digital social media robbing time in your life?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think about the latest big thing released by Netflix: the film &lt;a href=&quot;https://www.filmaffinity.com/es/film521393.html&quot;&gt;“Don’t look up” (Adam McKay, 2021)&lt;/a&gt;… the asteroid could fall on us at any time (as a rock or in the form of a pandemic). Do you want it to reach you while you are looking at your smartphone? would you rather have done something else?&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_decrease_noise_gain_focus_reduce_your_stress_level_1.jpg&quot; alt=&quot;Picture from Don't look up&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Picture from Don’t look up, Hyperobject Industries, Bluegrass Films&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;second-purify-purify-purify-always-debugging&quot;&gt;Second: Purify, purify, purify always (debugging)&lt;/h2&gt;

&lt;p&gt;In addition, Let’s say in software development there are some principles oriented to get better results in any scenario, working iteratively and incrementally, perfecting your code. You have to think that your code can always be improved, but you should also think about reaching a minimum validated form, something functional that brings value and starts to solve your problem. Think about how methodologies such as “Lean” and its derivatives approach the processes and the achievement / scope of goals…Can we learn something?&lt;/p&gt;

&lt;p&gt;Sometimes one way to manage our stress and anxiety is to reduce our goals to the achievement of a “minimum viable product”, thought to get ahead and leave aside an obsessive perfection that can be problematic. In times of pandemic we have become acutely aware that our time is limited, and we are learning to give it as much value as possible - but towards the things that matter to us - Look for example at the case of “the great resignation”: What are we doing with our time or our life? What do we need, basically? 
With the old “protestant” legends about work and the meaning of work out of the way, what’s left? maybe it’s time to think about our tasks and please, review the scope of your goals.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Is this task very complex?&lt;/li&gt;
  &lt;li&gt;Can they be reduced?&lt;/li&gt;
  &lt;li&gt;Is it really interesting?&lt;/li&gt;
  &lt;li&gt;Does this have a minimal version?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Perhaps it is time to review our daily agenda, our commitments and objectives, and as Danton said in the middle of the French Revolution: “Audacity, more audacity, always audacity”. So you know: Purge, debug, clean. Permanent movement, permanent purification, permanent revolution… it may seem interesting, no?&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_decrease_noise_gain_focus_reduce_your_stress_level_2.jpg&quot; alt=&quot;Picture from the film The Trotsky&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Picture of Jay Baruchel in the film The Trotsky, 2009&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;third-learn-how-to-say-no&quot;&gt;Third: Learn how to say ‘No’&lt;/h2&gt;

&lt;p&gt;Finally, there is an example I would like to share with you: José Saramago (Portuguese writer and Nobel Prize of Literature in 1998) once said in an interview that the word ‘No’ was one of his favorite words, and this made a strong impression on me. I was much younger than I am now, and lived more impressed by the culture of appearance, looks and relationships. Cultivating “no” was like growing a plant that could only lead to isolation, but I was wrong: it’s a sweet treat for personal dignity.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_decrease_noise_gain_focus_reduce_your_stress_level_3.jpg&quot; alt=&quot;José Saramago&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Portrait of José Saramago&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Just how the author of “Blindness” and “The Cave”, try saying ‘No’ also as an internal way to review the connection of the thousand daily situations with your values and schemes…as someone once said: the best policy is the policy of principles.&lt;br /&gt;
Ask yourself:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;How many things do I do a day that I don’t really feel like doing?&lt;/li&gt;
  &lt;li&gt;How many tasks would I rather not do?&lt;/li&gt;
  &lt;li&gt;How many comments and attitudes are obvious even though I know they are wrong?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Train your behavior. Start with small “no’s”. Weak, whispered, progressive, musical. Rehearse until you find the tone, the voice. Your voice. Then you can prepare explanations, give context, refute, open up your position, locate the opposite, establish your dividing lines.
With time and training the “yes” will gain even more beauty and will be much more refined, more poetic, stronger. They will come to mean much more. We will learn to identify who are the strongest and who are the weakest in a conflict situation. We will be reaching the &lt;a href=&quot;https://www.britannica.com/topic/Satori&quot;&gt;Satori&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;To conclude, I would like to think that these lines have been useful to someone, starting with myself by putting together the ideas in my head after two years of continuous changes and various adaptations… Perhaps this article is not so much about reducing stress (what I had initially set out to do) as it is about stopping for a second to think about how we live, just before the flow of time sweeps us away.&lt;/p&gt;

&lt;p&gt;In any case, I think that there are useful things in the former three blocks:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Ordering “real - digital” relationship&lt;/li&gt;
  &lt;li&gt;Reviewing and adjusting the scope of our goals&lt;/li&gt;
  &lt;li&gt;Learning to say ‘No’&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can live more comfortably and maybe, reduce your stress level. Or at least, you will gain some time to dwell on the only pending account that nostalgia (backward thinking) and worry (forward thinking) prevent us from facing: dreaming life, changing history.&lt;/p&gt;

&lt;h2 id=&quot;read-more&quot;&gt;Read More:&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.forbes.com/sites/alicegwalton/2017/02/28/8-science-based-tricks-for-quieting-the-monkey-mind/?sh=2feca341af6c&quot;&gt;Forbes: 8 Science-Based Tricks For Quieting The Monkey Mind&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://zenhabits.net/monkey/&quot;&gt;Monkey Mind: Shifting the Habit of Feeling Distracted Throughout the Day&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.broadbandsearch.net/blog/average-daily-time-on-social-media&quot;&gt;Broadband Search: Average Time Spent Daily on Social Media, 2022&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.refinery29.com/en-us/2018/08/206008/instagram-time-spent-reminder&quot;&gt;You Can Now See How Much Time You Spend On Instagram, But Do You Want To Know?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.imdb.com/title/tt11286314/&quot;&gt;Don’t Look Up Profile in IMDB&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;wq&quot;&gt;:wq!&lt;/h2&gt;

&lt;h3 id=&quot;recommended-song-tarantella-del-gargano---daniele-sepe&quot;&gt;Recommended song: Tarantella del Gargano - Daniele Sepe&lt;/h3&gt;

&lt;div class=&quot;embed-container&quot;&gt;
    &lt;iframe src=&quot;https://www.youtube.com/embed/GGD1JlFLz54&quot; width=&quot;700&quot; height=&quot;480&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;
    &lt;/iframe&gt;
  &lt;/div&gt;</content><author><name>davidjguru</name></author><category term="General" /><summary type="html">Picture from Unsplash, user Nikko Macaspac, @nikkotations Pandemic times have increased our stress levels, without a doubt. A very strange time that gradually stabilizes (it does not disappear, but becomes constant, inescapable and already installed in our daily lives). During this time, we have added new layers of concerns to our lives. We have said Goodbye to many loved ones. We have become (somewhat) more aware of the dangers of our consumerist way of life, seeing the risks of global warming and how this is intertwined, creating new serious problems that travel fast in our interconnected “world-system”…</summary></entry><entry><title type="html">Drupal Tips: Altering order of execution in resources</title><link href="https://davidjguru.github.io//blog/drupal-tips-altering-order-of-execution-in-resources" rel="alternate" type="text/html" title="Drupal Tips: Altering order of execution in resources" /><published>2022-01-15T00:00:00+00:00</published><updated>2022-01-15T00:00:00+00:00</updated><id>https://davidjguru.github.io//blog/drupal-tips-altering-order-of-execution-in-resources</id><content type="html" xml:base="https://davidjguru.github.io//blog/drupal-tips-altering-order-of-execution-in-resources">&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_altering_order_of_execution_in_resources_main.jpg&quot; alt=&quot;Picture from Unsplash, by @andretaissin&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Picture from Unsplash, user &lt;a href=&quot;https://unsplash.com/@andretaissin&quot;&gt;Andre Taissin, @andretaissin&lt;/a&gt;&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Changes, changes, changes… throughout a project, we have to implement many changes and alterations to the Drupal code, without touching it directly -of course-. The event system is very powerful but there are still hooks at all levels, so sometimes we must use Hooks that will alter things already modified by other Hooks of the same nature. Also we may need to execute our changes before the changes made by another module (contrib or custom), and for that we must understand well how the order of execution of resources works…&lt;br /&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;In this brief publication for this sketchbook, I’ve put together some quick techniques for making modifications to the run order.** What can we do to add new submit functions to a form? (incorporating new actions to that submit), How can we make our submit actions precede existing ones? What is the relationship between the “weight” assigned to a module and its position in the execution order? in an intuitive way I want to make an approach to these questions and along the way, share some useful resources, such as functions and available contributed modules that we can use for our changes.&lt;br /&gt;
&lt;strong&gt;Read this little post, it can be useful if you need execute this kind of changes.&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;acknowledgments&quot;&gt;&lt;strong&gt;Acknowledgments&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;This post was composed from my current position as Senior Drupal Developer at &lt;a href=&quot;https://www.digitalist.se/english&quot;&gt;Digitalist Sweden&lt;/a&gt;, one of the biggest companies oriented to Open Source in Europe and specifically focused in Drupal.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; -&amp;gt; This is a little post about how to do changes in the order of execution of some Drupal resources by altering the position or weight of modules, hooks and other functions like a submit for forms.&lt;/p&gt;

&lt;hr /&gt;

&lt;!-- /TOC --&gt;
&lt;p&gt;&lt;strong&gt;Table of Contents.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;#1--altering-order-in-submit-functions&quot;&gt;1- Altering order in submit functions&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;#2--altering-the-priority-order-of-modules&quot;&gt;2- Altering the priority order of modules&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;#3--how-to-change-the-registry-of-modules-using-a-hook&quot;&gt;3- How to change the registry of modules using a hook&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;#4--how-to-change-the-registry-of-modules-using-a-contrib-module&quot;&gt;4- How to change the registry of modules using a contrib module&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;#5--wq&quot;&gt;5- :wq!&lt;/a&gt;&lt;br /&gt;
&lt;!-- /TOC --&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;1--altering-order-in-submit-functions&quot;&gt;1- Altering order in submit functions&lt;/h2&gt;

&lt;p&gt;Sometimes, it’s very important for us to alter the order of execution in certain types of submit functions. By instance, we’re using a previously existing form with its existing submit fuction, but we want alter the process by using our own hook. And inside this hook we can define a new submit fuction for the form: We need 1) Add a new submit function and 2) Alter the order and have our submit executed first.&lt;/p&gt;

&lt;p&gt;Let’s see a more specific use case.&lt;/p&gt;
&lt;h3 id=&quot;use-case&quot;&gt;Use Case&lt;/h3&gt;
&lt;p&gt;We have custom changes in one entity (e.g a new field in the menu_link_content entity type) related with a node and loaded when we’re creating a new node by UI in Drupal:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_altering_order_of_execution_in_resources_1.png&quot; alt=&quot;Creating a menu entry when creating a new node in Drupal&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In this case, just when asking for a menu entry wen we’re creating a new node in Drupal we’re always using &lt;a href=&quot;https://api.drupal.org/api/drupal/core%21modules%21menu_link_content%21src%21Entity%21MenuLinkContent.php/class/MenuLinkContent/9.3.x&quot;&gt;the MenuLinkContent entity&lt;/a&gt;. Our change is as follow: We have a new field (a custom check for visibility) in this kind of Entity and we need to load/update the new field just when the node + menu_link_content are created and others modules are working on it (specifically &lt;a href=&quot;https://www.drupal.org/docs/8/core/modules/menu-ui/menu-configuration&quot;&gt;the menu_ui module from Drupal Core&lt;/a&gt;). So we have to pass values for our new field, due to the original hook is not responsible for loading our new field (and it doesn’t know anything about it). So the main idea is &lt;a href=&quot;https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Form%21form.api.php/function/hook_form_alter/9.0.x&quot;&gt;using a form_alter Hook&lt;/a&gt; and then add a new submit callback function just when the node form is saved.&lt;/p&gt;

&lt;p&gt;First I need to create my new submit function in a new custom module. For this step I’ll use the scheme of &lt;a href=&quot;https://api.drupal.org/api/drupal/core%21modules%21menu_ui%21menu_ui.module/function/menu_ui_form_node_form_submit/9.0.x&quot;&gt;the pre-existing function menu_ui_form_node_submit&lt;/a&gt; within &lt;a href=&quot;https://api.drupal.org/api/drupal/core%21modules%21menu_ui%21menu_ui.module/9.0.x&quot;&gt;the menu_ui.module file&lt;/a&gt;. The key step here is: while we’re saving a node, the menu_link_content entity was already created and existing in database register.&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cd&quot;&gt;/**
 * Form submission handler for menu item field on the node form.
 *
 * @see my_custom_module_form_node_form_alter()
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_custom_module_form_node_form_submit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;FormStateInterface&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$form_state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Get the current node information and search the entity in database.&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$node&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$form_state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getFormObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getEntity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$query&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Drupal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;entityQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'menu_link_content'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;condition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'link__uri'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'entity:node/'&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$entity_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$query&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;// Load the existing entity menu_link_content.&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$entity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Drupal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;entityTypeManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getStorage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'menu_link_content'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;array_key_first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$entity_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    
    &lt;span class=&quot;nv&quot;&gt;$entity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;check_visibility&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$form_state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getValues&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'menu'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'profile'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'check_visibility'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$entity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then in my new custom module I’ll create a new form_alter_hook. My goal is open the catalog of actions associated to the required form (node_form) and alter the order in submit callbacks. In order to do this, I’m filtering the type of actions that I’m interested to and then unsetting / setting the items.&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cd&quot;&gt;/**
 * Implements hook_form_BASE_FORM_ID_alter() for \Drupal\node\NodeForm.
 *
 * Adds stuff to the node form.
 *
 * @see my_custom_module_form_node_form_submit()
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_custom_module_form_node_form_alter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FormStateInterface&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$form_state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;  
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;array_keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'actions'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'preview'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'actions'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'#type'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'actions'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'#type'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'submit'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Delete the former last item in the array of submit callbacks.&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;array_pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'actions'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'#submit'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Now load the new order including the new custom submit action.&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'actions'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'#submit'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'my_custom_module_form_node_form_submit'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Reload the former submit function from the original core module menu_ui.&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;$form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'actions'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'#submit'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'menu_ui_form_node_form_submit'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;So, just when I’m saving a new node I’m reviewing the value of my new custom field “check_visibility”, getting from the form_state of the node form and saving the value in the menu_link_content entity. Then the next submit from the core module “menu_ui” goes on to run.&lt;/p&gt;

&lt;h2 id=&quot;2--altering-the-priority-order-of-modules&quot;&gt;2- Altering the priority order of modules&lt;/h2&gt;

&lt;p&gt;In Drupal, the order of execution of a hook is related to the weight assigned to the module that contains it. Each module (custom, contrib, core) has assigned a “weight” value that can be located in the “system” table of the database and in the related configuration file “core.extension.yml” in config/sync/:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;na&quot;&gt;typed_data&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;varnish_purger&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;views_ui&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;workflows&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;pathauto&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;content_translation&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;views&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;paragraphs&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;11&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can set a low weight to get your module to execute after or before others. If no weight is defined modules get a default weight of 0 (the default value for core modules in config).&lt;/p&gt;

&lt;p&gt;To find out the order in which the modules are executed you can get info using the configFactory service, by doing:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$extension_config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Drupal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;configFactory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getEditable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'core.extension'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$module_weight&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$extension_config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;module.MODULE_NAME&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we’re going to set a weight value for our custom module, inside a .install file, from the hook_install(). We can sue an existing function called &lt;a href=&quot;https://api.drupal.org/api/drupal/core%21includes%21module.inc/function/module_set_weight/9.0.x&quot;&gt;‘module_set_weight()’&lt;/a&gt; available within the Drupal API present in module.inc, with functions oriented to interacting with Drupal modules. &lt;a href=&quot;https://api.drupal.org/api/drupal/core%21includes%21module.inc/9.0.x&quot;&gt;See this API here&lt;/a&gt;.&lt;br /&gt;
doing something like this:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cd&quot;&gt;/**
 * Implements hook_install().
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_custom_module_install&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Ensures the hooks contained in your module will be executed after the originals.&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// e.g. the hook menu_ui_form_node_form_alter()&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Note: Weight for uninstalled modules can't be changed. &lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;module_set_weight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'my_custom_module'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Don’t forget update config, passing the active configuration (from database) to the passive configuration (configuration files) in order to have all the config values updated in your Drupal installation:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;drush cex &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;(And don’t forget commit the new changes to the remote repository, of course).&lt;/p&gt;

&lt;h2 id=&quot;3--how-to-change-the-registry-of-modules-using-a-hook&quot;&gt;3- How to change the registry of modules using a Hook&lt;/h2&gt;

&lt;p&gt;As you know, there are a lot de Hooks in Drupal, that is, predefined functions that cause alterations in in the normal operation of the installation, modifying aspects of the Drupal core or other modules. Ok you can check here all &lt;a href=&quot;https://api.drupal.org/api/drupal/core%21core.api.php/group/hooks/9.0.x&quot;&gt;the available Hooks in Drupal 9.x&lt;/a&gt;. Ok but is there any Hook that can be useful for us? Yep, the &lt;a href=&quot;https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Extension%21module.api.php/function/hook_module_implements_alter/9.0.x&quot;&gt;hook_module_implements_alter&lt;/a&gt; that implements just the steps we’ve seen before: pull out of the array the indicated hook for a selected module and then save the same items at the end of the array (just like in the case of the submit functionts in the first section).&lt;/p&gt;

&lt;p&gt;Exactly, this hook is executing:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hook_module_implements_alter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$implementations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$hook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$hook&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'form_alter'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$implementations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'my_custom_module'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;unset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$implementations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'my_custom_module'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$implementations&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'my_custom_module'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This is very useful to specify specifically which hook we want to alter at what time and for which module, locating the module by its name within the array of existing implementations.&lt;/p&gt;

&lt;h2 id=&quot;4--how-to-change-the-registry-of-modules-using-a-contrib-module&quot;&gt;4- How to change the registry of modules using a contrib module&lt;/h2&gt;

&lt;p&gt;There is also a contributed module that acts as a wrapper for this type of functionality but also provides several drush subcommands to execute and manage its features from the command line: &lt;a href=&quot;https://www.drupal.org/project/modules_weight&quot;&gt;The Modules Weight contrib module&lt;/a&gt; can change the order by GUI and by drush commands. Let’s see.&lt;/p&gt;

&lt;p&gt;First, a fast view in my config/sync/core.extension.yml file, with some core modules:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_altering_order_of_execution_in_resources_2.png&quot; alt=&quot;Initial view of the core.extension config file&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now I’m gonna installing and enabling the module in my DDEV deploy for testing:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer require drupal/modules_weight
  
  Using version ^1.9 &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;drupal/modules_weight
  &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;...]

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev drush en &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; modules_weight
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev drush cr
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And now from GUI present in /admin/config/system/modules-weight, I will change the order of the admin_toolbar family modules, as you can see:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_altering_order_of_execution_in_resources_4.png&quot; alt=&quot;Changing values from GUI&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And after saving the page, Now I can see the changes in the same config/sync/core.extension.yml file (after drush cex):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_altering_order_of_execution_in_resources_3.png&quot; alt=&quot;Review the weight changes from the same config file&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I have been testing the set of drush sub-commands provided by the module, but they don’t seem to work on my installed version of Drush (11.0.0 in Drupal 9.3.2) :-(&lt;/p&gt;

&lt;h2 id=&quot;5--wq&quot;&gt;5- :wq!&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_altering_order_of_execution_in_resources_5.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h3 id=&quot;recommended-song-lazy-bones---wooden-shjips&quot;&gt;Recommended song: Lazy Bones - Wooden Shjips&lt;/h3&gt;

&lt;div class=&quot;embed-container&quot;&gt;
    &lt;iframe src=&quot;https://www.youtube.com/embed/VJk-ilqdAYs&quot; width=&quot;700&quot; height=&quot;480&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;
    &lt;/iframe&gt;
  &lt;/div&gt;</content><author><name>davidjguru</name></author><category term="Drupal Tips" /><summary type="html">Picture from Unsplash, user Andre Taissin, @andretaissin Changes, changes, changes… throughout a project, we have to implement many changes and alterations to the Drupal code, without touching it directly -of course-. The event system is very powerful but there are still hooks at all levels, so sometimes we must use Hooks that will alter things already modified by other Hooks of the same nature. Also we may need to execute our changes before the changes made by another module (contrib or custom), and for that we must understand well how the order of execution of resources works…</summary></entry><entry><title type="html">Drupal Techniques: How to upgrade Drupal</title><link href="https://davidjguru.github.io//blog/drupal-techniques-how-to-upgrade-drupal" rel="alternate" type="text/html" title="Drupal Techniques: How to upgrade Drupal" /><published>2021-09-29T00:00:00+00:00</published><updated>2021-09-29T00:00:00+00:00</updated><id>https://davidjguru.github.io//blog/drupal-techniques-how-to-upgrade-drupal</id><content type="html" xml:base="https://davidjguru.github.io//blog/drupal-techniques-how-to-upgrade-drupal">&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_how_to_upgrade_to_d9_main.png&quot; alt=&quot;Picture from Unsplash, by @saddy143&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Picture from Unsplash, user &lt;a href=&quot;https://unsplash.com/@calypso999&quot;&gt;Raul Varzar, @calypso999&lt;/a&gt;&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;As you may have heard, the End Of Life for Drupal 8 is near. This is closing fast, very fast now. In fact the date for Drupal 8 EOL is November 2nd 2021, aligning this transition with the same EOL for one of the most important dependencies and key components: Symfony 3. Yep, the last minor version available for Symfony 3 (3.4) has marked like end for bug fixes and security fixes november 2021. As a rule, supported versions of Drupal must use supported version of Symfony, so this is the end unless you perform and upgrade in your Drupal platform…&lt;br /&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A few days ago I had to work on a upgrade to Drupal 9 and along the way&lt;/strong&gt;, I’ve taken some useful notes about the process. After publishing a quick guide for internal consumption  I’ve decided to write a more extended version with all the issues. Since enough articles with &lt;a href=&quot;https://en.wikipedia.org/wiki/Fear,_uncertainty,_and_doubt&quot;&gt;FUD&lt;/a&gt; have already been published about the necessary Drupal upgrade, I won’t dwell on the risks or in potential problems: There are less than eight weeks left until Drupal 8 community support development stops and there is little time if you want to focus on Drupal 9 upgrades with your team. &lt;strong&gt;Read this article, review its steps, make your own checklist and get started!&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;acknowledgments&quot;&gt;&lt;strong&gt;Acknowledgments&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;This post was composed from my current position as Senior Drupal Developer at &lt;a href=&quot;https://www.digitalist.se/english&quot;&gt;Digitalist Sweden&lt;/a&gt;, one of the biggest companies oriented to Open Source in Europe and specifically focused in Drupal.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_how_to_upgrade_to_d9_2.png&quot; alt=&quot;Drupal 7, 8 and 9 timeline about lifecycle&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Image taken from &lt;a href=&quot;https://www.drupal.org/blog/how-to-prepare-for-drupal-9&quot;&gt;drupal.org/how-to-prepare-for-drupal-9&lt;/a&gt;&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;In addition, there are a couple of premises or prerequisites that we must satisfy, just like a pair or assumptions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Assumption 1:&lt;/strong&gt; We’re working in a Drupal 8 installation now or in a Drupal major version &amp;gt; 7 (Drupal 9 to Drupal 10 maybe).
This is not an article about Drupal Migrations, so I’m not covering a Drupal 7 to Drupal 9 migration and upgrading (a more extensive, complex and exhaustive process due to the huge structural difference in the jump between Drupal 7 and Drupal 8), so this post is for Drupal &amp;gt; 7 installations, sorry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Assumption 2:&lt;/strong&gt; Your Drupal  installation is under the control of Composer as dependency manager.
I’m quite aware that there are still projects that don’t use Composer as a main dependency manager and also -as in Allen Ginsberg’s poem: Howl poem- &lt;a href=&quot;https://www.poetryfoundation.org/poems/49303/howl&quot;&gt;“I saw the best minds of my generation destroyed by madness”&lt;/a&gt;. But you need composerizate your project (that is, put it under Composer management). This article is for Drupal 8 installations using Composer.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; -&amp;gt; This is a post about how to execute (steps, tips, risks…) the upgrading process from major versions of Drupal (D8 to D9, D9 to D10, etc.).&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;If you want to learn how to execute Drupal upgrading reading resources from external sources, I have a Gist in Github with my favourite content, &lt;a href=&quot;https://gist.github.com/davidjguru/43212057fea0f8135899ee9b10ebfab2&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;If you came here looking for information about Drupal updates for minor versions (Drupal 9.2.6 -&amp;gt; 9.2.7 -&amp;gt; 9.2.8), better visit &lt;a href=&quot;https://gitlab.com/-/snippets/2203466&quot;&gt;this snippet I have in Gitlab with related information&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;If you want to have a quick overview, download the image below and zoom in to see the recommended steps.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;
&lt;p&gt;See the image below:&lt;br /&gt;
&lt;img src=&quot;/images/davidjguru_drupal_8_9_how_to_upgrade_between_mayor_versions_of_drupal.png&quot; alt=&quot;How to upgrade between major verions of Drupal&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;
&lt;!-- /TOC --&gt;
&lt;p&gt;&lt;strong&gt;Table of Contents.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;#1--setting-the-scenario&quot;&gt;1- Setting the scenario&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;#2--sorting-the-toolbox&quot;&gt;2- Sorting the toolbox&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;#3--assesing-the-status-of-your-project&quot;&gt;3- Assesing the status of your project&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;#4--preparing-the-work&quot;&gt;4- Preparing the work&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;#5--executing-the-upgrade&quot;&gt;5- Executing the work&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;#6--troubleshooting&quot;&gt;6- Troubleshooting&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;#7--read-more&quot;&gt;7- Read More&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;#8--wq&quot;&gt;8- :wq!&lt;/a&gt;&lt;br /&gt;
&lt;!-- /TOC --&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;1--setting-the-scenario&quot;&gt;1- Setting the scenario&lt;/h2&gt;

&lt;p&gt;As a first step we need to select our Drupal installation on which we have to perform the upgrade.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GOAL:&lt;/strong&gt; Have an enabled Drupal setup.&lt;/p&gt;

&lt;p&gt;I’m going to deploy in my local environment a new Drupal 8 site for testing updates to Drupal 9. I will call it “drupal8function”, with an user “admin” and password “admin”, using &lt;a href=&quot;https://ddev.readthedocs.io/en/stable/&quot;&gt;DDEV&lt;/a&gt; as deployment tool, as I wrote down here in this &lt;a href=&quot;https://gitlab.com/-/snippets/2012512&quot;&gt;gitlab snippet&lt;/a&gt;, just by typing the next commands in prompt:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;drupal8function &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;drupal8function
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev config &lt;span class=&quot;nt&quot;&gt;--project-type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;drupal8 &lt;span class=&quot;nt&quot;&gt;--docroot&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;web &lt;span class=&quot;nt&quot;&gt;--create-docroot&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;yes&lt;/span&gt; | ddev composer create &lt;span class=&quot;s2&quot;&gt;&quot;drupal/recommended-project:^8&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer require drush/drush drupal/admin_toolbar drupal/devel
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev &lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;drush si &lt;span class=&quot;nt&quot;&gt;--site-name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;drupal8function &lt;span class=&quot;nt&quot;&gt;--account-name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;admin &lt;span class=&quot;nt&quot;&gt;--account-pass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;admin &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev drush en &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; admin_toolbar devel
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev drush cr
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev start &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; ddev launch
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;I need some custom resources for testing so I’ll clone some Drupal 8 modules that &lt;a href=&quot;https://gitlab.com/davidjguru/drupal-custom-modules-examples&quot;&gt;I have in my Gitlab repository&lt;/a&gt;. My idea is taking some modules in a Drupal 8 version and then moving to my /custom folder enabling it by drush, so I’ll have Drupal 8 custom resources ready to review for the upgrade to Drupal 9. Let’s see some D8 modules:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone https://gitlab.com/davidjguru/drupal-custom-modules-examples.git
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; ./web/modules/custom
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mv &lt;/span&gt;drupal-custom-modules-examples/links_example ./web/modules/custom/
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mv &lt;/span&gt;drupal-custom-modules-examples/headers_manager/ ./web/modules/custom/
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mv &lt;/span&gt;drupal-custom-modules-examples/Migrations/migration_basic_module/ ./web/modules/custom/
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev drush en &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; links_example headers_manager migration_basic_module
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev drush
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Also, I’ve added some patches for Drupal 8 core modules, by adding some links in composer.json files:&lt;/p&gt;
&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;&quot;patches&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;drupal/core&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Content_entity, config_entity Plugins&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://www.drupal.org/files/issues/2020-09-24/3172853-2.patch&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;AccessAwareRouter HTTP method.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://www.drupal.org/files/issues/2018-12-12/2706241-34.patch&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Sets langcode.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://www.drupal.org/files/issues/2020-06-10/locale-config-langcodes.patch&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Layout builder assign inline block access.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://www.drupal.org/files/issues/2021-03-22/3047022-71.patch&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Generate pathauto aliases.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://www.drupal.org/files/issues/2020-11-06/3181070-possible-need-to-change-the-way-menulinkmanager-updates-menu-item-and-menu-tree.patch&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Ok, &lt;strong&gt;now I have a semi-real scenario composed by a Drupal 8 core, patches, some contrib modules and custom resources in Drupal 8 too&lt;/strong&gt;. So when I ask for the Drupal core version to Composer, I’m getting:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_how_to_upgrade_to_d9_1.png&quot; alt=&quot;How to upgrade to Drupal 9 one&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The next step will be Preparing the toolbox.&lt;/p&gt;

&lt;h2 id=&quot;2--sorting-the-toolbox&quot;&gt;2- Sorting the toolbox&lt;/h2&gt;

&lt;p&gt;First of all I think we need to prepare a toolbox with some basic utilities for our upgrading plan.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GOAL:&lt;/strong&gt; Have a set of well-know and tested tools.&lt;/p&gt;

&lt;p&gt;I have selected here only five basic resources, very easy to use. These are the following items:&lt;/p&gt;

&lt;h3 id=&quot;21--upgrade_status&quot;&gt;2.1- upgrade_status&lt;/h3&gt;

&lt;p&gt;Before studying and designing the process for update your Drupal installation, maybe you need a high-level view, a fast summary about what is the current status in your platform. &lt;a href=&quot;https://www.drupal.org/project/upgrade_status&quot;&gt;The contrib module “Upgrade Status”&lt;/a&gt; can provide you a fast review about this and it provides you with some solutions and tips too.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer require drupal/upgrade_status
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev drush en &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; upgrade_status
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev drush cr
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;(Avoid using the command ddev if you are not using DDEV, of course. Or change by lando command.)&lt;/p&gt;

&lt;p&gt;And if you don’t want touch your Drupal core, ask for dev versions for core and dependencies getting first your current core version in terminal:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer show drupal/core | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;versions
versions : &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; 8.9.18

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer require &lt;span class=&quot;nt&quot;&gt;--dev&lt;/span&gt; drupal/core-dev:8.9.18 &lt;span class=&quot;nt&quot;&gt;--update-with-all-dependencies&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer require drupal/upgrade_status
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev drush &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; upgrade_status
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev drush cr
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Once installed and enabled, this module will offer you a GUI and a pair of new drush subcommands in order to get the reports. We’ll see the results in a next section.&lt;/p&gt;

&lt;h3 id=&quot;22--php-stan&quot;&gt;2.2- php-stan&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://phpstan.org/user-guide/getting-started&quot;&gt;PHPStan&lt;/a&gt; is a PHP Static Analysis Tool created by &lt;a href=&quot;https://github.com/ondrejmirtes&quot;&gt;Ondřej Mirtes&lt;/a&gt; and others that combined with a set of custom rules for Drupal can do the job reviewing the status of your code. First, We have to install all the resources:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer require  &lt;span class=&quot;nt&quot;&gt;--dev&lt;/span&gt; phpstan/phpstan &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  phpstan/extension-installer &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  mglaman/phpstan-drupal &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  phpstan/phpstan-deprecation-rules
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The phpstan/extension.-installer will autoconfigure PHPStan to load phpstan-drupal and the deprecation-rules, the resource that will delivery the reports about using deprecated code in your installation and resources.&lt;/p&gt;

&lt;p&gt;Then we can run phpstan against the selected resources by doing something like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ddev php vendor/bin/phpstan.phar analyze web/modules/custom/my_custom_module
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And you can change the level for the review, from 0 (the loosest) to 8 (the strictest), passing the parameter -l to the command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ddev php vendor/bin/phpstan -l 4 analyze web/modules/custom/my_custom_module
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;23--drupal-check&quot;&gt;2.3- drupal-check&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/mglaman/drupal-check&quot;&gt;Drupal Check is a static analysis tool&lt;/a&gt; developed by &lt;a href=&quot;https://github.com/mglaman&quot;&gt;Matt Glaman&lt;/a&gt; based in &lt;a href=&quot;https://phpstan.org/&quot;&gt;PHPStan&lt;/a&gt;, a very useful resource for these updating processes, allowing us to search for deprecated code in our resources, errors and some more interesting information. You can use it as a new Composer dependency or &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=bbeversdorf.drupal-check&quot;&gt;as VSCode extension&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We’re going to install the tool through Composer, by doing:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer require mglaman/drupal-check &lt;span class=&quot;nt&quot;&gt;--dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And we’ll have available a new command from prompt: ‘drupal-check’. We’ll cover the use in a next section.&lt;/p&gt;

&lt;h3 id=&quot;24--drupal-rector&quot;&gt;2.4- drupal-rector&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/palantirnet/drupal-rector&quot;&gt;Drupal Rector is a fixing deprecated code tool&lt;/a&gt; for Drupal, built by &lt;a href=&quot;https://www.palantir.net/&quot;&gt;Palantir&lt;/a&gt; and available as a Composer dependency. It can inspect, proposing and apply patches for changes in your software from its code reviews.&lt;/p&gt;

&lt;h3 id=&quot;25--backward_compatibility&quot;&gt;2.5- backward_compatibility&lt;/h3&gt;

&lt;p&gt;This &lt;a href=&quot;https://www.drupal.org/project/backward_compatibility&quot;&gt;is a little contrib module&lt;/a&gt; oriented to simple cases: there are a lot of contrib modules in Drupal that only requires add a single line in its module.info.yml file, I mean:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;core_version_requirement: ^8 || ^9
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Well, instead of patching every contrib module with this problem, just install the resource and it will work’round the Issue. Just by doing:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ composer require drupal/backward_compatibility
$ drush en -y backward_compatibility
$ drush cr
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And nothing more! (simple solutions for very specific use cases).&lt;/p&gt;

&lt;h2 id=&quot;3--assesing-the-status-of-your-project&quot;&gt;3- Assesing the status of your project&lt;/h2&gt;

&lt;p&gt;Now It’s time to get a reliable image of the status of our project through the tools selected in the former section.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GOAL:&lt;/strong&gt; Have a true picture of the work to be done.&lt;/p&gt;

&lt;p&gt;It will be no secret to say that our field of work in this updating process will be mainly in the custom zone of our resources: We will dedicate a large percentage of time to the adaptaion of our custom modules, our custom themes and our patches applied to the project that are in local folders and not in Drupal.org (which is another category of custom work for us).&lt;/p&gt;

&lt;h3 id=&quot;31--taking-a-snapshot-of-your-platform&quot;&gt;3.1- Taking a snapshot of your platform&lt;/h3&gt;

&lt;p&gt;Before we can estimate how much time we will spend and how many actions we need to implement, let’s do some initial data collection and prepare some resources. This will give us a useful snapshot of the status of our platform.&lt;/p&gt;

&lt;p&gt;Ok, first you have to review the current status of your local deploy. Remember that your installation has five pillars, five main columns:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Composer files: composer.json and composer.lock&lt;/li&gt;
  &lt;li&gt;Config Files, usually in /config/sync/&lt;/li&gt;
  &lt;li&gt;The files folder, usually in /web/sites/default/files/&lt;/li&gt;
  &lt;li&gt;The database of your Drupal installation&lt;/li&gt;
  &lt;li&gt;All your custom work: custom modules, custom themes and (maybe) custom patches.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Put all the above resources in a safe place of your choice.&lt;/p&gt;

&lt;p&gt;Remember that if you did your homework and assignments right, then the alignment between “Active Configuration” (database) and “Passive Configuration” (configuration files) will be complete, I mean:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev drush cex
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;notice] The active configuration is identical to the configuration &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;the &lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;directory &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;sites/default/files/sync&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
sites/default/files/sync

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev drush cim
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;notice] There are no changes to import.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And there will be no change to identify. Otherwise, you should always prioritize the active database configuration as an up-to-date reference of the state of your Drupal installation.&lt;/p&gt;

&lt;h2 id=&quot;some-steps&quot;&gt;Some Steps:&lt;/h2&gt;
&lt;ol&gt;
  &lt;li&gt;Preparing your containers and backups&lt;/li&gt;
  &lt;li&gt;Check your current version for Drupal Core&lt;/li&gt;
  &lt;li&gt;Enable the upgrade_status module and check results&lt;/li&gt;
  &lt;li&gt;Check code with drupal-checker and drupal-rector&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;32--containers-and-backups&quot;&gt;3.2- Containers and Backups&lt;/h3&gt;

&lt;p&gt;It’s time to review some special configurations and values in your environments…what versions of Nginx, Apache, MySQL, Postgres or MariaDB you have? check the current versions in your environments, containers, etc.&lt;/p&gt;

&lt;h3 id=&quot;33--current-version-for-drupal-core&quot;&gt;3.3- Current version for Drupal Core&lt;/h3&gt;

&lt;p&gt;Let’s confirm our core version by typing in prompt:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer show drupal/core | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;versions
versions : &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; 8.9.18
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;34--upgrade-status&quot;&gt;3.4- Upgrade Status&lt;/h3&gt;

&lt;p&gt;After enabling the upgrade_status module, we’ll inspect the current status of our installation accesing to /admin/reports/upgrade-status and seeing the first information area of the status report:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_how_to_upgrade_to_d9_3.png&quot; alt=&quot;Upgrade Status fist region&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Here you can see the general review of your resources, custom and contrib, and seeing the changes to do, you will be able to estimate the amount of time you will need to dedicate to these updates,, about the hosting, core and environment:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_how_to_upgrade_to_d9_5.png&quot; alt=&quot;Requirements in core and hosting&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Or by seeing the specific modules:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_how_to_upgrade_to_d9_6.png&quot; alt=&quot;Changes required in modules&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We can use the new Drush commands provided by the module to explore some specific modules, doing:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev drush upgrade_status:analyze admin_toolbar
 &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;notice] Processing /var/www/html/web/modules/contrib/admin_toolbar.

&lt;span class=&quot;o&quot;&gt;================================================================================&lt;/span&gt;
Admin Toolbar,  3.0.2
Scanned on Mon, 09/20/2021 - 17:15

FILE:
web/modules/contrib/admin_toolbar/admin_toolbar_search/src/Controller/AdminToolb
arSearchController.php

STATUS         LINE                           MESSAGE                           
&lt;span class=&quot;nt&quot;&gt;--------------------------------------------------------------------------------&lt;/span&gt;
Check manually 15   Class PHPUnit&lt;span class=&quot;se&quot;&gt;\F&lt;/span&gt;ramework&lt;span class=&quot;se&quot;&gt;\T&lt;/span&gt;estCase not found.                 
&lt;span class=&quot;nt&quot;&gt;--------------------------------------------------------------------------------&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;...]

&lt;span class=&quot;nt&quot;&gt;--------------------------------------------------------------------------------&lt;/span&gt;

This module is ready &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;Drupal 9.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;35--drupal-checker-and-drupal-rector&quot;&gt;3.5- Drupal-Checker and Drupal-Rector&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;drupal-check &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; web/modules/contrib/admin_toolbar
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Install by doing:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer require &lt;span class=&quot;nt&quot;&gt;--dev&lt;/span&gt; palantirnet/drupal-rector
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can give to Drupal Rector a GUI from your Drupal installation:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer require &lt;span class=&quot;s1&quot;&gt;'drupal/upgrade_rector:^1.0@alpha'&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev drush en &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; upgrade_rector
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev drush cr
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And then go to /admin/reports/upgrade-rector and see the reviews available for contrib and custom resources:&lt;/p&gt;

&lt;h3 id=&quot;36--get-a-list-of-deprecated-resources&quot;&gt;3.6- Get a list of deprecated resources&lt;/h3&gt;

&lt;p&gt;You can check the current status of all your dependencies, getting a report with related information from Composer. Just run:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer outdated
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And you will get:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
alchemy/zippy                            0.4.9    1.0.0   Zippy, the archive manager companion
asm89/stack-cors                         1.3.0    v2.1.1  Cross-origin resource sharing library and stack middleware
chi-teck/drupal-code-generator           1.33.1   2.5.1   Drupal code generator
composer/composer                        2.2.6    2.2.9   Composer helps you &lt;span class=&quot;nb&quot;&gt;declare&lt;/span&gt;, manage and &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;dependencies of PHP projects. It ensures you have the right stack everywhere.
composer/installers                      v1.12.0  v2.1.0  A multi-framework Composer library installer
composer/pcre                            1.0.1    3.0.0   PCRE wrapping library that offers type-safe preg_&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; replacements.
composer/semver                          3.2.6    3.3.1   Semver library that offers utilities, version constraint parsing and validation.
composer/xdebug-handler                  2.0.4    3.0.3   Restarts a process without Xdebug.
consolidation/annotated-command          4.3.2    4.5.2   Initialize Symfony Console commands from annotated &lt;span class=&quot;nb&quot;&gt;command &lt;/span&gt;class methods.
consolidation/config                     1.2.1    2.1.0   Pr

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;...]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Now you have a little overview about all the pending tasks for upgrading all in your Drupal installation.&lt;/p&gt;
&lt;h2 id=&quot;4--preparing-the-work&quot;&gt;4- Preparing the work&lt;/h2&gt;

&lt;p&gt;Somebody, somewhere - maybe yourself - needs to know what needs to be done, risks we run and how much time / effort the upgrade needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GOAL:&lt;/strong&gt; Haver a reliable estimation of the process.&lt;/p&gt;

&lt;p&gt;Ok, after putting in a safe place a copy of the five basic parts of your installation (config, database dump, files folder, composer files and all your custom works -themes, modules, patches, etc. and after checking the state for update, you’ll be able to build a map with all the required tasks related with the update, I mean:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;List of resources that only requires basic and fast changes:&lt;/strong&gt; the quickest and easiest bet to execute. Small and perhaps repetitive changes that you might be able to run the same way in the same bash script or through the same Git patch.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;List of resources that contains deprecated code:&lt;/strong&gt; If you have ignored successive warnings and code deprecation warnings since previous versions (don’t be like me), you may need time to make adjustments to this part. Check the warnings thoroughly now.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;List of resources that requires refactoring or advanced changes:&lt;/strong&gt; Perhaps one of the most complex parts. You may take time to balance this part according to the latest changes in core and contributed modules, to adapt your own functionality in custom modules and to rewrite code. Be cautious and value well this estimation.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;List of items to update in environments (versions for PHP, MariaDB and other containers stuff):&lt;/strong&gt; A part that tends to be overlooked but someone will take care of executing… Do our current Docker images work? are our containers up to date? do they require a higher version of a resource? don’t forget this section.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After reviewing all this and compiling all the information provided by the tools discussed above as output, you can now think about what’s left, what output can we expect, you can combine all your estimates and build a tracking document of all the tasks associated with the upgrade. I use something like this, something primary but very useful as a checklist:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_how_to_upgrade_to_d9_8.png&quot; alt=&quot;Filling a worksheet for the Drupal 9 upgrading&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;5--executing-the-upgrade&quot;&gt;5- Executing the upgrade&lt;/h2&gt;

&lt;p&gt;The time has come to make the necessary changes and adjustments.  Let’s go!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GOAL:&lt;/strong&gt; Have an experienced process (trial, error, trial, error…)&lt;/p&gt;

&lt;h3 id=&quot;51--remove-some-resources&quot;&gt;5.1- Remove some resources&lt;/h3&gt;

&lt;p&gt;Remove drupal/console: (usually causes problems with symfony dependencies), so If you have installed drupal console, remove it as first step.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ddev composer remove drupal/console
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, remove drupal/core and/or drupal/core-recommended from composer.json. Look for drupal/core-recommended or drupal/core in composer.json and &lt;strong&gt;remove the line(s)&lt;/strong&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;drupal/core-recommended&quot;: &quot;^8.9.0&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you have drush and devel, which are widely used, also manually edit the versions:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;drupal/devel&quot;: &quot;^4.0&quot;,
&quot;drush/drush&quot;: &quot;^10.0.0&quot;,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then run composer update again:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ddev composer update
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will remove drupal core from your installation but will update the contrib resources.&lt;/p&gt;

&lt;h3 id=&quot;52--set-your-new-drupal-core-version&quot;&gt;5.2- Set your new Drupal Core version&lt;/h3&gt;

&lt;p&gt;Add drupal/core-recommended:9.0.0 to composer.json&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;drupal/core-recommended&quot;: &quot;9.0.0&quot;,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now run composer update one more time:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ddev composer update
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;53--delete-modules-with-problems&quot;&gt;5.3- Delete modules with problems&lt;/h3&gt;

&lt;p&gt;In my case, During the last tasks of upgrading projects to Drupal 9, I have some problems with a specific &lt;a href=&quot;https://www.drupal.org/project/multivalue_form_element&quot;&gt;contrib module: multivalue_form_element&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Problem 1
- Conclusion: remove drupal/core-recommended 9.0.0
- Conclusion: don&lt;span class=&quot;s1&quot;&gt;'t install drupal/core-recommended 9.0.0
- Conclusion: don'&lt;/span&gt;t &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;drupal/multivalue_form_element 1.0.0-beta2|don&lt;span class=&quot;s1&quot;&gt;'t install
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Why?&lt;/strong&gt; Well the module seems to be available only from Drupal 9.1:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_how_to_upgrade_to_d9_4.png&quot; alt=&quot;Multivalue Form Element Module Page&quot; /&gt;&lt;/p&gt;

&lt;p&gt;When deleting this module from composer.json, run  composer update and now You will have the new core version (9.0.0) installed. We will back to this module in next steps.&lt;/p&gt;

&lt;h3 id=&quot;54--upgrade-to-latest-drupal-9-version&quot;&gt;5.4- Upgrade to latest Drupal 9 version&lt;/h3&gt;

&lt;p&gt;After this, change your drupal/core-recommended line in composer.json to:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;drupal/core-recommended&quot;: &quot;^9.0.0&quot;,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And re-run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;composer update&lt;/code&gt; .&lt;/p&gt;

&lt;h3 id=&quot;55--update-patches&quot;&gt;5.5- Update patches&lt;/h3&gt;

&lt;p&gt;Sure you have some patches applied to your Drupal Core from the composer.json file. I have, for example these, mixin’ contrib from drupal.org and custom from a local folder within the project:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s2&quot;&gt;&quot;drupal/core&quot;&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;&quot;Add content_entity and config_entity DataType plugins (https://www.drupal.org/project/drupal/issues/3172853)&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;https://www.drupal.org/files/issues/2020-09-24/3172853-2.patch&quot;&lt;/span&gt;,
&lt;span class=&quot;s2&quot;&gt;&quot;AccessAwareRouter does not respect HTTP method (https://www.drupal.org/project/drupal/issues/2706241)&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;https://www.drupal.org/files/issues/2018-12-12/2706241-34.patch&quot;&lt;/span&gt;,
&lt;span class=&quot;s2&quot;&gt;&quot;Claro removes contextual links for inline blocks translate - only needed when using claro in layout builder&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;./patches/claro-preprocess-contextual.patch&quot;&lt;/span&gt;,
&lt;span class=&quot;s2&quot;&gt;&quot;Sets the langcode for config export to en&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;https://www.drupal.org/files/issues/2020-06-10/locale-config-langcodes.patch&quot;&lt;/span&gt;,
&lt;span class=&quot;s2&quot;&gt;&quot;Layout builder fails to assign inline block access dependencies for the overrides section storage on entities with pending revisions.&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;https://www.drupal.org/files/issues/2020-09-10/3047022-43.patch&quot;&lt;/span&gt;,
&lt;span class=&quot;s2&quot;&gt;&quot;Generate pathauto aliases when rearranging menu.&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;https://www.drupal.org/files/issues/2020-11-06/3181070-possible-need-to-change-the-way-menulinkmanager-updates-menu-item-and-menu-tree.patch&quot;&lt;/span&gt;,
&lt;span class=&quot;s2&quot;&gt;&quot;Remove entity constraint validator for inline blocks&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;./patches/3053881-30-reroll-8.x.patch&quot;&lt;/span&gt;,
&lt;span class=&quot;s2&quot;&gt;&quot;Replace token module internal link to nodes with a entity link&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;./patches/menu_ui-token-uuid-to-id.patch&quot;&lt;/span&gt;,
&lt;span class=&quot;s2&quot;&gt;&quot;Drupal dialog respect drupalAutoButtons: false&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;./patches/drupal-dialog-respect-drupalautobuttons.patch&quot;&lt;/span&gt;,
&lt;span class=&quot;s2&quot;&gt;&quot;Make drupalAutoButtons a boolean&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;./patches/OpenDialogCommand-drupalAutoButtons-boolean.patch&quot;&lt;/span&gt;,
&lt;span class=&quot;s2&quot;&gt;&quot;Tabledrag nested stuff.&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;https://www.drupal.org/files/issues/2020-12-08/3092181-142-8X_0.patch&quot;&lt;/span&gt;,
&lt;span class=&quot;s2&quot;&gt;&quot;Error in computed image fields (width, height) when saving nodes&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;https://www.drupal.org/files/issues/2019-02-11/ignore_width_height_on_untranslatable_field_comparision_2941092_8.patch&quot;&lt;/span&gt;,
&lt;span class=&quot;s2&quot;&gt;&quot;Vary block definitions on language&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;./patches/block-manager-cache-key.patch&quot;&lt;/span&gt;,
&lt;span class=&quot;s2&quot;&gt;&quot;Expose resetSize from dialog position to the Drupal object&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;./patches/expose-reset-size-to-drupal-object.patch&quot;&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So when I’m trying update my Drupal core I’m getting these errors:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Could not apply patch! 
  Skipping. The error was: Cannot apply patch 
    https://www.drupal.org/files/issues/2020-09-10/3047022-43.patch
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;...]
Could not apply patch! 
  Skipping. The error was: Cannot apply patch ./patches/drupal-dialog-respect-drupalautobuttons.patch
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;...]
Could not apply patch! 
  Skipping. The error was: Cannot apply patch 
  https://www.drupal.org/files/issues/2020-12-08/3092181-142-8X_0.patch

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;As you can see, &lt;strong&gt;I’m having problems with three patches for Drupal Core&lt;/strong&gt;. Ok, so here we have to do some manual work…We have to check for every patch:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;If the patch was already applied to the 9.x development branch, so It’s not necesary to apply now in the upgrade.&lt;/li&gt;
  &lt;li&gt;If the patch was not applied, then you have to look for a new re-rolled patch ready for the new version of Drupal (&amp;gt; 9.x.x.).&lt;/li&gt;
  &lt;li&gt;If the patch doesn’t come from &lt;a href=&quot;http://drupal.org&quot;&gt;drupal.org&lt;/a&gt; and it’s a custom solution located in /patches directory, then you’ll have to work in the migration of the resource, re-rolling the patch. :-/&lt;/li&gt;
  &lt;li&gt;If the patch has not been applied and there is no version for Drupal 9 either, so you have to talk with your team, including your scrum master and / or Product Owner. The original problem will come back to the Drupal installation until you or somebody in the Drupal community can port the patch to Drupal 9. Sorry :-/&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And looking the original Issues, I can see &lt;a href=&quot;https://www.drupal.org/project/drupal/issues/3047022&quot;&gt;versions for Drupal 9.2, as here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I found &lt;a href=&quot;https://www.drupal.org/files/issues/2021-03-22/3047022-71.patch&quot;&gt;a solution for Drupal 9 here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Or there:&lt;br /&gt;
&lt;a href=&quot;https://www.drupal.org/project/drupal/issues/3092181&quot;&gt;www.drupal.org/issues/3092181&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://www.drupal.org/project/drupal/issues/3092181#comment-14170867&quot;&gt;Seems to be resolved from Drupal 9.2&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My third patch with problems is a local custom patch in /patches folder, so I have to do some coding review here  :-/&lt;/p&gt;

&lt;h3 id=&quot;56--reinstall-modules-with-issues&quot;&gt;5.6- Reinstall modules with Issues&lt;/h3&gt;

&lt;p&gt;After install the updated core, upgrading to the latest version available and working with patches, now can request the problematic modules, like the multivalue_form_element:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer require drupal/multivalue_form_element
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Remember that you can avoid problems pre-testing the installation of dependencies in Composer by using:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;57--run-updates-in-database&quot;&gt;5.7- Run updates in database&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Not run the database updates before install the modules with issues: You can have the module saved as active in database but the codebase doesn’t exist, due to this you’ll get a lot of problems. Remember: first update core, then install modules with issues and after all, launch the database updates.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev drush updb &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev drush cr
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;58--review-all-your-custom-work&quot;&gt;5.8- Review all your custom work&lt;/h3&gt;

&lt;p&gt;You can use the well-formed tools commented in the section about tooling, doing so:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer require mglaman/drupal-check &lt;span class=&quot;nt&quot;&gt;--dev&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev drupal-check &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; web/modules/custom
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;59--checking-new-installed-versions&quot;&gt;5.9- Checking new installed versions&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;name     : drupal/smtp
descrip. : Allow &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;site emails to be sent through an SMTP server of your choice.
keywords : 
versions : &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; 1.0.0
&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;     : drupal-module
license  : GNU General Public License v2.0 or later &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;GPL-2.0-or-later&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;OSI approved&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; https://spdx.org/licenses/GPL-2.0-or-later.html#licenseText
homepage : https://www.drupal.org/project/smtp
&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt;   : &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;git] https://git.drupalcode.org/project/smtp.git 8.x-1.0
dist     : &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;zip] https://ftp.drupal.org/files/projects/smtp-8.x-1.0.zip 8.x-1.0
path     : /app/backend/web/modules/contrib/smtp
names    : drupal/smtp

support
&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; : https://git.drupalcode.org/project/smtp
issues : https://www.drupal.org/project/issues/smtp

&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;requires
drupal/core ^8.8 &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; ^9&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;
phpmailer/phpmailer ^6.1.7
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Or:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer show drupal/pathauto
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Getting:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;name     : drupal/pathauto
descrip. : Provides a mechanism &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;modules to automatically generate aliases &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;the content they manage.
keywords : 
versions : &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; 1.8.0
&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;     : drupal-module
license  : GNU General Public License v2.0 or later &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;GPL-2.0-or-later&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;OSI approved&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; https://spdx.org/licenses/GPL-2.0-or-later.html#licenseText
homepage : https://www.drupal.org/project/pathauto
&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt;   : &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;git] https://git.drupalcode.org/project/pathauto.git 8.x-1.8
dist     : &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;zip] https://ftp.drupal.org/files/projects/pathauto-8.x-1.8.zip 8.x-1.8
path     : /app/backend/web/modules/contrib/pathauto
names    : drupal/pathauto

support
&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; : https://cgit.drupalcode.org/pathauto
issues : https://www.drupal.org/project/issues/pathauto
documentation : https://www.drupal.org/docs/8/modules/pathauto

&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;requires
drupal/core ^8.8 &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; ^9&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;
drupal/ctools &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
drupal/token &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer show drupal/core

name     : drupal/core
descrip. : Drupal is an open &lt;span class=&quot;nb&quot;&gt;source &lt;/span&gt;content management platform powering millions of websites and applications.
keywords : 
&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;versions : &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; 9.2.5&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;     : drupal-core
license  : GNU General Public License v2.0 or later &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;GPL-2.0-or-later&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;OSI approved&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;510--remove-tooling-for-upgrade&quot;&gt;5.10- Remove tooling for upgrade&lt;/h3&gt;

&lt;p&gt;Remove the upgrade_status contrib module or the extra resources by typing:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev drush pmu &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; upgrade_status
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer remove drupal/upgrade_status
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev drush cr

&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer remove mglaman/drupal-check &lt;span class=&quot;nt&quot;&gt;--dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;511--commit-files-with-changes&quot;&gt;5.11- Commit files with changes&lt;/h3&gt;

&lt;p&gt;You will have to commit to repository the new versions of your  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;composer.json&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;composer.lock&lt;/code&gt; files, in order to get the new versions in the next deploys for environments.&lt;/p&gt;

&lt;h2 id=&quot;6--troubleshooting&quot;&gt;6- Troubleshooting&lt;/h2&gt;

&lt;p&gt;Maybe it’s not your last update or a colleague needs help: make your experience a validated learning experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GOAL:&lt;/strong&gt; Have a reusable set of problems and solutions.&lt;/p&gt;

&lt;p&gt;Here I would like to gather some problems and limitations observed in various Drupal 9 upgrade tasks.&lt;/p&gt;

&lt;h3 id=&quot;61--graphql-is-giving-me-some-errors&quot;&gt;6.1- GraphQL is giving me some errors&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;For Drupal 9, GraphQL module has a dependency in alpha version, which can crash with your Drupal 9 installation: the &lt;strong&gt;drupal/typed_data&lt;/strong&gt; module (&lt;a href=&quot;https://www.drupal.org/project/typed_data&quot;&gt;https://www.drupal.org/project/typed_data&lt;/a&gt;):&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Your requirements could not be resolved to an installable &lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;of packages.

  Problem 1
    - Root composer.json requires drupal/graphql ^4.1 -&amp;gt; satisfiable by drupal/graphql[4.1.0].
    - drupal/graphql 4.1.0 requires drupal/typed_data &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; -&amp;gt; found drupal/typed_data[dev-1.x, 1.0.0-alpha1, ..., 1.x-dev &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;of dev-1.x&lt;span class=&quot;o&quot;&gt;)]&lt;/span&gt; but it does not match your minimum-stability.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And so, by doing: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ddev composer require drupal/typed_data&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer require drupal/typed_data                                                                                                                                        
&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;InvalidArgumentException]                                                                                                                                                      
Could not find a version of package drupal/typed_data matching your minimum-stability &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;stable&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; Require it with an explicit version constraint allowing its desired stability.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It can be changed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;composer.json&lt;/code&gt; file, where you’ve marked stability as “stable”, so composer won’t accept the dependency in alpha, so you can change your requirements, allowing the minimum-stability of packages in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev&lt;/code&gt;  or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alpha&lt;/code&gt;  but prefer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stable.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This has to be changed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;composer.json&lt;/code&gt;file in your project root folder:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;s2&quot;&gt;&quot;conflict&quot;&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;drupal/drupal&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;*&quot;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;,
    &lt;span class=&quot;s2&quot;&gt;&quot;minimum-stability&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;dev&quot;&lt;/span&gt;,  &amp;lt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; THIS
    &lt;span class=&quot;s2&quot;&gt;&quot;prefer-stable&quot;&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;,&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;config&quot;&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;sort-packages&quot;&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;,
        &lt;span class=&quot;s2&quot;&gt;&quot;platform&quot;&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&quot;php&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;7.4&quot;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;,
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But it’s not a good idea, cause you can change the level of minimum-stability &lt;strong&gt;and it could be a risk for your project&lt;/strong&gt;. Instead, use the recommended way that is only install in alpha the dependency, step by step by doing:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;composer require drupal/typed_data:@alpha
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;composer require drupal/graphql
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;62--i-cant-create-new-users&quot;&gt;6.2- I can’t create new users&lt;/h3&gt;

&lt;p&gt;I noticed that after an update to Drupal 9, in some projects is not possible create a new user in path &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/admin/people/create&lt;/code&gt;, you can’t see the second password field “Confirm Password” and due to this, the form is not saving a new user.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is this happening to you?&lt;/strong&gt; Don’t worry, it has an easy solution. Let’s see.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;First,&lt;/strong&gt; this happens when using custom themes based in Claro (&lt;a href=&quot;https://www.drupal.org/project/claro&quot;&gt;https://www.drupal.org/project/claro&lt;/a&gt;) now, in Drupal Core -but experimental by now-.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Second&lt;/strong&gt;, The error is coming from a change in Claro theme. In Claro 9.2.5 (Drupal Core 9.2.5) there is a change in a library declaration and this was moving from one to another block.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Third,&lt;/strong&gt; you only need edit your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;custom_theme.info.yml&lt;/code&gt; file and move the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user/drupal.user: claro/form.password-confirm&lt;/code&gt; pair from the block “libraries-override” to the block “libraries-extend”. Now:&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;libraries-extend&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;lt;= HERE&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;core/drupal.ajax&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;claro/ajax&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;user/drupal.user&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;claro/form.password-confirm  &amp;lt;= HERE&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;views/views.module&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;claro/views&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Fourth,&lt;/strong&gt; only save the change and clear cache by doing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ drush cr&lt;/code&gt;  and now you’ll see the second field, saving new users.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Fifth (remember)&lt;/strong&gt;, Claro theme is experimental in Drupal Core, and is not stable.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Sixth (more remember)&lt;/strong&gt;, You must to know that subtheming from Admin Themes are not offically supported in Drupal, so be carefull: &lt;a href=&quot;https://www.drupal.org/project/claro/issues/3085894#comment-13784182&quot;&gt;Related Issue in Drupal.org&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Read more about&lt;/strong&gt; &lt;a href=&quot;https://www.drupal.org/project/drupal/issues/3192501#comment-14219792&quot;&gt;this Issue in Drupal.org.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read more&lt;/strong&gt; about subtheming an Admin theme in Drupal.org: &lt;a href=&quot;https://www.drupal.org/project/drupal/issues/3118850&quot;&gt;drupal.org/issues/3118850&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;63--config-split-not-seem-to-work-well-in-deploys&quot;&gt;6.3- Config Split not seem to work well in deploys&lt;/h3&gt;

&lt;p&gt;After updates to Drupal 9 and moving forward versions of contributed modules, in some cases there are problems when importing configuration files orchestrated by the contrib module &lt;a href=&quot;https://www.drupal.org/project/config_split&quot;&gt;config split&lt;/a&gt; and launched from some task runners tools like &lt;a href=&quot;https://dropcat.org/docs/&quot;&gt;dropcat&lt;/a&gt;, &lt;a href=&quot;https://robo.li/&quot;&gt;robo&lt;/a&gt;, &lt;a href=&quot;https://github.com/Ymbra/Drobo&quot;&gt;drobo (robo for Drupal)&lt;/a&gt; etc.&lt;/p&gt;

&lt;p&gt;Well, some Drush commands aliases has been changed in Config Split and maybe you have to change your commands:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.drupal.org/project/config_split/issues/3013423&quot;&gt;drupal.org/issues/3013423)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.drupal.org/project/config_split/issues/3181368&quot;&gt;drupal.org/issues/3181368&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the most important thing is:… the version 2.x is not recommended by the module maintainers…so please, downgrade to the former version.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_how_to_upgrade_to_d9_7.png&quot; alt=&quot;Config Split recommended version&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;64--review-and-change-deprecated-code&quot;&gt;6.4- Review (and change) deprecated code&lt;/h3&gt;

&lt;p&gt;As part of the code upgrades - especially working with custom code - in the move to Drupal 9 you will have to make mandatory changes that were previously only optional: deprecated code that (now yes) you will no longer be able to use in D9 (in D8 you were only informed or warned).&lt;/p&gt;

&lt;p&gt;For example, I have received warnings but I have not changed some services (don’t be like me) and when I got to Drupal 9 I received errors like this:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Symfony&lt;span class=&quot;se&quot;&gt;\C&lt;/span&gt;omponent&lt;span class=&quot;se&quot;&gt;\D&lt;/span&gt;ependencyInjection&lt;span class=&quot;se&quot;&gt;\E&lt;/span&gt;xception&lt;span class=&quot;se&quot;&gt;\S&lt;/span&gt;erviceNotFoundException: 
&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;You have requested a non-existent service &lt;span class=&quot;s2&quot;&gt;&quot;entity.query&quot;&lt;/span&gt;.&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt; 
Did you mean one of these: &lt;span class=&quot;s2&quot;&gt;&quot;entity.query.config&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;entity.query.sql&quot;&lt;/span&gt;, 
&lt;span class=&quot;s2&quot;&gt;&quot;pgsql.entity.query.sql&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;entity.query.null&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;entity.query.keyvalue&quot;&lt;/span&gt;? 
&lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;Drupal&lt;span class=&quot;se&quot;&gt;\C&lt;/span&gt;omponent&lt;span class=&quot;se&quot;&gt;\D&lt;/span&gt;ependencyInjection&lt;span class=&quot;se&quot;&gt;\C&lt;/span&gt;ontainer-&amp;gt;get&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; 
&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;line 156 of 
/var/www/html/web/core/lib/Drupal/Component/DependencyInjection/Container.php&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This message is about the Issue: &lt;a href=&quot;https://www.drupal.org/node/2849874&quot;&gt;drupal.org/2849874&lt;/a&gt; talking about a service deprecation. It has been around for a long time but now generates errors and should be removed.&lt;/p&gt;

&lt;p&gt;In this case I was using the service:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$query&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; Drupal::service&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'entity.query'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;-&amp;gt;get&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'menu_link_content'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$query&lt;/span&gt;-&amp;gt;condition&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'link.uri'&lt;/span&gt;, &lt;span class=&quot;s1&quot;&gt;'entity:node/'&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$node&lt;/span&gt;-&amp;gt;id&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$query&lt;/span&gt;-&amp;gt;execute&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s just a service provided by the class QueryFactory: 
&lt;a href=&quot;https://api.drupal.org/api/drupal/core!core.services.yml/service/entity.query/8.2.x&quot;&gt;api.drupal.org/entity.query&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So now you have to use the general manager for entities, the entityTypeManager service:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$query&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\D&lt;/span&gt;rupal::entityTypeManager&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;-&amp;gt;getStorage&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'menu_link_content'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;-&amp;gt;getQuery&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$query&lt;/span&gt;-&amp;gt;condition&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'link.uri'&lt;/span&gt;, &lt;span class=&quot;s1&quot;&gt;'entity:node/'&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$node&lt;/span&gt;-&amp;gt;id&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$query&lt;/span&gt;-&amp;gt;execute&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And entityQuery is available too:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$query&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\D&lt;/span&gt;rupal::entityQuery&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'menu_link_content'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$query&lt;/span&gt;-&amp;gt;condition&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'link.uri'&lt;/span&gt;, &lt;span class=&quot;s1&quot;&gt;'entity:node/'&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$node&lt;/span&gt;-&amp;gt;id&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$query&lt;/span&gt;-&amp;gt;execute&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Please, think about using review-code tooling like drupal-check and drupal-rector in order to avoid these kind of errors in code deprecations.&lt;/p&gt;

&lt;h2 id=&quot;7--read-more&quot;&gt;7- Read More&lt;/h2&gt;

&lt;p&gt;Many others have also written about the upgrade process. There is also information from Drupal.org, as well as many related experiences. If you want to go deeper into this, I recommend here several reading materials from different organisations, companies and authors.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://symfony.com/releases/3.4&quot;&gt;Symfony 3.4 EOL&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.amazeelabs.com/en/journal/end-life-drupal-8-and-upgrade-drupal-9&quot;&gt;Amazee Labs: EOL Drupal 8&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.drupal.org/psa-2021-2021-06-29&quot;&gt;Drupal 8 EOL Announcement&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.lullabot.com/articles/what-if-you-dont-upgrade-drupal-8&quot;&gt;Lullabot: What If you don’t upgrade D8?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.drupal.org/blog/how-to-prepare-for-drupal-9&quot;&gt;Drupal.org: How to prepare for Drupal 9&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.palantir.net/rector/adding-drupal-rector-site&quot;&gt;Palantir.net: Adding Drupal Rector to a site&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gorannikolovski.com/blog/how-to-upgrade-drupal-8-to-9&quot;&gt;Goran Nikolovski: How to upgrade Drupal 8 to 9&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://medium.com/@ondrejmirtes/phpstan-2939cd0ad0e3&quot;&gt;PHPStan: Find Bugs In Your Code Without Writing Tests!&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://stefvanlooveren.me/blog/how-upgrade-drupal-8-9-composer&quot;&gt;Stef Van Looveren: How to upgrade from Drupal 8 to 9 with composer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://robertroose.com/blog/drupal/how-upgrade-drupal-8-website-drupal-9-when-youre-not-developer&quot;&gt;Robert Troose: How to upgrade to Drupal 9 when you’re not a developer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.hojtsy.hu/blog/2021-oct-26/seven-days-go-until-drupal-8-eol-start-using-composer&quot;&gt;Gábor Hojtsy: Seven days to go until Drupal 8 EOL: start using Composer!&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://mglaman.dev/blog/phpstan-drupal-drupal-check-drupal-rector-upgradestatus-oh-my&quot;&gt;Matt Glaman: phpstan-drupal, drupal-check, drupal-rector, upgrade_status&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://mglaman.dev/blog/writing-better-drupal-code-static-analysis-using-phpstan&quot;&gt;Matt Glaman: Writing better Drupal code with static analysis using PHPStan&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;8--wq&quot;&gt;8- :wq!&lt;/h2&gt;

&lt;h3 id=&quot;recommended-song-panda---dungen&quot;&gt;Recommended song: Panda - Dungen&lt;/h3&gt;

&lt;div class=&quot;embed-container&quot;&gt;
    &lt;iframe src=&quot;https://www.youtube.com/embed/gsH2mNqGYTc&quot; width=&quot;700&quot; height=&quot;480&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;
    &lt;/iframe&gt;
  &lt;/div&gt;</content><author><name>davidjguru</name></author><category term="Drupal Techniques" /><summary type="html">Picture from Unsplash, user Raul Varzar, @calypso999 As you may have heard, the End Of Life for Drupal 8 is near. This is closing fast, very fast now. In fact the date for Drupal 8 EOL is November 2nd 2021, aligning this transition with the same EOL for one of the most important dependencies and key components: Symfony 3. Yep, the last minor version available for Symfony 3 (3.4) has marked like end for bug fixes and security fixes november 2021. As a rule, supported versions of Drupal must use supported version of Symfony, so this is the end unless you perform and upgrade in your Drupal platform…</summary></entry><entry><title type="html">PHP Coding: Reverse Geocoding for taxonomy terms</title><link href="https://davidjguru.github.io//blog/php-coding-reverse-geocoding-for-taxonomy-terms" rel="alternate" type="text/html" title="PHP Coding: Reverse Geocoding for taxonomy terms" /><published>2021-06-28T00:00:00+00:00</published><updated>2021-06-28T00:00:00+00:00</updated><id>https://davidjguru.github.io//blog/php-coding-reverse-geocoding-for-taxonomy-terms</id><content type="html" xml:base="https://davidjguru.github.io//blog/php-coding-reverse-geocoding-for-taxonomy-terms">&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_php_coding_reverse_geocoding_loading_taxonomy_terms.png&quot; alt=&quot;Picture from Unsplash, by @saddy143&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Picture from Unsplash, user &lt;a href=&quot;https://unsplash.com/@saddy143&quot;&gt;Nafis Al Sadnan, @saddy143&lt;/a&gt;&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Have you ever had to perform geocoding? I mean, the exercise of getting some kind of data from stuff like a specific naming in order to get values like longitude and latitude. It had been a long time since I had used the know as “Geographic Information Systems” (GIS), when I was a young (and naive) Java developer…
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;The fact is that I recently had to perform some tasks related to Geocoding: I needed to get some values from latitude and longitude values, the so-called “Reverse Geocoding”. My goal was fill out a Drupal taxonomy and populating a related field in a specific content type. 
I have decided to compile my case notes here in a sequential way, but the experience was previously published separately as a sucession of Gitlab Snippets and Gist from Github that you can follow from here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; -&amp;gt; This is a post about how to execute Reverse Geocoding for populating a taxonomy term field in Drupal 8, 9.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://gist.github.com/davidjguru/0ba7b135ae2d9738278c5dff2a311e09&quot;&gt;Drupal 8,9 - Reverse Geocoding using external Service from PHP&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gist.github.com/davidjguru/3b9d36bf3e00dd338d751b7bfa2c41eb&quot;&gt;Drupal 8,9 - Getting Taxonomy Terms from different levels programmatically &lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gitlab.com/-/snippets/2137785&quot;&gt;Drupal 8,9 - Populating taxonomy with hierarchical structure from external geocoding &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;
&lt;!-- /TOC --&gt;
&lt;p&gt;&lt;strong&gt;Table of Contents.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;#1--what-am-i-looking-for&quot;&gt;1- What am I looking for?&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;#2--reverse-geocoding-for-php&quot;&gt;2- Reverse Geocoding for PHP&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;#3--resources&quot;&gt;3- Resources&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;#4--loading-taxonomy-terms&quot;&gt;4- Loading taxonomy terms&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;#5--read-more&quot;&gt;5- Read More&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;#6--wq&quot;&gt;6- :wq!&lt;/a&gt;&lt;br /&gt;
&lt;!-- /TOC --&gt;
————————————————————————————————&lt;/p&gt;

&lt;h2 id=&quot;1--what-am-i-looking-for&quot;&gt;1- What am I looking for?&lt;/h2&gt;

&lt;p&gt;Well, I’m inside a scenario where I’m creating new nodes of a specific content type, then I’m populating its fields programmatically and finally saving the whole new node. I’m doing all the process by coding, out of the Drupal GUI and from a custom code made by me. This is the big picture.&lt;/p&gt;

&lt;p&gt;At a higher zoom level, within all its related fields, I have a Entity Reference field, specfically for a Hierarchical Taxonomy Term, I mean, a field with values to pre-charged taxonomy terms from a populated vocabulary which contains terms in three levels:&lt;/p&gt;

&lt;p&gt;My vocabulary is storing places from Peru (Perú, Piruw) in South America. This is a set of more than 2000 terms divided in a tree of hierarchy with three level. In Peru there are 24 departments, 25 regions, 196 provinces and 1838 districts, so It looks pretty extensive, something like:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/davidjguru_php_coding_reverse_geocoding_loading_taxonomy_terms_1.png&quot; alt=&quot;Reverse Geocoding: vocabulary view&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I receive geocoded files with some values and I take long, lat and I start to consult to wich point they belong, in order to obtain their things like its department, province and district. Then I’ll look for a match with my pre-populated taxonomy and I’ll save the three references to taxonomy terms maintaining hierarchy. Ok? Let’s recap.&lt;/p&gt;

&lt;h2 id=&quot;steps&quot;&gt;Steps:&lt;/h2&gt;
&lt;p&gt;1- Processing long, lat values.&lt;br /&gt;
2- Getting Department, Province and District from the long, lat values.&lt;br /&gt;
3- Looking for matching in my vocabulary.&lt;br /&gt;
4- Setting the matched values in the taxonomy hierarchy for each new node.&lt;br /&gt;
5- Saving the new populated node.&lt;/p&gt;

&lt;h2 id=&quot;2--reverse-geocoding-for-php&quot;&gt;2- Reverse Geocoding for PHP&lt;/h2&gt;

&lt;p&gt;Since we have to perform Geocoding tasks, let’s first remember some basic concepts and what kind of main resources we have available.&lt;/p&gt;

&lt;h3 id=&quot;what-is-reverse-geocoding&quot;&gt;What is “Reverse Geocoding”&lt;/h3&gt;

&lt;p&gt;First, let us initially review the concept of Reverse Geocoding:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;“Reverse geocoding is the process of converting a location as described by geographic coordinates (latitude, longitude) to a human-readable address or place name. It is the opposite of forward geocoding.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Source: &lt;a href=&quot;https://en.wikipedia.org/wiki/Reverse_geocoding&quot;&gt;Reverse Geocoding in Wikipedia&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;installing-geocoder-for-php&quot;&gt;Installing geocoder for PHP&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://geocoder-php.org/&quot;&gt;Geocoder PHP&lt;/a&gt; is the most famous library for Geocoding operations written in PHP language.&lt;br /&gt;
Geocoder PHP provides: “an abstraction layer for geocoding manipulations”. You can get the resources from &lt;a href=&quot;https://github.com/geocoder-php/Geocoder&quot;&gt;its repository in Github&lt;/a&gt; and as a &lt;a href=&quot;https://packagist.org/providers/geocoder-php/provider-implementation&quot;&gt;Packagist set of packages&lt;/a&gt;. The main library is divided into three basic concepts in order to work with Geocoding: an HttpAdapter for doing requests, several geocoding Providers and various Dumpers to get a formatting output. You will need two basic resources: the main library and a provider. I’m gonna install it in my Drupal local deploy:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer require willdurand/geocoder
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ddev composer require geocoder-php/locationiq-provider 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Or whithout ddev if you’re out of this tooling:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;composer require willdurand/geocoder
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;composer require geocoder-php/locationiq-provider 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now I have the classes available through the class loader. I can use the resources in my installation. Geocoder only requires just a pair of keyresources:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;An external provider&lt;/li&gt;
  &lt;li&gt;A HTTP Client for connections.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have the provider clasess and I have the HTTP Client too, Guzzle library, present and available in Drupal. So what I need now is get data from an external service. Let’s see some ideas about it.&lt;/p&gt;

&lt;h3 id=&quot;external-services&quot;&gt;External Services&lt;/h3&gt;

&lt;p&gt;As you can see in former sections I’m using the classical https://geocoder-php.org library. It requires the main library and the external providers classes in order to connect to others external APIs.&lt;br /&gt;
In this case I’m using LocationIQ to get the addresses:  https://locationiq.com in free mode. I’ve created a new user in this platform and I’m getting a token API for queries.&lt;/p&gt;

&lt;p&gt;Some Limitations for the free mode of LocationIQ:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;1 Access Token&lt;/li&gt;
  &lt;li&gt;5,000 request/day&lt;/li&gt;
  &lt;li&gt;2 request/second&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But well, only for some tests this may be useful.&lt;/p&gt;
&lt;h3 id=&quot;making-external-reverse-geocoding-queries&quot;&gt;Making External Reverse Geocoding Queries&lt;/h3&gt;

&lt;p&gt;Now I have the Geocoding library, the classes for the provider and data for connections to external provider, I can do some tests for Reverse Geocoding. Now for instance, I wanna build a address like an unique string builded from external received data:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Geocoder\Query\ReverseQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Http\Adapter\Guzzle6\Client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Geocoder\Provider\LocationIQ\LocationIQ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Geocoder\StatefulGeocoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// You can use other options for the HTTP Client. &lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// $httpClient = \Drupal::httpClient();&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$httpClient&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$provider&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LocationIQ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$httpClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;MY-APIKEY-FROM-LOCATIONIQ&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$geocoder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StatefulGeocoder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$provider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'en'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Launch the external query.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$geocoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reverseQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ReverseQuery&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fromCoordinates&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$latitude_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$longitude_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Mount the returned address like a unique string. &lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getStreetName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;' '&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getStreetNumber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;', '&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getLocality&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;' '&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getPostalCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;', '&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getCountry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And then I can load the address variable in a Drupal field. But this is not my case, remember I need to populate taxonomy terms fields in a Drupal node, so beyond this example I need to test more resouces.&lt;/p&gt;

&lt;h2 id=&quot;3--resources&quot;&gt;3- Resources&lt;/h2&gt;

&lt;p&gt;By searching these resources we can find libraries, services and APIs for consumption that have as few limitations as possible (rate limit, requests per second/day, etc), and finally achieve a more efficient implementation.&lt;/p&gt;
&lt;h3 id=&quot;external-public-resources&quot;&gt;External Public Resources&lt;/h3&gt;

&lt;p&gt;There are some public resources opened to connections, URLs ready to connections, just like this &lt;a href=&quot;http://www.cartociudad.es/geocoder/&quot;&gt;cartociudad.es/geocoder/&lt;/a&gt; with its own &lt;a href=&quot;http://www.cartociudad.es/geocoder/api/geocoder/reverseGeocode?lon=-0.562854&amp;amp;lat=39.918735&quot;&gt;Geocoding / Reverse Geocoding services&lt;/a&gt; (click and see the results in browser).&lt;/p&gt;

&lt;p&gt;The operations are free and simple, just an open URL and query parameters, but maybe the service is not available or stable enough for you. Let’s see other options.&lt;/p&gt;

&lt;h3 id=&quot;what-about-drupal&quot;&gt;What about Drupal&lt;/h3&gt;

&lt;p&gt;In Drupal you can use the &lt;a href=&quot;https://www.drupal.org/project/geocoder&quot;&gt;Drupal Geocoder Module&lt;/a&gt;, a contrib module that acting like a wrapper for geocoder library and resolves by itself the installation of the main library, as you can see in: &lt;a href=&quot;https://git.drupalcode.org/project/geocoder/-/blob/8.x-3.x/composer.json&quot;&gt;geocoder/composer.json&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You have to follow the instructions from its README file: &lt;a href=&quot;https://git.drupalcode.org/project/geocoder/-/blob/8.x-3.x/README.md&quot;&gt;geocoder/README.md&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I certainly haven’t had much luck using this module. Some strange bug limits me to use it for quick situations. There are some weird issues installing providers, see the &lt;a href=&quot;https://www.drupal.org/project/geocoder/issues/3153678&quot;&gt;Issue 3153678&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;nominatim&quot;&gt;Nominatim&lt;/h3&gt;

&lt;p&gt;Nominatim is an API used to search OSM data by name and address in order to doing Geocoding and Reverse Geocoding. &lt;a href=&quot;https://www.openstreetmap.org&quot;&gt;OSM is “Open Street Map”&lt;/a&gt;, a collaborative project creating a big, free and editable map of the world. 
&lt;a href=&quot;https://www.linkedin.com/in/delawen/&quot;&gt;Maria Arias de Reyna&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/delawen&quot;&gt;@delawen&lt;/a&gt; and &lt;a href=&quot;https://www.linkedin.com/in/juanluisrp/&quot;&gt;Juan Luis Rodríguez&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/juanluisrp&quot;&gt;@juanluisrp&lt;/a&gt; guided me in this way. They are the greatest &lt;a href=&quot;https://en.wikipedia.org/wiki/Geographic_information_system&quot;&gt;GIS&lt;/a&gt; experts I ever know and they were very helpful here, givin’ me some ideas and links to resources. Kudos. Specifically, @delawen told me about Nominatim, a heavy-weight solution for Geocoding Operations and I began to play with it. What is ‘Nominatim’? First Bus Stop:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Nominatim is the geocoding software that powers the official OSM site www.openstreetmap.org. It serves 30 million queries per day on a single server.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Source: &lt;a href=&quot;https://nominatim.org/&quot;&gt;https://nominatim.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ok, I see I can do my queries using Nominatim, but what else?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/mediagis/nominatim-docker&quot;&gt;There is a Nominatim version based in Docker&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://download.geofabrik.de/&quot;&gt;You can select Region for your Docker deploy&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://download.geofabrik.de/south-america.html&quot;&gt;And select Sub-Region&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://download.geofabrik.de/south-america/peru.html&quot;&gt;Country&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://download.geofabrik.de/europe/&quot;&gt;Or Continent&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/osm-search/Nominatim&quot;&gt;You can download the source code from its main repository&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://nominatim.org/release-docs/develop/api/Overview/&quot;&gt;And get an overview about how it works&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nominatim offers some Endpoints for specific queries:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/search - search OSM objects by name or &lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;
/reverse - search OSM object by their location
/lookup - look up address details &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;OSM objects by their ID
/status - query the status of the server
/deletable - list objects that have been deleted &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;OSM but are held back &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;Nominatim &lt;span class=&quot;k&quot;&gt;in case&lt;/span&gt; the deletion was accidental
/polygons - list of broken polygons detected by Nominatim
/details - show internal details &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;an object &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;debugging only&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And you can use Nominatim from a local Docker deploy or from live in external server:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;https://nominatim.openstreetmap.org/reverse?lat&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&amp;lt;value&amp;gt;&amp;amp;lon&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&amp;lt;value&amp;gt;&amp;amp;&amp;lt;params&amp;gt;
https://nominatim.openstreetmap.org/reverse?format&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;json&amp;amp;lat&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-12&lt;/span&gt;.046374&amp;amp;lon&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-77&lt;/span&gt;.042793
https://nominatim.openstreetmap.org/reverse?format&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;json&amp;amp;lat&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-9&lt;/span&gt;.949480903131423&amp;amp;lon&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-78&lt;/span&gt;.22368622836807
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;What will return a Reverse Geocoding Query from Nominatim? Take a look:&lt;/p&gt;
&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;place_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;159358569&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;licence&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;osm_type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;way&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;osm_id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;286831995&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;lat&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-9.949531163248126&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;lon&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-78.22368982770104&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;display_name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Culebras, Province of Huarmey, Ancash, Peru&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;address&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;village&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Culebras&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;region&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Province of Huarmey&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;state&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Ancash&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;country&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Peru&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;country_code&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pe&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;boundingbox&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-9.9496929&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-9.9483904&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-78.225981&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-78.2215248&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ok, This seems to be all I need!…&lt;br /&gt;
Nominatim is my great solution! well, let’s get to work.&lt;/p&gt;

&lt;h2 id=&quot;4--loading-taxonomy-terms&quot;&gt;4- Loading taxonomy terms&lt;/h2&gt;

&lt;p&gt;Well, I feel that throughout the previous sections we have already laid some firm foundations. Well, I feel that throughout the previous sections we have already laid some firm foundations. Now I want to recover my initial goal: to load taxonomy terms. For this I will use Nominatim, but as the local container addresses are not queryable from this article, I will change the URLs to external queries so you can try.&lt;/p&gt;

&lt;p&gt;I need to complete the next field:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/davidjguru_php_coding_reverse_geocoding_loading_taxonomy_terms_2.png&quot; alt=&quot;Taxonomy Terms field based in geodata&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;getting-data-for-country&quot;&gt;Getting data for Country&lt;/h3&gt;
&lt;p&gt;In Peru there are 24 departments, 25 regions, 196 provinces and 1838 districts. I need to save Department, Province and Districts for every item.  In the former example I will catch the data from the Nominatim reverse endpoint, where Department=”Ancash” , Province=”Huarmey”  District=”Culebras”, so based on the data received from Nominatim that you can see in a former example, I need to adapt this:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Department=state&lt;/li&gt;
  &lt;li&gt;Province=region&lt;/li&gt;
  &lt;li&gt;District=village&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;mounting-the-new-container&quot;&gt;Mounting the new container&lt;/h3&gt;

&lt;p&gt;Ok, now I’m gonna launch the Nominatim container using my local Docker Installation and the selected URLs with data from my required country (Peru):&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;docker run &lt;span class=&quot;nt&quot;&gt;-it&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--rm&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;PBF_URL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;https://download.geofabrik.de/south-america/peru-latest.osm.pbf &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;REPLICATION_URL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;https://download.geofabrik.de/south-america/peru-updates/ &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 8080:8080 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--name&lt;/span&gt; nominatim &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  mediagis/nominatim:3.7
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This new container will expose the API address at:&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;http://localhost:8080/search.php?q&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;KEYWORD
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;resolving-queries&quot;&gt;Resolving queries&lt;/h3&gt;

&lt;p&gt;Now I can build some queries to my new Nominatim Server from my PHP code (in a Drupal custom module, like a service or from a Controller, you know):&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GuzzleHttp\Client&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GuzzleClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Http\Adapter\Guzzle6\Client&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GuzzleAdapter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GuzzleHttp\Psr7\Request&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GuzzleRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
 &lt;span class=&quot;c1&quot;&gt;// We are getting the values for geofield.&lt;/span&gt;
 &lt;span class=&quot;c1&quot;&gt;// 'lat' =&amp;gt; $latitude_data, 'lng' =&amp;gt; $longitude_data.&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'timeout'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$httpNominatimClient&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GuzzleClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$adapter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GuzzleAdapter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$httpNominatimClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$request&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GuzzleRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'GET'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'https://nominatim.openstreetmap.org/reverse?format=json&amp;amp;lat='&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$latitude_data&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&amp;amp;lon='&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$longitude_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$adapter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sendRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$geo_nominatim&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;json_decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getBody&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And I can extract the required values following the returned format in the json response, putting some control in the case of the value for “District” (sometimes is a City, sometimes is a Village):&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// First get the initial strings. &lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$initial_department&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$geo_nominatim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'address'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'state'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$initial_province&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$geo_nominatim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'address'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'region'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$geo_nominatim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'address'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'village'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])){&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$initial_district&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$geo_nominatim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'address'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'city'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$initial_district&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$geo_nominatim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'address'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'village'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;my-next-problem-the-ñ-character-and-the-diacritics&quot;&gt;My next problem: the ‘Ñ’ character and the diacritics&lt;/h3&gt;

&lt;p&gt;The first thing I notice is that Nominatim is returning me some naming without accents or diacritics in some cases, in pure English. Let’s see an example about this. I’m looking for data (lat, lon) for “Huánuco” (Perú) and Nominatim is returning me something like this:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;city&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Chinchao&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;region&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Province of Huánuco&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;state&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Huánuco&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;postcode&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;062&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;country&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Peru&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;country_code&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pe&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you can see, “Huánuco” is comming with diacritics but the country name “Peru” is returned without accent. Can this cause me problems in the future? So now having observed this issue, I now have to check that there are no misinterpretations, normalizing all the strings on both sides of the matching.&lt;/p&gt;

&lt;p&gt;The ‘Ñ’ character is the sign for a very common sound that you can build using ‘gn’ in French or Italian, and using ‘ny’ in Catalan language. But at some point an old transcriber monk decided to use this symbol, and here we are…&lt;/p&gt;

&lt;p&gt;So, I normalize some values but maintaining the ‘ñ’ character in names, just in &lt;a href=&quot;https://en.wikipedia.org/wiki/San_Vicente_de_Ca%C3%B1ete&quot;&gt;‘San Vicente de Cañete’&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;How Can Normalize string but maintaining special characters like ‘ñ’? well, I was thinking about changes the character, normalize and then return the ‘ñ’ character to the strings, so I can try something like this:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Changes the 'ñ' character.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$first_step_replace_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ñ'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'\001'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$initial_department&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$first_step_replace_2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ñ'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'\001'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$initial_province&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$first_step_replace_3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ñ'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'\001'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$initial_district&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Normalizes all the strings.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$normalized_department&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;preg_replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'/[\x{0300}-\x{036f}]/u'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Normalizer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;normalize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$first_step_replace_1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Normalizer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;FORM_D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$normalized_province&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;preg_replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'/[\x{0300}-\x{036f}]/u'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Normalizer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;normalize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$first_step_replace_2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Normalizer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;FORM_D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$normalized_district&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;preg_replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'/[\x{0300}-\x{036f}]/u'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Normalizer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;normalize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$first_step_replace_3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Normalizer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;FORM_D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Returns the 'ñ' character to the strings.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$normalized_department&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'\001'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'ñ'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$normalized_department&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$normalized_province&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'\001'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'ñ'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$normalized_province&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$normalized_district&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'\001'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'ñ'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$normalized_district&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Now I can make sure that everything is normalized, flattened without diacritics and maintaining the ‘ñ’ character.&lt;/p&gt;

&lt;h3 id=&quot;loading-the-whole-taxonomy&quot;&gt;Loading the whole taxonomy&lt;/h3&gt;

&lt;p&gt;The next step for me is to make sure that I can execute a matching between the received values and the existing ones from my vocabulary. In addition, I must take into account that the same name can be repeated throughout the tree structure: A province and a district may share a name, and it may even be the case that the same name is shared at all three levels of the hierarchy of terms, for instance, see the next example where “Arequipa” is a Department, a Province and a District:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/davidjguru_php_coding_reverse_geocoding_loading_taxonomy_terms_3.png&quot; alt=&quot;Same term for all the structure&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So I have to do some thinking to discern how to know that a specific name is part of the first, second or third level within the taxonomy. For the moment to start with, I load the whole taxonomy, all its terms, using &lt;a href=&quot;https://api.drupal.org/api/drupal/core%21modules%21taxonomy%21src%21TermStorage.php/function/TermStorage%3A%3AloadTree/8.2.x&quot;&gt;the loadTree() method&lt;/a&gt;. Although it is a heavy process to load all the complete entities (TRUE parameter), later I can change this for a “light” load of only name and numeric tid.&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Load the whole taxonomy tree using values.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$manager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Drupal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;entityTypeManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getStorage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'taxonomy_term'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$taxonomy_tree&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;loadTree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'location'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// The taxonomy term vocabulary machine name.&lt;/span&gt;
        &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;               &lt;span class=&quot;c1&quot;&gt;// The &quot;tid&quot; of parent using &quot;0&quot; to get all.&lt;/span&gt;
        &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;               &lt;span class=&quot;c1&quot;&gt;// Get all available level.&lt;/span&gt;
        &lt;span class=&quot;kc&quot;&gt;TRUE&lt;/span&gt;             &lt;span class=&quot;c1&quot;&gt;// Get full load of taxonomy term entity.&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Ok, now I’m in a loop going through the values taken from Nominatim, point by point. I need to find the term matching from traversing the taxonomy values and know in which position (by level) I should load the geolocated point. To do this I’m planning to ask each term if it has children or if it has parents, since (I think):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;If it has no parents and it has children, it will be first level.&lt;/li&gt;
  &lt;li&gt;If it has parents and has children, it will be second level.&lt;/li&gt;
  &lt;li&gt;If it has parents and has no children, it will be third level.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But as first step:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Prepares the future array of taxonomy terms to load.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$array_of_tids&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now I’m gonna loop over all the taxonomy terms in a Normalized way:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$taxonomy_tree&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$term&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$first_step_naming&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ñ'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'\001'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$second_step_naming&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;preg_replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'/[\x{0300}-\x{036f}]/u'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Normalizer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;normalize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$first_step_naming&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Normalizer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;FORM_D&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$normalized_naming&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str_replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'\001'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'ñ'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$second_step_naming&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I can play with terms using conditions and testing parents and childrens. I can use &lt;a href=&quot;https://api.drupal.org/api/drupal/core%21modules%21taxonomy%21src%21TermStorage.php/function/TermStorage%3A%3AloadChildren/8.2.x&quot;&gt;the loadChildren() method&lt;/a&gt; and &lt;a href=&quot;https://api.drupal.org/api/drupal/core%21modules%21taxonomy%21src%21TermStorage.php/function/TermStorage%3A%3AloadParents/8.2.x&quot;&gt;the loadParents() method&lt;/a&gt; passing by its tid for every term.&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// If has not parent and has children is a first level term. &lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;loadParents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;loadChildren&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$normalized_naming&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$normalized_department&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$array_of_tids&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// If has parent and children then is a second level term.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;loadParents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;loadChildren&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$normalized_naming&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$normalized_province&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$array_of_tids&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// If has parent and has not children then is a third level term.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;loadParents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;loadChildren&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$normalized_naming&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$normalized_district&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$array_of_tids&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$parent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;reset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;loadParents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()));&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$array_of_tids&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Also I can save the terms in hierarchy using only the final term from the third level, completing the tree from bottom to top, each time I identify a third-level term:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// If has parent and has not children then is a third level term.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;loadParents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;loadChildren&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$normalized_naming&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$normalized_district&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Third level Term.&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$array_of_tids&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Second level Term.&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$parent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;reset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;loadParents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$term&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()));&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$array_of_tids&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  
  &lt;span class=&quot;c1&quot;&gt;// First level Term.&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$grandparent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;reset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;loadParents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$array_of_tids&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$grandparent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;My goal is to finally have an array composed of three numeric values that will be the tids of the terms found. This array can be saved in the Entity Reference field for the taxonomy and finally when the node is saved, these taxonomy terms will be charged in every node.&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$new_node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field_taxonomy_location&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$array_of_tids&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$new_node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Done!&lt;/p&gt;

&lt;h2 id=&quot;5--read-more&quot;&gt;5- Read More&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://medium.com/@adri.espejo/getting-started-with-openstreetmap-nominatim-api-e0da5a95fc8a&quot;&gt;Getting started with OpenStreetMap Nominatim API, by Adrián Espejo&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.ivanlokhov.com/osm-geodata-with-nominatim-api/&quot;&gt;Getting OpenStreetMap geodata with Nominatim API, by Ivan Lokhov&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.mapquest.com/documentation/open/nominatim-search/&quot;&gt;Open Search Nominatim API&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;6--wq&quot;&gt;6- :wq!&lt;/h2&gt;

&lt;h3 id=&quot;recommended-song-addio-lugano-bella&quot;&gt;Recommended song: Addio Lugano bella&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Giorgio Gaber, Enzo Jannacci, Lino Toffolo, Otello Profazio and Silverio Pisu.&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;embed-container&quot;&gt;
    &lt;iframe src=&quot;https://www.youtube.com/embed/k84G4ODpBsE&quot; width=&quot;700&quot; height=&quot;480&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;
    &lt;/iframe&gt;
  &lt;/div&gt;</content><author><name>davidjguru</name></author><category term="PHP Coding" /><summary type="html">Picture from Unsplash, user Nafis Al Sadnan, @saddy143 Have you ever had to perform geocoding? I mean, the exercise of getting some kind of data from stuff like a specific naming in order to get values like longitude and latitude. It had been a long time since I had used the know as “Geographic Information Systems” (GIS), when I was a young (and naive) Java developer…</summary></entry><entry><title type="html">PHP Coding: functions that can save your day</title><link href="https://davidjguru.github.io//blog/php-coding-functions-that-can-save-your-day" rel="alternate" type="text/html" title="PHP Coding: functions that can save your day" /><published>2021-05-30T00:00:00+00:00</published><updated>2021-05-30T00:00:00+00:00</updated><id>https://davidjguru.github.io//blog/php-coding-functions-that-can-save-your-day</id><content type="html" xml:base="https://davidjguru.github.io//blog/php-coding-functions-that-can-save-your-day">&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_php_coding_functions_can_save_your_day_main.png&quot; alt=&quot;Picture from Unsplash, by @umby&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Picture from Unsplash, user &lt;a href=&quot;https://unsplash.com/@umby&quot;&gt;Umberto, @umby&lt;/a&gt;&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Well, this month I’ve been doing some things I haven’t practiced for some time: data migrations, intensive connections to Gitlab API v4 and even some web-scraping to get data. Along the way I’ve recovered some old PHP functions that I had forgotten or hadn’t used for a long time. As I didn’t want to forget them again, I took this notebook as a reference and wrote down a small post with some functions of our old friend PHP that can give us a little help in the day to day.&lt;br /&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;The old man PHP has over 1000 built-in functions that can be called and used directly from your code and will be independient of the platform/CMS/framework (Drupal, Symfony, Laravel…) so you can load the functions in your scripts or classes in order to execute specific tasks. I’ve given a little context to each one and possible uses. You probably already know them or they seem very obvious to you, but I thought it was fun to share them. I’m sure someone might find them useful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This month (may 2021) I’ve published an article with a review about &lt;a href=&quot;https://www.therussianlullaby.com/blog/books-31-days-of-drupal-migrations&quot;&gt;the book ‘31 Days of Drupal Migrations’ in The Russian Lullaby&lt;/a&gt;. This could be interesting for you.&lt;/p&gt;

&lt;h2 id=&quot;1--basename&quot;&gt;1- basename()&lt;/h2&gt;

&lt;p&gt;I really don’t know why I had forgotten this function of PHP…but the fact is that I had been processing URLs for some time and cutting them to get paths, directory names and final files.&lt;/p&gt;

&lt;p&gt;One day I remembered it again and there it was! basename() is a function that returns the final item in a path and if you add a suffix (maybe you only need the name of a file, not its extension), the function will delete the .extension and will give you just a name.&lt;/p&gt;

&lt;h3 id=&quot;examples&quot;&gt;Examples&lt;/h3&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Do your things.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Trying to get the final component in url.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$cut_url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;substr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Same as.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$cut_url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;basename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;remember&quot;&gt;Remember&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Function / Method:&lt;/strong&gt; basename() returns the final element of a path.&lt;br /&gt;
&lt;strong&gt;Using:&lt;/strong&gt; basename($path); basename($path, $suffix);&lt;br /&gt;
&lt;strong&gt;Available:&lt;/strong&gt; PHP4, PHP5, PHP7, PHP8.&lt;br /&gt;
&lt;strong&gt;More Info:&lt;/strong&gt; &lt;a href=&quot;https://www.php.net/manual/en/function.basename.php&quot;&gt;php.net/basename&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;2--getelementsbytagname&quot;&gt;2- getElementsByTagName()&lt;/h2&gt;

&lt;p&gt;Ok, well I was doing some data extractions from web scraping and suddenly remembered the existence of 
the DOMDocument class in PHP, a set of available functions for getting a HTML document and parsing / extracting diverse information from the DOM object.&lt;/p&gt;

&lt;p&gt;This function (really is a method, due to live in a class context): getElementsByTagName() gives you a set of results gettings values only from reffered tags in the processed DOM. For instance, I can do something like:&lt;/p&gt;

&lt;h3 id=&quot;examples-1&quot;&gt;Examples&lt;/h3&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Create a new DOM Document to get the HTML remote content.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$html_code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DOMDocument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Load the url's contents into the DOM item.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$html_code&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;loadHTMLFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But in my Drupal context will be just like:&lt;/p&gt;
&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Third: Gets a whole post from original website.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$post&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;file_get_contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$domain_link_post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$dom&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Html&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;It’s the same operation, and then we’ll get specific values:&lt;/p&gt;
&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Do your things.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Fourth: Gets all the interesting values for the new node. &lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Gets title and subtitle from DOM.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$block_title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$dom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'title'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$block_title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'h1'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;textContent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$alias&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$block_title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'h3'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;textContent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the former codeblock I was extracting some basic data for load in a new Drupal node, strings like the title of the node and information to fill in a field called “alias”. My parsed DOM document is well known to me, this is very important for implementing the correct parsing: I must know well where are the data I am interested in.&lt;br /&gt;
In fact Drupal is using this DOMDocument class under the hood through a wrapper, the Html class available from:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;core&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lib&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Drupal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Component&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Utility&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Html&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;php&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Inside this class we’re doing an extensive use of the DOMDocument class. Just in the load() main function you can see, for instance:&lt;/p&gt;
&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$dom&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;DOMDocument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Ignore warnings during HTML soup loading.&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$dom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;loadHTML&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$dom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;remember-1&quot;&gt;Remember&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Function / Method:&lt;/strong&gt; DOMDocument::getElementsByTagName(), search all elements from a tag name.&lt;br /&gt;
&lt;strong&gt;Using:&lt;/strong&gt; $dom-&amp;gt;getElementsByTagName(‘li’); $dom-&amp;gt;getElementsByTagName(‘p’);
&lt;strong&gt;Available:&lt;/strong&gt; PHP5, PHP7, PHP8.&lt;br /&gt;
&lt;strong&gt;More Info:&lt;/strong&gt; &lt;a href=&quot;https://www.php.net/manual/en/domdocument.getelementsbytagname.php&quot;&gt;php.net/getelementsbytagname&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read More:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.php.net/manual/en/class.domdocument.php&quot;&gt;DOMDocument class of PHP&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Component%21Utility%21Html.php/class/Html/8.2.x&quot;&gt;Html class of Drupal&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;3--glob&quot;&gt;3- glob()&lt;/h2&gt;

&lt;p&gt;What is glob? (baby don’t hurt me… xD) Well the glob() function will return naming of files in a certain path, and I was using the function for treating files and processing values, or delete existing files from a folder.&lt;/p&gt;

&lt;h3 id=&quot;examples-2&quot;&gt;Examples&lt;/h3&gt;

&lt;p&gt;Here deleting files by unlink function.&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$initial_files&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;glob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'sites/default/files/my_folder/*'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Deleting all the files in the list&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$initial_files&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;is_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)){&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Delete the given file&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;unlink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And here looping over the files for processing some specific values.&lt;/p&gt;
&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Get all the existing files.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$geodata_files&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;glob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'modules/custom/my_custom_module/geodata_files/*'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Now we are going to loop over the existing files for doing stuff.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$geodata_files&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$geodata_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Doing your things.&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;remember-2&quot;&gt;Remember&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Function / Method:&lt;/strong&gt; glob(), find pathnames matching a pattern.&lt;br /&gt;
&lt;strong&gt;Using:&lt;/strong&gt; count(glob(‘folder/files/&lt;em&gt;’)); $files = glob(‘folder/files/&lt;/em&gt;’);&lt;br /&gt;
&lt;strong&gt;Available:&lt;/strong&gt; PHP4, PHP5, PHP7, PHP8.&lt;br /&gt;
&lt;strong&gt;More Info:&lt;/strong&gt; &lt;a href=&quot;https://www.php.net/manual/en/function.glob.php&quot;&gt;Glob function of PHP&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;4--curl_init&quot;&gt;4- curl_init()&lt;/h2&gt;

&lt;p&gt;Curl is a function library supported by PHP that allows HTTP request and also is available as command line tool for prompt. In that context I’ve been using it for a while now, but only from the Linux console… The reason? Well, for almost all the code related to REST clients from Drupal I’ve implemented it using Guzzle (the PHP reference library for REST clients and integrated in Drupal) or indirectly using the HTTP Client Manager, a resource that allows you manage HTTP Clients from YAML description files -or JSON- (and is using Guzzle under the hood, by the way).&lt;/p&gt;

&lt;p&gt;But the last week I had to implement a small external query from my code to the Google Places API and I thought I’d try curl directly from PHP. This was my case.&lt;/p&gt;

&lt;h3 id=&quot;examples-3&quot;&gt;Examples&lt;/h3&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Enables a new cURL resource.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;curl_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$url_map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;https://maps.googleapis.com/maps/api/place/details/json?cid=&quot;&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$required_cid_code&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;amp;key=&quot;&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;myConfig&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'google_places_api_key'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;curl_setopt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CURLOPT_URL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$url_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;curl_setopt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CURLOPT_RETURNTRANSFER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
&lt;span class=&quot;nb&quot;&gt;curl_setopt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CURLOPT_HEADER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Get the geo file from google maps API for places.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$result_value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;curl_exec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$converted_result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;json_decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$result_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;curl_close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;curl is available from your server installation as a PHP resource, in my case the web container of &lt;a href=&quot;https://www.digitalocean.com/community/tutorials/how-to-develop-a-drupal-9-website-on-your-local-machine-using-docker-and-ddev&quot;&gt;my DDEV local deploy&lt;/a&gt;, and only requires initialize a session, set your options for the work, then execute the session and finally close it.&lt;/p&gt;
&lt;h3 id=&quot;remember-3&quot;&gt;Remember&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Function / Method:&lt;/strong&gt; curl_init(), initializes a new session and return a cURL handle for use.&lt;br /&gt;
&lt;strong&gt;Using:&lt;/strong&gt; $ch = curl_init(); $ch = curl_init(“http://www.externaldomain.com/”);&lt;br /&gt;
&lt;strong&gt;Available:&lt;/strong&gt; PHP4, PHP5, PHP7, PHP8.&lt;br /&gt;
&lt;strong&gt;More Info:&lt;/strong&gt; &lt;a href=&quot;https://www.php.net/manual/en/book.curl.php&quot;&gt;The PHP’s book of curl&lt;/a&gt;&lt;br /&gt;
&lt;strong&gt;Read More:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.php.net/manual/en/curl.examples-basic.php&quot;&gt;curl basic example&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.guzzlephp.org/en/stable/&quot;&gt;Guzzle the PHP HTTP client&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.drupal.org/project/http_client_manager&quot;&gt;Drupal HTTP Manager contrib module&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;5--htmlspecialchars_decode&quot;&gt;5- htmlspecialchars_decode()&lt;/h2&gt;

&lt;p&gt;I was extracting values from an external web source of HTML, real numbers, but in some cases when loading them in target and then rendering my nodes, some of these fields were showing character encoding using HTML entities, changing a single quote or apostrophe: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;'&lt;/code&gt;  by its HTML encoding: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;#39;&lt;/code&gt; (you can see equivalences &lt;a href=&quot;https://www.toptal.com/designers/htmlarrows/punctuation/apostrophe/&quot;&gt;here&lt;/a&gt;). So in a received and then loaded value for a field, instead of get some like from the external source:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Price&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;marked&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Soles&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;From&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;597&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;604&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;To&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;703&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;183&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I was setting in destiny:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Price&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;marked&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Soles&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;From&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;597&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;604&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;To&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;#39;703,183&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;So I needed a way to decode that parameter and set its original format. And there’re a pair of interesting functions in PHP to execute something like this:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;htmlspecialchars_decode(): Convert HTML entities to special characters.&lt;/li&gt;
  &lt;li&gt;htmlspecialchars(): Convert special characters to HTML entities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My case is exactly the first option, I need to change the HTML codification and save it and I can use a specific flag to mark this required behavior: ENT_QUOTES.&lt;/p&gt;
&lt;h3 id=&quot;examples-4&quot;&gt;Examples&lt;/h3&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$value_soles&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;htmlspecialchars_decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$soles_value_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ENT_QUOTES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$value_dolars&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;htmlspecialchars_decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$dolars_value_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ENT_QUOTES&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;remember-4&quot;&gt;Remember&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Function / Method:&lt;/strong&gt; htmlspecialchars_decode(), convert special HTML entities to characters.&lt;br /&gt;
&lt;strong&gt;Using:&lt;/strong&gt; htmlspecialchars_decode($original_string, ENT_QUOTES); htmlspecialchars_decode($original_string);&lt;br /&gt;
&lt;strong&gt;Available:&lt;/strong&gt; PHP5, PHP7, PHP8.&lt;br /&gt;
&lt;strong&gt;More Info:&lt;/strong&gt; &lt;a href=&quot;https://www.php.net/manual/en/function.htmlspecialchars-decode.php&quot;&gt;php.net/htmlspecialchars-decode.php&lt;/a&gt;&lt;br /&gt;
&lt;strong&gt;Read More:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.php.net/manual/en/function.htmlspecialchars.php&quot;&gt;php.net/htmlspecialchars&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.php.net/manual/en/function.htmlentities.php&quot;&gt;php.net/htmlentities&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.php.net/manual/en/function.html-entity-decode.php&quot;&gt;php.net/html_entity_decode&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;wq&quot;&gt;:wq!&lt;/h2&gt;

&lt;h3 id=&quot;recommended-song-quemas---ede--xoel-lópez&quot;&gt;Recommended song: Quemas - Ede &amp;amp; Xoel López&lt;/h3&gt;

&lt;div class=&quot;embed-container&quot;&gt;
    &lt;iframe src=&quot;https://www.youtube.com/embed/MxXNNOXiUgI&quot; width=&quot;700&quot; height=&quot;480&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;
    &lt;/iframe&gt;
  &lt;/div&gt;</content><author><name>davidjguru</name></author><category term="PHP Coding" /><summary type="html">Picture from Unsplash, user Umberto, @umby Well, this month I’ve been doing some things I haven’t practiced for some time: data migrations, intensive connections to Gitlab API v4 and even some web-scraping to get data. Along the way I’ve recovered some old PHP functions that I had forgotten or hadn’t used for a long time. As I didn’t want to forget them again, I took this notebook as a reference and wrote down a small post with some functions of our old friend PHP that can give us a little help in the day to day.</summary></entry><entry><title type="html">Drupal Tips: Link fields from Twig</title><link href="https://davidjguru.github.io//blog/drupal-tips-link-fields-from-twig" rel="alternate" type="text/html" title="Drupal Tips: Link fields from Twig" /><published>2021-04-30T00:00:00+00:00</published><updated>2021-04-30T00:00:00+00:00</updated><id>https://davidjguru.github.io//blog/drupal-tips-link-fields-from-twig</id><content type="html" xml:base="https://davidjguru.github.io//blog/drupal-tips-link-fields-from-twig">&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_link_fields_from_twig_main.png&quot; alt=&quot;Picture from Unsplash, by @lazycreekimages&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Picture from Unsplash, user &lt;a href=&quot;https://unsplash.com/@lazycreekimages&quot;&gt;Michael Dziedzic, @lazycreekimages&lt;/a&gt;&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;In this new issue of the Drupal Fast Tips I would like to share some basic tips and examples related with the Drupal Link field and how to get the data from its sub-fields (title and link) to rendering in a Twig template. Sometimes we need render values from a link field in a structured way through a Twig template, and depending on the location of the Link field, this may have a different articulation.&lt;br /&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;Because of this, I wanted to show some small examples of extracting and handling the values of this particular type of fields. This will be a post for site-builders or developers with basic knowledge on the Drupal backend (yes, Twig and the rendering are in the backend, sorry.).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This month (april 2021) I’ve published an article about &lt;a href=&quot;https://www.therussianlullaby.com/blog/condition-plugins-for-visibility-in-drupal/&quot;&gt;Visibility Condition Plugins for Drupal in The Russian Lullaby&lt;/a&gt;. This could be interesting for you.&lt;/p&gt;

&lt;hr /&gt;
&lt;!-- /TOC --&gt;
&lt;p&gt;&lt;strong&gt;This article is part of a series of posts about Drupal Tips.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://davidjguru.github.io/blog/drupal-fast-tips-using-links-in-drupal-8&quot;&gt;1- Drupal Fast Tips (I) - Using links in Drupal 8&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://davidjguru.github.io/blog/drupal-fast-tips-prefilling-fields-in-forms&quot;&gt;2- Drupal Fast Tips (II) - Prefilling fields in forms&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://davidjguru.github.io/blog/drupal-fast-tips-the-magic-of-attached&quot;&gt;3- Drupal Fast Tips (III) - The Magic of ‘#attached’&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://davidjguru.github.io/blog/drupal-fast-tips-xdebug-ddev-and-postman&quot;&gt;4- Drupal Fast Tips (IV) - Xdebug, DDEV and Postman&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://davidjguru.github.io/blog/drupal-fast-tips-placing-a-block-by-code&quot;&gt;5- Drupal Fast Tips (V) - Placing a block by code&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://davidjguru.github.io/blog/drupal-fast-tips-from-array-to-html&quot;&gt;6- Drupal Fast Tips (VI) - From Arrays to HTML&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://davidjguru.github.io/blog/drupal-fast-tips-link-fields-from-twig&quot;&gt;7- Drupal Fast Tips (VII) - Link Fields from Twig&lt;/a&gt;&lt;br /&gt;
&lt;!-- /TOC --&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;using-a-link-field&quot;&gt;Using a Link Field&lt;/h2&gt;

&lt;p&gt;Only starts when you add a new Link field to your content, directly or from a Paragraph using this field. Now you have two sub-fields (title and link) and some config options.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_link_fields_from_twig_1.png&quot; alt=&quot;Link field basic configuration&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It’s also quite possible that you have added &lt;a href=&quot;https://www.drupal.org/project/link_attributes&quot;&gt;the contrib module ‘Link Attributes’&lt;/a&gt; for adding some extra widgets to the Link field. For instance, this is a very common configuration for saving values in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;target&lt;/code&gt; attribute. After passing by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/admin/structure/types/manage/article/form-display&lt;/code&gt; and select &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;link with attributes&lt;/code&gt; for your Link field display, now you have got something like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_link_fields_from_twig_2.png&quot; alt=&quot;Link field basic configuration&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So you’re building links to render with two subfields and one related attribute.&lt;/p&gt;
&lt;h2 id=&quot;building-the-link-with-separate-items&quot;&gt;Building the link with separate items&lt;/h2&gt;

&lt;p&gt;When you’re getting the link field values from a view and you’ve selected as formatter: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;separate link element and text&lt;/code&gt; in config. First check if title exists and render it. If not, only builds the link data:&lt;/p&gt;

&lt;div class=&quot;language-twig highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;link-item&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;cp&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%}&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;link-title&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;cp&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;%}&lt;/span&gt;`
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;link-url&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;{{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;}}&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is basic structure for showing the link from Twig if you have separate values for link and title, and you aren’t returning the values mounting in a single object.&lt;/p&gt;
&lt;h2 id=&quot;getting-value-of-the-target-attribute-from-a-link-field-in-paragraph&quot;&gt;Getting value of the target attribute from a Link Field in Paragraph&lt;/h2&gt;

&lt;p&gt;Sometimes you can use the Link Field within a Paragraph and then you need get the values of the link from a Twig Template. 
Here the syntax can be more strange, but let’s see how to extract some values from a field in a Paragraph: Link with url, text and target values.&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;c1&quot;&gt;// key -&amp;gt; target=&quot;{{ paragraph.field_link_link[0].options.attributes.target }}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;{{ paragraph.field_link_link.0.url  }}&quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;{{ paragraph.field_link_link[0].options.attributes.target }}&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field_link_title&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;In the snippet from above, you can see that we’re using as title of the link the data from the content, mixing origins.&lt;/p&gt;

&lt;h2 id=&quot;processing-and-building-links-from-a-view-to-a-twig-template&quot;&gt;Processing and building links from a View to a Twig Template&lt;/h2&gt;

&lt;p&gt;I’m getting some fields from a specific view, passing values from a Link field (text, link), and a I want review if external / internal links and put some attributes from the link text.&lt;/p&gt;

&lt;p&gt;The next snippet is a piece of code from a classic &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hook_preprocess_views_view_fields()&lt;/code&gt; included in a *.theme file, where we’re using a control variable registering if the link was external or not. Then we’ll try to reach this variable and take some decisions about the structure in Twig. This case involves three areas of work:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The view itself, when we configure the exit of the fields to the render system (You can overwrite the fields output here).&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;theme_name.theme&lt;/code&gt; file, with hooks and methods for altering the future render.&lt;/li&gt;
  &lt;li&gt;The related Twig template, catching the variables from the theme file and processing values.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s see:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;storage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'user_page'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current_display&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'page_5'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Loads and cuts the field resources_link for processing.&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$link&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$variables&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'fields'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'field_resources_link'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;__toString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;//$link -&amp;gt; &quot;&amp;lt;a href=&quot;https://www.google.com/&quot; target=&quot;_blank&quot;&amp;gt;External Link Example&amp;lt;/a&amp;gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//$link -&amp;gt; &quot;&amp;lt;a href=&quot;/blog&quot;&amp;gt;Internal Link Example&amp;lt;/a&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;$sliced_link&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;explode&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'&quot;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$url_link&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$sliced_link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Check if external link.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$link&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;str_contains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'target=&quot;_blank&quot;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)){&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;$variables&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'external'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;$url_title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;substr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$sliced_link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$link&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;str_contains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'target=&quot;_blank&quot;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// Check if internal link.&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;$variables&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'external'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;$url_title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;explode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;substr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$sliced_link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;// Loads the final values for twig template.&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$variables&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'url_link'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$url_link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$variables&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'url_title'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$url_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then mounting the received values in twig:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;row-news&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;row-news-header {% if external %} resources-link {% endif %}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
	  &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ url_link }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;alt=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;url_title&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;}}&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;title= &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;url_title&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;}}&lt;/span&gt; 
        &lt;span class=&quot;err&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;%}&lt;/span&gt; 
          &lt;span class=&quot;na&quot;&gt;target=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;_blank&quot;&lt;/span&gt; 
        &lt;span class=&quot;err&quot;&gt;{%&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;endif&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;%}&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt; 
        {{ fields.title.content }} 
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
	{{fields.field_resource_description.content}}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;wq&quot;&gt;:wq!&lt;/h2&gt;

&lt;h3 id=&quot;recommended-song-catalina---rosalía--refree&quot;&gt;Recommended song: Catalina - Rosalía &amp;amp; Refree&lt;/h3&gt;

&lt;div class=&quot;embed-container&quot;&gt;
    &lt;iframe src=&quot;https://www.youtube.com/embed/6O192OAzMH8&quot; width=&quot;700&quot; height=&quot;480&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;
    &lt;/iframe&gt;
  &lt;/div&gt;</content><author><name>davidjguru</name></author><category term="Drupal Tips" /><summary type="html">Picture from Unsplash, user Michael Dziedzic, @lazycreekimages In this new issue of the Drupal Fast Tips I would like to share some basic tips and examples related with the Drupal Link field and how to get the data from its sub-fields (title and link) to rendering in a Twig template. Sometimes we need render values from a link field in a structured way through a Twig template, and depending on the location of the Link field, this may have a different articulation.</summary></entry><entry><title type="html">Linux: 70 commands aliases for everyday life</title><link href="https://davidjguru.github.io//blog/linux-70-commands-aliases-for-everyday-life" rel="alternate" type="text/html" title="Linux: 70 commands aliases for everyday life" /><published>2021-03-29T00:00:00+00:00</published><updated>2021-03-29T00:00:00+00:00</updated><id>https://davidjguru.github.io//blog/linux-70-commands-aliases-for-everyday-life</id><content type="html" xml:base="https://davidjguru.github.io//blog/linux-70-commands-aliases-for-everyday-life">&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;/images/davidjguru_drupal_8_9_50_command_aliases_for_everyday_life_main.jpg&quot; alt=&quot;Picture from Unsplash, by @jjying&quot; /&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;em&gt;Picture from Unsplash, user &lt;a href=&quot;https://unsplash.com/@jjying&quot;&gt;JJ Ying&lt;/a&gt;&lt;/em&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Following on from my previous post about “200 Linux commands for everyday life” that I published a few months ago -September 2020, &lt;a href=&quot;https://davidjguru.github.io/blog/200-linux-commands-for-everyday-life&quot;&gt;here&lt;/a&gt;-, so today I want to share another small article about little everyday utilities. The previous post had a more extensive (and intense) feedback than when I’m writing about Drupal, so this has invited me to think that maybe (just maybe) it could be useful content for someone.&lt;br /&gt;
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;This time, I have chosen to gather my favourite console “aliases” in one post. Aliases are a very dynamic way to add power to the command terminal and also a way to improve your fluency in the Linux terminal and therefore, your own productivity when working on projects. They are really just an exercise in replacing commands that you use frequently with a faster and simpler version of them, so that you can type them faster and more intuitively (especially if they include options and parameters). This way you can type less to request the same long instructions.&lt;/p&gt;

&lt;p&gt;Do you often type the same command with similar parameters? make it a console “alias”!…well, you can also create “functions” to do the same but in a much more dynamic and adaptive way, but I’ve left that for another article later on. Today: aliases!.&lt;/p&gt;

&lt;hr /&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Just go to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/home/user&lt;/code&gt; folder and edit your .bashrc file in order to include these aliases. Then reload the bashrc file and you’ll get the new aliases available. You can add the new aliases in a new file too, using a file named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bash_aliases&lt;/code&gt; and then load the new file from your original &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bashrc&lt;/code&gt; file, just by adding the reference in order to set the aliases:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Alias definitions.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# You may want to put all your additions into a separate file like&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# ~/.bash_aliases, instead of adding them here directly.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# See /usr/share/doc/bash-doc/examples in the bash-doc package.&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; ~/.bash_aliases &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; ~/.bash_aliases
&lt;span class=&quot;k&quot;&gt;fi

if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; ~/.bash_functions &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; ~/.bash_functions
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For example, if you wanna use reduced formats for usual instrucions, you can do something like this:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;yep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'sudo apt install $1'&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;nop&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'sudo apt remove $1'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And so you can type by prompt using the new aliases:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;yep nmap
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;nop nmap
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Remember:&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1. &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;:~&lt;span class=&quot;nv&quot;&gt;$*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~    
2. &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;:~&lt;span class=&quot;nv&quot;&gt;$*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; vim .bashrc // :wq! &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;after &lt;span class=&quot;nb&quot;&gt;paste &lt;/span&gt;the content&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;      
3. &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;:~&lt;span class=&quot;nv&quot;&gt;$*&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; .bashrc   
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can download the whole file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bash_aliases&lt;/code&gt; fullfilled with all the aliases from &lt;a href=&quot;https://gist.github.com/davidjguru/019beabeac6245959564499db3e45084#file-bash_aliases&quot;&gt;here like a Github Gist&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;morning-opertures&quot;&gt;Morning Opertures&lt;/h2&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;whatsup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'service --status-all'&lt;/span&gt;  
2. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'sudo /etc/init.d/apache2 stop &amp;amp;&amp;amp; cd workspace/project &amp;amp;&amp;amp; ddev start &amp;amp;&amp;amp; ddev launch'&lt;/span&gt;   
3. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'sudo systemctl stop apache2'&lt;/span&gt;  
4. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'nmap localhost'&lt;/span&gt;  
   &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;Are my ports open?&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;
5. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dens&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;sudo systemd-resolve --status | grep 'DNS Servers'&quot;&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;What is my current DNS Server?&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;
6. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;iad&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'systemctl is-active docker'&lt;/span&gt;  
7. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;bye&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'shutdown -r now'&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;usual-instructions&quot;&gt;Usual Instructions&lt;/h2&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;8. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'clear'&lt;/span&gt;  
9. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'history'&lt;/span&gt;  
10. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'history | grep $1'&lt;/span&gt;  
    &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;Search using &lt;span class=&quot;nb&quot;&gt;history command&lt;/span&gt;: &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;hg somestring.&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;  
11.  &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;wg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'wget -c '&lt;/span&gt;  
12. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;al&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;echo ------------Your curent aliases are:------------¡';alias&quot;&lt;/span&gt;  
    &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;Returns all your aliases collection.&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;
13. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;sup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&quot;&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;content-in-folders&quot;&gt;Content in folders&lt;/h2&gt;

&lt;h3 id=&quot;getting-info-from-a-position-in-a-folder&quot;&gt;Getting info from a position in a folder.&lt;/h3&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;14. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ll&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ls -la'&lt;/span&gt;  
    &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;Debian doesnt have the &lt;span class=&quot;nt&quot;&gt;-ll-&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;created by default, like Ubuntu.&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;    
15. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ls -alF'&lt;/span&gt;  
16. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;la&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ls -A'&lt;/span&gt;  
17. &lt;span class=&quot;nb&quot;&gt;alias ls&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ls -CF'&lt;/span&gt;  
18. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ls --human-readable --size -1 -S --classify'&lt;/span&gt;  
    &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;Sort resources by _file_ size.&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;   
19. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lu&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'du -sh * | sort -h'&lt;/span&gt;  
    &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;Same as former but counting size from folders too.&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;   
20. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ls -t -1 -long'&lt;/span&gt;  
    &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;Gets an ordered list of files and folders by changes &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;time.&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;   
21. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'find . -type f | wc -l'&lt;/span&gt;  
    &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;Gets a total recursirve count of existing files, no folders.&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;   
22. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ld&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ls -d */'&lt;/span&gt;  
    &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;Gets a list of existing directories from current folder.&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;   
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;info-from-drupal-config-files-types-of-content-and-existing-paragraphs&quot;&gt;Info from Drupal: config files, types of content and existing paragraphs&lt;/h3&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;23. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lsc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ls -lah config/sync/ | wc -l'&lt;/span&gt;   
24. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lsn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ls -lah config/sync/node.type.* | wc -l'&lt;/span&gt;    
25. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lsp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ls -lah config/sync/paragraphs.paragraphs_type.* | wc -l'&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;files-folders-and-resources&quot;&gt;Files, folders and resources&lt;/h2&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;26. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;fh&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'find . -name '&lt;/span&gt;   
27. &lt;span class=&quot;nb&quot;&gt;alias&lt;/span&gt; ..&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'cd ..'&lt;/span&gt;  
28. &lt;span class=&quot;nb&quot;&gt;alias&lt;/span&gt; ....&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'cd ../..'&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;more-jump-down&quot;&gt;More Jump Down&lt;/h3&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;29. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;1d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;cd ..&quot;&lt;/span&gt;  
30. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;2d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;cd ..;cd ..&quot;&lt;/span&gt;  
31. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;3d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;cd ..;cd ..;cd ..&quot;&lt;/span&gt;  
32. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;4d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;cd ..;cd ..;cd ..;cd ..&quot;&lt;/span&gt;  
33. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;5d&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;cd ..;cd ..;cd ..;cd ..;cd ..&quot;&lt;/span&gt;  
34. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;untar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'tar -zxvf $1'&lt;/span&gt;  
    &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;Open a tar.gz formated folder.&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;  
35. &lt;span class=&quot;nb&quot;&gt;alias tar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'tar -czvf $1'&lt;/span&gt;  
    &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;Compressing a folder &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;tar.gz format.&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;  
36. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;mnt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;mount | awk -F' ' '{ printf &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\t&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;1,&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;3; }' | column -t | egrep ^/dev/ | sort&quot;&lt;/span&gt;  
37. &lt;span class=&quot;nb&quot;&gt;alias df&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;df -Tha --total&quot;&lt;/span&gt;   
38. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'nautilus .'&lt;/span&gt;  
    &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;Opens the current directory &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;file explorer.&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;git-related-aliases&quot;&gt;Git Related Aliases&lt;/h2&gt;

&lt;h3 id=&quot;basic-info&quot;&gt;Basic info&lt;/h3&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;39. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;gs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'git status'&lt;/span&gt;  
40. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;gb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'git branch'&lt;/span&gt;  
41. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;gr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'git remote -v'&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;getting-info-from-git-log&quot;&gt;Getting info from ‘Git log’&lt;/h3&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;42. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;gl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'git log --oneline'&lt;/span&gt;  
    &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;Gets a log info view &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;a single line format.&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;    
43. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;glc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;git log --format=format: --name-only --since=12.month | egrep -v '^&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$'&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; | sort | uniq -c  | sort -nr | head -50&quot;&lt;/span&gt;  
    &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;Get a list with the most changed files from 12 months ago.&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;  
44. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;gld&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'git log –oneline –decorate –graph –all'&lt;/span&gt;  
    &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;Show all the branches &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;the tree format &lt;span class=&quot;nb&quot;&gt;history &lt;/span&gt;with pointers.&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;  
45. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;glp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;git log -g --grep='PHP' -10 --pretty='%h - %s - %cn - %cd'&quot;&lt;/span&gt;  
    &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;Gets info from log filtering by some fixed key &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;commit messages.&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;  
    &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;I am using some keys &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;message commits, &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;just like these.]&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;https://gitlab.com/-/snippets/2096890&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;  
46. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;glf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'git for-each-ref --sort=-committerdate'&lt;/span&gt;   
    &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;Get commits list by DESC order.&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;pushing-to-basic-branches&quot;&gt;Pushing to basic branches&lt;/h3&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;47. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;gpom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'git push origin master'&lt;/span&gt;  
48. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;gpod&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'git push origin develop'&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;drush-commands&quot;&gt;Drush Commands&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;I’m using &lt;a href=&quot;https://ddev.readthedocs.io/en/stable/&quot;&gt;DDEV-Local&lt;/a&gt; for my Drupal local deploys.&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;49. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ddev drush cex'&lt;/span&gt;  
50. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ddev drush cim'&lt;/span&gt;  
51. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cexy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'yes|ddev drush cex'&lt;/span&gt;  
52. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cimy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'yes|ddev drush cim'&lt;/span&gt;  
53. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dgm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ddev drush generate module'&lt;/span&gt;  
54. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dws&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ddev drush watchdog:show –count=20'&lt;/span&gt;  
    &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;Shows the last 20 problems &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;your Drupal installation.&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;  
55. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ddc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ddev drush cr'&lt;/span&gt;  
56. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dpc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ddev drush pmu $@'&lt;/span&gt;
57. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ddev drush en -y $@'&lt;/span&gt;
58. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dpe&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ddev drush pmu $1 &amp;amp;&amp;amp; ddev drush cr &amp;amp;&amp;amp; ddev drush en -y $1'&lt;/span&gt;
59. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dva&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ddev drush views:analyze'&lt;/span&gt;
60. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dpl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ddev drush pml'&lt;/span&gt;
61. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ddev drush pm-list --status='enabled'&quot;&lt;/span&gt;
62. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dld&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ddev drush pm-list --status='disabled'&quot;&lt;/span&gt;
63. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dlo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ddev drush pm-list --type=module --status=enabled --no-core'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;ddev-explicit-aliases&quot;&gt;DDEV Explicit Aliases&lt;/h2&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;64. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dsl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ddev start &amp;amp;&amp;amp; ddev launch'&lt;/span&gt;   
65. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ddy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ddev delete -Oy'&lt;/span&gt;  
    &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;Deletes the DDEV folder and resources &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;the current project folder.&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;  
66. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;did&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ddev import-db'&lt;/span&gt;   
67. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ddl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ddev list'&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;reviewing-codestyle-aliases&quot;&gt;Reviewing Codestyle Aliases&lt;/h2&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;68. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dcs1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ddev exec -d=/var/www/html vendor/bin/phpcs --standard=Drupal --extensions='php,module,inc,install,test,profile,theme,info,txt,md' web/modules/custom/&quot;&lt;/span&gt;  
69. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dcs2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;ddev exec -d=/var/www/html vendor/bin/phpcs --standard=DrupalPractice --extensions='php,module,inc,install,test,profile,theme,info,txt,md' web/modules/custom/&quot;&lt;/span&gt;  
70. &lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dcsr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ddev exec -d=/var/www/html vendor/bin/phpcs –report=diff'&lt;/span&gt;  
    &lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;With /path/to/code, Will generate a patch file from a style diff.&lt;span class=&quot;k&quot;&gt;**&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;wq&quot;&gt;:wq!&lt;/h2&gt;

&lt;h3 id=&quot;recommended-song-vitamin-c---can&quot;&gt;Recommended song: Vitamin C - CAN&lt;/h3&gt;

&lt;div class=&quot;embed-container&quot;&gt;
    &lt;iframe src=&quot;https://www.youtube.com/embed/NTFFhcEus5o&quot; width=&quot;700&quot; height=&quot;480&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;
    &lt;/iframe&gt;
  &lt;/div&gt;</content><author><name>davidjguru</name></author><category term="Linux &amp; Commands" /><summary type="html">Picture from Unsplash, user JJ Ying Following on from my previous post about “200 Linux commands for everyday life” that I published a few months ago -September 2020, here-, so today I want to share another small article about little everyday utilities. The previous post had a more extensive (and intense) feedback than when I’m writing about Drupal, so this has invited me to think that maybe (just maybe) it could be useful content for someone.</summary></entry></feed>