<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[thedotwriter's blog (by Peeter Rannou)]]></title><description><![CDATA[If I'm stuck on a bug that no one ever talked about, you can bet I'm gonna write a little somethin' about it.]]></description><link>http://thedotwriter.com/</link><image><url>http://thedotwriter.com/favicon.png</url><title>thedotwriter&apos;s blog (by Peeter Rannou)</title><link>http://thedotwriter.com/</link></image><generator>Ghost 5.66</generator><lastBuildDate>Sat, 04 Apr 2026 15:00:59 GMT</lastBuildDate><atom:link href="http://thedotwriter.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Add a New Appearance to the Product Content-Type for the Page Builder on Magento 2 EE]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>The recent addition of Page Builder (formely known as BlueFoot when it was available as a separate extension), allows for a more user-friendly way to create CMS Pages. However, when using a <code>Products</code> item to generate a list of products, only one template is available. Let me show you how</p>]]></description><link>http://thedotwriter.com/add-a-new-appearance-to-a-page-builder-content-type-on-magento-2/</link><guid isPermaLink="false">651835af9bb2470001ef2cb3</guid><dc:creator><![CDATA[Peeter RANNOU]]></dc:creator><pubDate>Thu, 11 Jul 2019 12:09:18 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>The recent addition of Page Builder (formely known as BlueFoot when it was available as a separate extension), allows for a more user-friendly way to create CMS Pages. However, when using a <code>Products</code> item to generate a list of products, only one template is available. Let me show you how to create new templates and make them available on the creation form.</p>
<h1 id="shortexplanationdownload">Short Explanation (+ Download)</h1>
<p>Behind the scene, a <code>Products</code> item from the PageBuilder is just a wrapper for the <code>ProductsList</code> widget. Therefore, the process is fairly simple, we just need to:</p>
<ol>
<li>Tweak some JavaScript (<code>widget-directive.js</code>) to allow new templates to be used.</li>
<li>Create a valid .phtml file using the methods available for <code>ProductsList</code> widget (Magento\CatalogWidget\Block\Product\ProductsList).</li>
<li>Add a new <code>Appearance</code> with some XML.</li>
</ol>
<h3 id="downloadthemodulefromthisarticle">Download the module from this article</h3>
<p>You can <a href="http://thedotwriter.com/static/Thedotwriter_PageBuilderExtensionProducts.zip">download an archive of the module here</a>. Just drop it at the root of your website and modify what you need based on the tutorial below.</p>
<h1 id="fullexplanation">Full explanation</h1>
<h2 id="createamodule">Create a module</h2>
<p>First thing we have to do is create a new module. Here&apos;s a <a href="https://devdocs.magento.com/videos/fundamentals/create-a-new-module/?ref=thedotwriter.com">link to the official documentation</a> if you don&apos;t know how to do it.</p>
<p>For the example, we&apos;ll name the module <code>Thedotwriter_PageBuilderExtensionProducts</code> (following the naming convention used in <a href="https://devdocs.magento.com/page-builder/docs/extend-existing-content-type/step-1-create-extension-module.html?ref=thedotwriter.com">the documentation for extending a content type</a>).</p>
<h2 id="listoffiles">List of files</h2>
<p>Here&apos;s a tree view of all files and folders we&apos;re going to create:</p>
<pre><code>app   
&#x2514;&#x2500;&#x2500;&#x2500;code
    &#x2514;&#x2500;&#x2500;&#x2500;Thedotwriter
        &#x2514;&#x2500;&#x2500;&#x2500;PageBuilderExtensionProducts
            &#x2502;   composer.json
            &#x2502;   registration.php
            &#x2502;   
            &#x251C;&#x2500;&#x2500;&#x2500;etc
            &#x2502;   &#x2502;   module.xml
            &#x2502;   &#x2502;   
            &#x2502;   &#x2514;&#x2500;&#x2500;&#x2500;adminhtml
            &#x2502;           di.xml
            &#x2502;           
            &#x2514;&#x2500;&#x2500;&#x2500;view
                &#x251C;&#x2500;&#x2500;&#x2500;adminhtml
                &#x2502;   &#x251C;&#x2500;&#x2500;&#x2500;pagebuilder
                &#x2502;   &#x2502;   &#x2514;&#x2500;&#x2500;&#x2500;content_type
                &#x2502;   &#x2502;           products.xml
                &#x2502;   &#x2502;           
                &#x2502;   &#x2514;&#x2500;&#x2500;&#x2500;web
                &#x2502;       &#x251C;&#x2500;&#x2500;&#x2500;css
                &#x2502;       &#x2502;   &#x2514;&#x2500;&#x2500;&#x2500;images
                &#x2502;       &#x2502;       &#x2514;&#x2500;&#x2500;&#x2500;content-type
                &#x2502;       &#x2502;           &#x2514;&#x2500;&#x2500;&#x2500;products
                &#x2502;       &#x2502;               &#x2514;&#x2500;&#x2500;&#x2500;appearance
                &#x2502;       &#x2502;                       menu-list-complex.svg
                &#x2502;       &#x2502;                       menu-list-simple.svg
                &#x2502;       &#x2502;                       
                &#x2502;       &#x2514;&#x2500;&#x2500;&#x2500;js
                &#x2502;           &#x2514;&#x2500;&#x2500;&#x2500;content-type
                &#x2502;               &#x2514;&#x2500;&#x2500;&#x2500;products
                &#x2502;                   &#x2514;&#x2500;&#x2500;&#x2500;mass-converter
                &#x2502;                           widget-directive.js
                &#x2502;                           
                &#x2514;&#x2500;&#x2500;&#x2500;frontend
                    &#x2514;&#x2500;&#x2500;&#x2500;templates
                        &#x2514;&#x2500;&#x2500;&#x2500;product
                            &#x2514;&#x2500;&#x2500;&#x2500;widget
                                &#x2514;&#x2500;&#x2500;&#x2500;content
                                        widget-menu-list-complex.phtml
                                        widget-menu-list-simple.phtml
