php https://michaelwelford.com/ en Drupal tech blogging https://michaelwelford.com/series/drupal-tech-blogging <span class="field field--name-title field--type-string field--label-hidden">Drupal tech blogging</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/user/1" typeof="schema:Person" property="schema:name" datatype="">admin</span></span> <span class="field field--name-created field--type-created field--label-hidden">Mon, 23/09/2019 - 15:37</span> <div class="field field--name-field-posts field--type-viewfield field--label-above"> <div class="field__label">List of blog posts</div> <div class="field__item field__item-label-hidden"> <div class="views-element-container"><div class="view view-series-listing view-id-series_listing view-display-id-block_2 js-view-dom-id-cf1eede57db093fa869040ae935b82420c3be1c911d205b31d78eeb8a4d2a611"> <div class="view-content"> <div class="item-list"> <ol> <li><a href="/post/building-tech-blog-2019-introduction" hreflang="en">Building a tech blog in 2019, an introduction</a></li> </ol> </div> </div> </div> </div> </div> </div> <div class="field field--name-field-blog-tags field--type-entity-reference field--label-above"> <div class="field__label">// @Tags</div> <div class="field__items"> <div class="field__item"><a href="/tag/bespoke" hreflang="en">bespoke</a></div> <div class="field__item"><a href="/tag/drupal" hreflang="en">Drupal</a></div> <div class="field__item"><a href="/tag/php" hreflang="en">php</a></div> </div> </div> <div class="field field--name-field-category field--type-entity-reference field--label-above"> <div class="field__label">// @Category</div> <div class="field__items"> <div class="field__item"><a href="/category/code" hreflang="en">code</a></div> <div class="field__item"><a href="/category/technology" hreflang="en">technology</a></div> </div> </div> Mon, 23 Sep 2019 06:07:48 +0000 admin 38 at https://michaelwelford.com How to determine the name of a Drupal dynamic permission https://michaelwelford.com/post/how-determine-name-drupal-dynamic-permission <span class="field field--name-title field--type-string field--label-hidden">How to determine the name of a Drupal dynamic permission</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/user/1" typeof="schema:Person" property="schema:name" datatype="">admin</span></span> <span class="field field--name-created field--type-created field--label-hidden">Sun, 02/09/2018 - 12:41</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Here’s something…. <em>funny</em> aka painful.</p> <p>I tried to take a shortcut in determining a dynamic permission for a workflow by just looking at the names of the classes on the permssions page and I saw this:</p> <pre><code>edit-permissions-use-study-plan-transition-archive edit-permissions-use-study-plan-transition-create-new-draft </code></pre> <p>etc.</p> <p>One incorrectly thought that maybe the name of the permission was <code>use study plan transition create new draft</code> but no - there is no way to tell which one of those dashes translates to underscores.</p> <p><strong>Hold the boat</strong></p> <p>If one looks a bit further (I just did this) in at the markup for the actual checkboxes on the permissions one will then find:</p> <pre><code class="language-html">&lt;input class=&quot;rid-anonymous js-rid-anonymous form-checkbox&quot; data-drupal-selector=&quot;edit-anonymous-use-study-plan-transition-archive&quot; type=&quot;checkbox&quot; id=&quot;edit-anonymous-use-study-plan-transition-archive&quot; name=&quot;anonymous[use study_plan transition create_new_draft]&quot; value=&quot;1&quot;&gt; </code></pre> <p>…where <code>use study_plan transition create_new_draft</code> can be seen.</p> <p>Before I <em>actually used my eyes and clicked around</em> I was going to say that the code to find these things out is a trivial:</p> <pre><code class="language-php">$role = Role::load('admin'); $all_permissions = $role-&gt;getPermissions(); </code></pre> <p>etc.</p> <p>Note that you can also use the <code>EntityTypeManager</code> to load up your roles but the storage is of type <code>user_storage</code> <em>of course</em>!</p></div> <div class="field field--name-field-category field--type-entity-reference field--label-above"> <div class="field__label">// @Category</div> <div class="field__items"> <div class="field__item"><a href="/category/code" hreflang="en">code</a></div> </div> </div> <div class="field field--name-field-blog-tags field--type-entity-reference field--label-above"> <div class="field__label">// @Tags</div> <div class="field__items"> <div class="field__item"><a href="/tag/drupal" hreflang="en">Drupal</a></div> <div class="field__item"><a href="/tag/php" hreflang="en">php</a></div> </div> </div> <div class="field field--name-field-size field--type-entity-reference field--label-above"> <div class="field__label">// @Size</div> <div class="field__item"><a href="/size/snack" hreflang="en">snack</a></div> </div> <div class="field field--name-published-at field--type-published-at field--label-above"> <div class="field__label">// @</div><div class="field__item">02/09/2018</div> </div> Sun, 02 Sep 2018 03:11:47 +0000 admin 26 at https://michaelwelford.com Writing a BaseFieldDefinition hook_update_N https://michaelwelford.com/post/writing-basefielddefinition-hookupdaten <span class="field field--name-title field--type-string field--label-hidden">Writing a BaseFieldDefinition hook_update_N</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/user/1" typeof="schema:Person" property="schema:name" datatype="">admin</span></span> <span class="field field--name-created field--type-created field--label-hidden">Sun, 26/11/2017 - 14:34</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Before I wrote this code the “documentation” on this was in one of the two treasure troves (the other being the actual Drupal code itself) of the <a rel="nofollow noopener noreferrer" target="_blank" href="https://www.drupal.org/list-changes/drupal">change records</a>, specifically <a rel="nofollow noopener noreferrer" target="_blank" href="https://www.drupal.org/node/2554097">Write update functions for entity schema updates, automation removed</a>.</p> <p>As often happens the change record didn’t quite cover what I wanted to do and it specifically didn’t mention a couple of mind bending gotchas.</p> <h2>Trust the process</h2> <p>If you need to update the <em>type</em> of a custom <code>BaseFieldDefinition</code> the general process is:</p> <ol> <li>Store the existing values for the field</li> </li> <li>Clear out the values from the field (required to uninstall a field)</li> </li> <li>Uninstall the field</li> <li>Create a new <code>BaseFieldDefinition</code> </li> <li>Install the new definition</li> <li>Restore the values from step 1</li> </ol> <p>For example, changing the type from <code>boolean</code> to <code>string</code> for which the code is:</p> <pre><code class="language-php">$entity_type_manager = \Drupal::entityTypeManager(); $bundle_of = 'node'; $storage = $entity_type_manager-&gt;getStorage($bundle_of); $bundle_definition = $entity_type_manager-&gt;getDefinition($bundle_of); // Sometimes the primary key isn't 'id'. e.g. 'eid' or 'item_id'. $id_key = $bundle_definition-&gt;getKey('id'); // If there is no data table defined then use the base table. $table_name = $storage-&gt;getDataTable() ?? $storage-&gt;getBaseTable(); $database = \Drupal::database(); $definition_manager = \Drupal::entityDefinitionUpdateManager(); // Store the existing values. $status_values = $database-&gt;select($table_name) -&gt;fields($table_name, [$id_key, 'status_field']) -&gt;execute() -&gt;fetchAllKeyed(); // Clear out the values. $database-&gt;update($table_name) -&gt;fields(['status_field' =&gt; NULL]) -&gt;execute(); // Uninstall the field. $field_storage_definition = $definition_manager-&gt;getFieldStorageDefinition('status_field', $bundle_of); $definition_manager-&gt;uninstallFieldStorageDefinition($field_storage_definition); // Create a new field definition. $new_status_field = BaseFieldDefinition::create('string') -&gt;setLabel(t('Status field')) -&gt;setDescription(t('The status - either no, yes or skip.')) -&gt;setDefaultValue('no') -&gt;setRevisionable(FALSE) -&gt;setTranslatable(FALSE); // Install the new definition. $definition_manager-&gt;installFieldStorageDefinition('status_field', $bundle_of, $bundle_of, $new_status_field); // Restore the values. $value_map = [ '1' =&gt; 'yes', '0' =&gt; 'no', ]; foreach ($status_values as $id =&gt; $value) { $database-&gt;update($table_name) -&gt;fields(['status_field' =&gt; $value_map[$value]]) -&gt;condition($id_key, $id) -&gt;execute(); } } </code></pre> <p>Phew! I truly pity you if you have to do this for multiple defs and types.</p> <h2>Gotchas</h2> <p>So how about dem gotchas:</p> <ul> <li>The primary key <code>id</code> for an entity probably differs in name</li> <li>The name of the table that stores your <code>BaseFieldDefinition</code> probably differs in name pattern</li> <li>You can’t uninstall a definition until the field is cleared out</li> </ul> <p>Bon chance, Drupalistas!</p></div> <div class="field field--name-field-category field--type-entity-reference field--label-above"> <div class="field__label">// @Category</div> <div class="field__items"> <div class="field__item"><a href="/category/code" hreflang="en">code</a></div> </div> </div> <div class="field field--name-field-blog-tags field--type-entity-reference field--label-above"> <div class="field__label">// @Tags</div> <div class="field__items"> <div class="field__item"><a href="/tag/drupal" hreflang="en">Drupal</a></div> <div class="field__item"><a href="/tag/drupal-8" hreflang="en">Drupal 8</a></div> <div class="field__item"><a href="/tag/php" hreflang="en">php</a></div> </div> </div> <div class="field field--name-field-size field--type-entity-reference field--label-above"> <div class="field__label">// @Size</div> <div class="field__item"><a href="/size/meal" hreflang="en">meal</a></div> </div> <div class="field field--name-published-at field--type-published-at field--label-above"> <div class="field__label">// @</div><div class="field__item">19/08/2018</div> </div> Sun, 26 Nov 2017 04:04:53 +0000 admin 5 at https://michaelwelford.com