</code></pre>
<p>Now, let&apos;s explain them one by one.</p>
<h2 id="addadependencytomagento_pagebuilder">Add a dependency to Magento_PageBuilder</h2>
<p>Let&apos;s make sure to load our module components after Magento_PageBuilder. For that, <a href="https://devdocs.magento.com/guides/v2.3/extension-dev-guide/build/module-load-order.html?ref=thedotwriter.com">add a <code>&lt;sequence&gt;</code> to your module.xml file</a>:</p>
<p><strong><code>etc/module.xml</code>:</strong></p>
<pre><code class="language-xml">&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;config xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:noNamespaceSchemaLocation=&quot;urn:magento:framework:Module/etc/module.xsd&quot;&gt;
    &lt;module name=&quot;Thedotwriter_PageBuilderExtensionProducts&quot; setup_version=&quot;0.1.0&quot;&gt;
        &lt;sequence&gt;
            &lt;module name=&quot;Magento_PageBuilder&quot;/&gt;
        &lt;/sequence&gt;
    &lt;/module&gt;
&lt;/config&gt;
</code></pre>
<h2 id="createanewwidgetconvertor">Create a new widget convertor</h2>
<p>Remember, the <code>Products</code> PageBuilder item is only a wrapper for the already existing <code>ProductsList</code> widget (&quot;Catalog Product List&quot; in the backend). Therefore, the PageBuilder item configuraton needs to be passed to a <code>ProductsList</code> widget at some point. That&apos;s the job of the <code>widget-directive.js</code> convertor.</p>
<p>There&apos;s one issue with it though, the path to the phtml file is hard coded into the original file. So, <strong>we&apos;re gonna create another JS convertor that lets us set the phtml file as a setting in the products.xml file</strong>. It&apos;s quite simple (once you spent enough time looking around!):</p>
<p>Copy:<br>
<code>vendor/magento/module-page-builder/view/adminhtml/web/js/content-type/products/mass-converter/widget-directive.js</code><br>
Into our module :<br>
<code>view/web/js/content-type/products/mass-converter/widget-directive.js</code></p>
<p>Then in the <code>toDom()</code> function, change the line 53:</p>
<pre><code>template: &quot;Magento_CatalogWidget::product/widget/content/grid.phtml&quot;,
</code></pre>
<p>Into this:</p>
<pre><code>template: config.template_path,
</code></pre>
<h2 id="createanewtemplatefile">Create a new template file</h2>
<p>Now, create an empty <code>.phtml</code> file in the following path in our module:<br>
<code>view/frontend/templates/product/widget/content/</code></p>
<p>This example being based on a recent work of mine, the file is called <code>widget-menu-list-simple.phtml</code>, but call it however you want. Just remember to update the name in the <code>products.xml</code> file I&apos;ll make you create later. That&apos;s where the template file will be specified.</p>
<p>In the ZIP file provided in this article, you&apos;ll find an example of how to work with this template. But if you want more, you can check out the original <code>grid.phtml</code> file in <code>vendor/magento/module-catalog-widget/view/frontend/templates/product/widget/content/</code>.</p>
<h2 id="addanewappearance">Add a new Appearance</h2>
<p>To setup a new Appearance, start by creating a <code>products.xml</code> file in<br>
<code>view/adminhtml/pagebuilder/content_type/</code>. Then add the following:</p>
<pre><code class="language-xml">&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;config xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:noNamespaceSchemaLocation=&quot;urn:magento:module:Magento_PageBuilder:etc/content_type.xsd&quot;&gt;
    &lt;type name=&quot;products&quot;&gt;
        &lt;appearances&gt;
            &lt;appearance name=&quot;menu-list-simple&quot;
                        preview_template=&quot;Magento_PageBuilder/content-type/products/grid/preview&quot;
                        master_template=&quot;Magento_PageBuilder/content-type/products/grid/master&quot;
                        reader=&quot;Magento_PageBuilder/js/master-format/read/configurable&quot;&gt;
                &lt;elements&gt;
                    &lt;element name=&quot;main&quot;&gt;
                        &lt;style name=&quot;text_align&quot; source=&quot;text_align&quot;/&gt;
                        &lt;style converter=&quot;Magento_PageBuilder/js/converter/style/border-style&quot; name=&quot;border&quot; source=&quot;border_style&quot;/&gt;
                        &lt;style converter=&quot;Magento_PageBuilder/js/converter/style/color&quot; name=&quot;border_color&quot; source=&quot;border_color&quot;/&gt;
                        &lt;style converter=&quot;Magento_PageBuilder/js/converter/style/border-width&quot; name=&quot;border_width&quot; source=&quot;border_width&quot;/&gt;
                        &lt;style converter=&quot;Magento_PageBuilder/js/converter/style/remove-px&quot; name=&quot;border_radius&quot; source=&quot;border_radius&quot;/&gt;
                        &lt;style name=&quot;display&quot; source=&quot;display&quot; converter=&quot;Magento_PageBuilder/js/converter/style/display&quot; preview_converter=&quot;Magento_PageBuilder/js/converter/style/preview/display&quot;/&gt;
                        &lt;style name=&quot;margins&quot; storage_key=&quot;margins_and_padding&quot; reader=&quot;Magento_PageBuilder/js/property/margins&quot; converter=&quot;Magento_PageBuilder/js/converter/style/margins&quot;/&gt;
                        &lt;style name=&quot;padding&quot; storage_key=&quot;margins_and_padding&quot; reader=&quot;Magento_PageBuilder/js/property/paddings&quot; converter=&quot;Magento_PageBuilder/js/converter/style/paddings&quot;/&gt;
                        &lt;attribute source=&quot;data-content-type&quot; name=&quot;name&quot;/&gt;
                        &lt;attribute source=&quot;data-appearance&quot; name=&quot;appearance&quot;/&gt;
                        &lt;html name=&quot;html&quot; preview_converter=&quot;Magento_PageBuilder/js/converter/attribute/preview/store-id&quot;/&gt;
                        &lt;css name=&quot;css_classes&quot;/&gt;
                    &lt;/element&gt;
                &lt;/elements&gt;
                &lt;converters&gt;
                    &lt;converter component=&quot;Thedotwriter_PageBuilderExtensionProducts/js/content-type/products/mass-converter/widget-directive&quot; name=&quot;widget_directive&quot;&gt;
                        &lt;config&gt;
                            &lt;item name=&quot;html_variable&quot; value=&quot;html&quot;/&gt;
                            &lt;item name=&quot;template_path&quot; value=&quot;Thedotwriter_PageBuilderExtensionProducts::product/widget/content/widget-menu-list-simple.phtml&quot;/&gt;
                        &lt;/config&gt;
                    &lt;/converter&gt;
                &lt;/converters&gt;
            &lt;/appearance&gt;
        &lt;/appearances&gt;
    &lt;/type&gt;
&lt;/config&gt;
</code></pre>
<p>What we&apos;ve done above is copy the default &quot;grid&quot; <code>&lt;appearance&gt;</code> (originally set in vendor/magento/module-page-builder/view/adminhtml/pagebuilder/content_type/products.xml), put it in our XML file and change the name of the appearance to <code>menu-list-simple</code>.</p>
<p>Next, we update the path of the widget_directive converter to <code>Thedotwriter_PageBuilderExtensionProducts/js/content-type/products/mass-converter/widget-directive</code> which will make Magento use our javascript file created earlier:</p>
<pre><code class="language-xml">&lt;converter component=&quot;Thedotwriter_PageBuilderExtensionProducts/js/content-type/products/mass-converter/widget-directive&quot; name=&quot;widget_directive&quot;&gt;
</code></pre>
<p>And finally, we add a new config item named &quot;template_path&quot; to the converter settings. <strong>That&apos;s where you specify the template you want to use</strong>:</p>
<pre><code class="language-xml">&lt;item name=&quot;template_path&quot; value=&quot;Thedotwriter_PageBuilderExtensionProducts::product/widget/content/widget-menu-list-simple.phtml&quot;/&gt;
</code></pre>
<h3 id="makethenewappearanceavailableinthebackend">Make the new Appearance available in the backend</h3>
<p>Once the Appearance is created, you have to tell Magento to make it available for the PageBuilder <code>Products</code> item.</p>
<p>This is done by adding this to your module <code>di.xml</code> file:</p>
<pre><code class="language-xml">&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;config xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:noNamespaceSchemaLocation=&quot;urn:magento:framework:ObjectManager/etc/config.xsd&quot;&gt;
    &lt;virtualType name=&quot;AppearanceSourceProducts&quot;&gt;
        &lt;arguments&gt;
            &lt;argument name=&quot;optionsData&quot;&gt;
                &lt;item name=&quot;1&quot; xsi:type=&quot;array&quot;&gt;
                    &lt;item name=&quot;value&quot; xsi:type=&quot;string&quot;&gt;menu-list-simple&lt;/item&gt;
                    &lt;item name=&quot;title&quot; xsi:type=&quot;string&quot; translate=&quot;true&quot;&gt;Menu List Simple&lt;/item&gt;
                    &lt;item name=&quot;icon&quot; xsi:type=&quot;string&quot;&gt;Thedotwriter_PageBuilderExtensionProducts/css/images/content-type/products/appearance/menu-list-simple.svg&lt;/item&gt;
                &lt;/item&gt;
            &lt;/argument&gt;
        &lt;/arguments&gt;
    &lt;/virtualType&gt;
&lt;/config&gt;
</code></pre>
<p>Update the <code>value</code>, <code>title</code> and <code>icon</code> of the item according to the appearance name, the label you want to show on the edit form and the SVG icon you want to use.</p>
<p>Don&apos;t forget to enable your module and clear the cache and you should be good to go!</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Moving .drush/ Folder to a Custom Location on Drupal 7]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>To work properly, Drush needs to create a <code>.drush/</code> folder in the home directory of the user that&apos;s launching the command. If you wish to change the location of the <code>.drush</code> directory, you need to change the value of the HOME environment variable temporarily.</p>
<p>To do that, start</p>]]></description><link>http://thedotwriter.com/moving-drush-folder-custom-path-drupal-7/</link><guid isPermaLink="false">651835af9bb2470001ef2cac</guid><dc:creator><![CDATA[Peeter RANNOU]]></dc:creator><pubDate>Mon, 04 Dec 2017 13:25:43 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>To work properly, Drush needs to create a <code>.drush/</code> folder in the home directory of the user that&apos;s launching the command. If you wish to change the location of the <code>.drush</code> directory, you need to change the value of the HOME environment variable temporarily.</p>
<p>To do that, start by creating an empty module named <code>update_drush_dir</code>. An empty module needs only two files, an empty file named <code>update_drush_dir.module</code> and an <code>.info</code> file with basic informations:</p>
<p><strong>update_drush_dir.info</strong></p>
<pre><code>name = Update Drush Directory
description = Update the $HOME variable each time a Drush command is launched.
core = 7.x
package = Drush
</code></pre>
<p>Once you have that, create a <code>update_drush_dir.drush.inc</code> file. <strong>That&apos;s the place where Drush will look for hook implementations</strong>, a <code>.module</code> file would not work in this case.</p>
<p><strong>update_drush_dir.drush.inc</strong></p>
<pre><code>&lt;?php 

/**
 * Implements hook_drush_init().
 */
function update_drush_dir_drush_init() {
  putenv(&apos;HOME=&apos; . DRUPAL_ROOT . &apos;/scripts/drush&apos;);
}
</code></pre>
<p>With this, you&apos;re pretty much set. The <code>drush_init</code> hook will run before each command and set the desired HOME path.</p>
<p>This example comes from an actual project where Drush is stored in <code>scripts/drush/</code> in the webroot. We choose to move the <code>.drush/</code> in this directory too.</p>
<p><strong>Don&apos;t forget to change the HOME variable to a path that&apos;s relevant for you!</strong></p>
<p>You can <a href="http://thedotwriter.com/static/update_drush_dir.zip">download an archive of the module here</a>.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Understanding #ajax_processed on Drupal 7 Form API]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Working on a complex multi-steps AJAX form? Stuck trying to attach AJAX to a field? You may as well be informed on the usage of the internal property <code>#ajax_processed</code>, it could help you understand what&apos;s going on behind the scene.</p>
<p>First, this property of the Form API</p>]]></description><link>http://thedotwriter.com/understand-ajax_processed-on-drupal-7-form-api/</link><guid isPermaLink="false">651835af9bb2470001ef2ca3</guid><dc:creator><![CDATA[Peeter RANNOU]]></dc:creator><pubDate>Sat, 18 Apr 2015 09:28:01 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Working on a complex multi-steps AJAX form? Stuck trying to attach AJAX to a field? You may as well be informed on the usage of the internal property <code>#ajax_processed</code>, it could help you understand what&apos;s going on behind the scene.</p>
<p>First, this property of the Form API is used by <code>ajax_pre_render_element()</code> located in <code>includes/ajax.inc</code>. <strong>It&apos;s here that Drupal will decide whether to attach AJAX to your field or not.</strong></p>
<p>I encourage you to open <a href="https://api.drupal.org/api/drupal/includes!ajax.inc/function/ajax_pre_render_element/7?ref=thedotwriter.com"><code>ajax_pre_render_element()</code> sources</a> on another tab. It may come in handy to better understand what I&apos;m talking about.</p>
<h2 id="whatsgoingon">What&apos;s going on?</h2>
<p>Let&apos;s keep it simple. Here&apos;s what&apos;s gonna happen based on the current state of <code>$element[&apos;#ajax_processed&apos;]</code>:</p>
<h3 id="ajax_processedisset">#ajax_processed is set</h3>
<p>If the <code>#ajax_processed</code> key already exists in the <code>$element</code> array, the function will stop and return the variable unchanged.<br>
It means Drupal already has examined the element earlier and attached libraries and AJAX settings if #ajax was set and values were correct.</p>
<h3 id="ajax_processedisnotset">#ajax_processed is not set</h3>
<p>If the <code>#ajax_processed</code> key does not already exist in the <code>$element</code> array, Drupal will determine its value.</p>
<h4 id="whenisajax_processedsettofalse">When is #ajax_processed set to <code>FALSE</code>?</h4>
<p>The <code>#ajax_processe</code> attribute is set to <code>FALSE</code> by default. Then, if the <code>#ajax</code> array doesn&apos;t contain valid settings, the function will end, returning <code>$element</code> with that only modification.</p>
<h4 id="whenisajax_processedsettotrue">When is #ajax_processed set to <code>TRUE</code>?</h4>
<p>For the attribute to switch from <code>FALSE</code> to <code>TRUE</code>, the <code>#ajax</code> array should have :</p>
<ul>
<li>A <code>&quot;callback&quot;</code> key storing the name of a callback function as a string.</li>
<li>A <code>&quot;path&quot;</code> key storing the link to the ajax callback page (usually &quot;system/ajax&quot;).</li>
<li>A <code>&quot;type&quot;</code> key storing the field type.</li>
<li>An <code>&quot;event&quot;</code> key (automatically defined earlier) storing the name of the DOM event to attach to the element from the browser.</li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Git Clone: Prompted for Password with TortoisePlink on Windows]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>If you get prompted for password by TortoisePlink each time you try to use <code>git clone</code>, even with the guest machine knowing your public key, the following could help you:</p>
<p><a href="http://www.computerhope.com/issues/ch000549.htm?ref=thedotwriter.com">Open the Environment Variable window</a> and check the value of <code>GIT_SSH</code>, TortoiseGit should have replaced the original program by</p>]]></description><link>http://thedotwriter.com/git-clone-prompted-password-tortoiseplink-windows/</link><guid isPermaLink="false">651835af9bb2470001ef2ca1</guid><dc:creator><![CDATA[Peeter RANNOU]]></dc:creator><pubDate>Tue, 19 Aug 2014 18:27:12 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>If you get prompted for password by TortoisePlink each time you try to use <code>git clone</code>, even with the guest machine knowing your public key, the following could help you:</p>
<p><a href="http://www.computerhope.com/issues/ch000549.htm?ref=thedotwriter.com">Open the Environment Variable window</a> and check the value of <code>GIT_SSH</code>, TortoiseGit should have replaced the original program by its own (TortoisePlink.exe). Locate the Git installation folder on your computer, copy the path of the <code>bin</code> directory and use it as the <code>GIT_SSH</code> value, the path could look like this:</p>
<pre><code>	C:\PATH TO PROGRAM FILES\Git\bin\ssh.exe
</code></pre>
<p>You may have to reboot your machine for the change to propagate but I&apos;m sure there&apos;s a better way to do it out there (if you know of one, feel free to share it in the comments!). Once the change is taken into account, <code>git clone</code> should behave correctly ;)</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[How to Use Hierarchical Select Hooks in Drupal 7]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Hierarchical Select differs from other modules when dealing with hooks, here&apos;s the right way to implement one.</p>
<p>First, each HS field implementation needs <strong>a set of functions</strong> to work. The needed functions are the following:</p>
<ul>
<li>hook_hierarchical_select_children</li>
<li>hook_hierarchical_select_params</li>
<li>hook_hierarchical_select_root_level</li></ul>]]></description><link>http://thedotwriter.com/how-to-use-hierarchical-select-hooks-in-drupal-7/</link><guid isPermaLink="false">651835af9bb2470001ef2c9d</guid><dc:creator><![CDATA[Peeter RANNOU]]></dc:creator><pubDate>Sun, 06 Jul 2014 15:53:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Hierarchical Select differs from other modules when dealing with hooks, here&apos;s the right way to implement one.</p>
<p>First, each HS field implementation needs <strong>a set of functions</strong> to work. The needed functions are the following:</p>
<ul>
<li>hook_hierarchical_select_children</li>
<li>hook_hierarchical_select_params</li>
<li>hook_hierarchical_select_root_level</li>
<li>hook_hierarchical_select_lineage</li>
<li>hook_hierarchical_select_valid_item</li>
<li>hook_hierarchical_select_item_get_label</li>
<li>hook_hierarchical_select_create_item</li>
<li>hook_hierarchical_select_entity_count</li>
<li>hook_hierarchical_select_implementation_info</li>
<li>hook_hierarchical_select_config_info</li>
</ul>
<h3 id="thecode">The code</h3>
<p>The first thing to do is to tell hierarchical_select that your module will provide the API for the field that you want to tweak. To achieve this, you can use hook_form_FORM_ID_alter() and put that line of code in it:</p>
<pre><code>$form[&apos;fieldname&apos;][LANGUAGE_NONE][&apos;#config&apos;][&apos;module&apos;] = &apos;my_module&apos;;</code></pre>
<p>Next, insert that code into your .module file :</p>
<pre><code>function mymodule_hierarchical_select_params() {
  return hs_taxonomy_hierarchical_select_params(); 
}
function mymodule_hierarchical_select_root_level($params, $dropbox = FALSE) {
  return hs_taxonomy_hierarchical_select_root_level($params, $dropbox); 
}
function mymodule_hierarchical_select_children($parent, $params, $dropbox = FALSE) {
  return hs_taxonomy_hierarchical_select_children($parent, $params, $dropbox = FALSE);
}
function mymodule_hierarchical_select_lineage($item, $params) {
  return hs_taxonomy_hierarchical_select_lineage($item, $params);
}
function mymodule_hierarchical_select_valid_item($item, $params) {
  return hs_taxonomy_hierarchical_select_valid_item($item, $params);
}
function mymodule_hierarchical_select_item_get_label($item, $params) {
  return hs_taxonomy_hierarchical_select_item_get_label($item, $params);
}
function mymodule_hierarchical_select_create_item($label, $parent, $params) {
  return hs_taxonomy_hierarchical_select_create_item($label, $parent, $params);
}
function mymodule_hierarchical_select_entity_count($item, $params) {
  return hs_taxonomy_hierarchical_select_entity_count($item, $params);
}
function mymodule_hierarchical_select_implementation_info() {
  return hs_taxonomy_hierarchical_select_implementation_info();
}
function mymodule_hierarchical_select_config_info() {
  return hs_taxonomy_hierarchical_select_config_info();
}
</code></pre>
<p>Now, your module provides all the API needed for the field to work. Find the hook that fits your needs, remove the call to the original function (only needed for the hooks you don&apos;t want to use), copy the code of the function from the core module and start altering it :)</p>
<p>Lastly, don&apos;t forget to replace <strong>&quot;mymodule&quot;</strong> and <strong>&quot;fieldname&quot;</strong> with the appropriate values!</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Create User with entity_metadata_wrapper() in Drupal 7]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Here&apos;s a little snippet to use when creating a new user with <strong>entity_metadata_wrapper()</strong>:</p>
<pre><code>// Get an empty object with the is_new attribute set to TRUE.
$user = entity_create(&apos;user&apos;, array());

// Define specific role IDs for the user.
$roles = array(3, 4, ...);

$user-&gt;name</code></pre>]]></description><link>http://thedotwriter.com/create-user-with-entity-metadata-wrapper-drupal-7/</link><guid isPermaLink="false">651835af9bb2470001ef2c9c</guid><dc:creator><![CDATA[Peeter RANNOU]]></dc:creator><pubDate>Tue, 18 Mar 2014 20:14:19 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Here&apos;s a little snippet to use when creating a new user with <strong>entity_metadata_wrapper()</strong>:</p>
<pre><code>// Get an empty object with the is_new attribute set to TRUE.
$user = entity_create(&apos;user&apos;, array());

// Define specific role IDs for the user.
$roles = array(3, 4, ...);

$user-&gt;name = &apos;username&apos;;
// Enable the user by default.
$user-&gt;status    = 1;
// Set nescessary role to let the user log in.
$user-&gt;roles     = drupal_map_assoc($roles + array(DRUPAL_AUTHENTICATED_RID));
// Set e-mail for lost password procedure.
$user-&gt;init      = &apos;foo@bar.com&apos;;
$user-&gt;mail      = &apos;foo@bar.com&apos;;
// Set hashed password.
$user-&gt;pass      = user_hash_password(&apos;password&apos;);

// Once we have enough data, set the wrapper around the user object.
$user = entity_metadata_wrapper(&apos;user&apos;, $user);

/**
 * Do your things.
 */
 
 // Save the user.
 $user-&gt;save();
 
</code></pre>
<p>With that, you have enough data to start using <strong>entity_metadata_wrapper()</strong>. Don&apos;t forget to check <a href="https://drupal.org/node/1021556?ref=thedotwriter.com">the doc on Drupal.org</a> for more info about setting fields value and so on.</p>
<p>Oh, and if you want the ID of the newly created user :<br>
<code>$uid = $user-&gt;getIdentifier();</code></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Entity Malformed Exception with field_attach_load() in Drupal 7]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>While using <a href="https://api.drupal.org/api/drupal/modules!field!field.attach.inc/function/field_attach_load/7?ref=thedotwriter.com">field_attach_load()</a> to <a title="Loading Only One Field From An Entity or Node in Drupal 7 | TimeOnWeb" href="http://timonweb.com/loading-only-one-field-from-an-entity-or-node?ref=thedotwriter.com" target="_blank">add not loaded fields to a node object</a>, I found myself stubling across that particular error multiple times :</p>
<blockquote>Entity Malformed Exception : Missing bundle property on entity of type node</blockquote>
<p>After spending hours trying to understand what was going on,&#xA0;<strong>twice</strong>, I decided that</p>]]></description><link>http://thedotwriter.com/entity-malformed-exception-with-field_attach_load-in-drupal-7/</link><guid isPermaLink="false">651835af9bb2470001ef2c89</guid><dc:creator><![CDATA[Peeter RANNOU]]></dc:creator><pubDate>Wed, 03 Jul 2013 10:00:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>While using <a href="https://api.drupal.org/api/drupal/modules!field!field.attach.inc/function/field_attach_load/7?ref=thedotwriter.com">field_attach_load()</a> to <a title="Loading Only One Field From An Entity or Node in Drupal 7 | TimeOnWeb" href="http://timonweb.com/loading-only-one-field-from-an-entity-or-node?ref=thedotwriter.com" target="_blank">add not loaded fields to a node object</a>, I found myself stubling across that particular error multiple times :</p>
<blockquote>Entity Malformed Exception : Missing bundle property on entity of type node</blockquote>
<p>After spending hours trying to understand what was going on,&#xA0;<strong>twice</strong>, I decided that publishing the solution of this problem <em>might</em> be a good idea.</p>
<p>The issue generaly comes from the structure of the <code>$entities</code> array passed to <a href="https://api.drupal.org/api/drupal/modules!field!field.attach.inc/function/field_attach_load/7?ref=thedotwriter.com">field_attach_load()</a>. Here&apos;s a good rule of thumb to easily get you out of trouble :</p>
<p>Before passing $entities to field_attach_load(), make sure that :</p>
<ul>
<li>The array is keyed by entity ID,</li>
<li>Each array item has at least those 2 keys/values :
<ul>
<li>&quot;type&quot;, with the entity bundle as value (&quot;node&quot; in our case),</li>
<li>&quot;nid&quot;, with the entity ID as value (change the key to &quot;tid&quot; in case of a taxonomy term or &quot;uid&quot; for a user entity).</li>
</ul>
</li>
</ul>
<p>After that, the error should disappear and never bother you again!</p>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>