<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet title="XSL formatting" type="text/xsl" href="https://uname.pingveno.net/blog/index.php/feed/rss2/xslt" ?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title># uname -a - Mot-clé - drupal</title>
    <link>https://uname.pingveno.net/blog/index.php/</link>
    <atom:link href="https://uname.pingveno.net/blog/index.php/feed/tag/drupal/rss2" rel="self" type="application/rss+xml" />
    <description>Le blog de uname.pingveno.net</description>
    <language>fr</language>
    <pubDate>Wed, 01 Apr 2026 16:19:15 +0200</pubDate>
    <copyright>Mathieu Pellegrin</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>Dotclear</generator>
          <item>
        <title>Drupal 8 / 9 / 10 : Programmatically render a view with contextual and exposed filters input</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2024/03/10/Drupal-8-/-9-/-10-%3A-The-right-way-to-programatically-render-a-view-while-setting-exposed-and-contextual-filters-input</link>
        <guid isPermaLink="false">urn:md5:28fceab459140a8a74e0ec4b7befc8fc</guid>
        <pubDate>Sun, 10 Mar 2024 19:45:00 +0100</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Informatique</category>
                          <category>drupal</category>
                  <category>drupal 10</category>
                  <category>drupal 8</category>
                  <category>drupal 9</category>
                  <category>php</category>
                <description>&lt;p&gt;&lt;strong&gt;Exposed Input&lt;/strong&gt; and &lt;strong&gt;Contextual Input&lt;/strong&gt; are two different ways of providing input to Drupal Views.&lt;/p&gt;

&lt;p&gt;Contextual filters work with an ordered list of parameters, while Exposed Input works with a form that has a couple name/value for every input parameter.&lt;/p&gt;          &lt;h2&gt;Contextual Filters&lt;/h2&gt;

&lt;p&gt;The right way to render a view result with &lt;strong&gt;contextual filters&lt;/strong&gt; is to generate a render array:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;
$render_array = [
  '#type' =&amp;gt; 'view',
  '#name' =&amp;gt; 'YOUR_VIEW_NAME',
  '#display_id' =&amp;gt; 'YOUR_VIEW_DISPLAY',
  '#arguments' =&amp;gt; [CONTEXTUAL_FILTER_1, CONTEXTUAL_FILTER_2, ...],
];&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can then send the render array to a Twig variable, or render it programatically:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;
$result = \Drupal::service('renderer')-&amp;gt;render($render_array);
return $result-&amp;gt;__toString();&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;We are using the &lt;code&gt;__toString()&lt;/code&gt; function to get the rendered HTML because the result returned by Drupal Render service is an object containing cache metadata.&lt;/p&gt;

&lt;h2&gt;Exposed Filters&lt;/h2&gt;

&lt;p&gt;The right way to render a view result with &lt;strong&gt;exposed filters&lt;/strong&gt; is to generate a render array, and set the &lt;code&gt;'#view#'&lt;/code&gt; parameter with a view object where you can initialize the filters:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;
$view = \Drupal\views\Views::getView('YOUR_VIEW_NAME');
$view-&amp;gt;setExposedInput([
    'YOUR_FILTER_NAME' =&amp;gt; 'YOUR_FILTER_VALUE',
]);
$render_array = [
  '#type' =&amp;gt; 'view',
  '#name' =&amp;gt; 'YOUR_VIEW_NAME',
  '#view' =&amp;gt; $view,
  '#display_id' =&amp;gt; 'YOUR_VIEW_DISPLAY',
  '#arguments' =&amp;gt; [CONTEXTUAL_FILTER_1, CONTEXTUAL_FILTER_2, ...],
];&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can then send the render array to a Twig variable, or render it programatically:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;
$result = \Drupal::service('renderer')-&amp;gt;render($render_array);
return $result-&amp;gt;__toString();&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;We are using the &lt;code&gt;__toString()&lt;/code&gt; function to get the rendered HTML because the result returned by Drupal Render service is an object containing cache metadata.&lt;/p&gt;

&lt;h2&gt;Leaked Metadata and Early Rendering&lt;/h2&gt;

&lt;p&gt;If you render a view while rendering a controller output that is suppose&amp;nbsp; to provide its own cache metadata (&lt;code&gt;CacheableJsonResponse&lt;/code&gt; for instance), and run on the error:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;
LogicException: The controller result claims to be providing relevant cache metadata, but leaked metadata was detected. Please ensure you are not rendering content too early.&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Just wrap the rendering in a render context:&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre&gt;
$context = new Drupal\Core\Render\RenderContext\RenderContext();
$html = \Drupal::service('renderer')-&amp;gt;executeInRenderContext($context, function () {
  $render_array = [
    '#type' =&amp;gt; 'view',
    '#name' =&amp;gt; 'YOUR_VIEW_NAME',
    '#display_id' =&amp;gt; 'YOUR_VIEW_DISPLAY',
    '#arguments' =&amp;gt; [CONTEXTUAL_FILTER_1, CONTEXTUAL_FILTER_2, ...],
  ];
  $result = \Drupal::service('renderer')-&amp;gt;render($render_array);
  return $result-&amp;gt;__toString();
});
&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;h2&gt;Sources&lt;/h2&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;https://drupal.stackexchange.com/a/295496&quot;&gt;https://drupal.stackexchange.com/a/295496&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;https://www.drupal.org/docs/drupal-apis/render-api/render-arrays&quot;&gt;https://www.drupal.org/docs/drupal-apis/render-api/render-arrays&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;https://api.drupal.org/api/drupal/10/search/setExposedInput&quot;&gt;https://api.drupal.org/api/drupal/10/search/setExposedInput&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;https://www.lullabot.com/articles/early-rendering-a-lesson-in-debugging-drupal-8&quot;&gt;https://www.lullabot.com/articles/early-rendering-a-lesson-in-debugging-drupal-8&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
        
              </item>
          <item>
        <title>Drupal 8 : create a custom Rule Action</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2016/07/27/Drupal-8-%3A-create-a-custom-Rule-action</link>
        <guid isPermaLink="false">urn:md5:4028da17989c185a5f86e2d3f8a25968</guid>
        <pubDate>Wed, 27 Jul 2016 10:56:00 +0200</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                          <category>action</category>
                  <category>drupal</category>
                  <category>drupal 8</category>
                  <category>module</category>
                  <category>php</category>
                  <category>rules</category>
                <description>          &lt;p&gt;Warning : the Rule plugin for Drupal 8 was not considered stable when I wrote this post.&lt;/p&gt;

&lt;h3&gt;1. Drupal 8: the new modules paradigm&lt;/h3&gt;

&lt;p&gt;Drupal 8 modules structure changed, and many modules are now using the new API.&lt;/p&gt;

&lt;p&gt;No more plain old functions name like hook_something, no more obscurous PHP for menu entries. Instead, Object Oriented programming, YAML configuration files, magic comments, and Symfony routing.&lt;/p&gt;

&lt;p&gt;Let's give it a try, let's make our first simplest module.&lt;/p&gt;

&lt;h3&gt;2. Base module configuration&lt;/h3&gt;

&lt;p&gt;If you already know how to do this, jumb to next section.&lt;/p&gt;

&lt;p&gt;Create a directory for your module, for instance &lt;strong&gt;mymodule&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Create an info file in YAML format : &lt;strong&gt;mymodule/mymodule.info.yaml&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;
name: 'My Module'
type: module
core: 8.x
package: Custom&lt;/pre&gt;

&lt;p&gt;You don't need more! You don't need routing as you will plug into Rules.&lt;/p&gt;

&lt;h3&gt;3. File names and Namespaces&lt;/h3&gt;

&lt;p&gt;Create the &lt;strong&gt;RulesAction&lt;/strong&gt; directory and its parents: &lt;strong&gt;mymodule/src/Plugin/RulesAction/&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a PHP file for your class: &lt;strong&gt;MyAction.php&lt;/strong&gt;. The class will be loaded with the autoload system.&lt;/p&gt;

&lt;p&gt;Edit the file you just created, and specify the namespace at the beginning of the file:&lt;/p&gt;

&lt;pre&gt;
/**
 * @file
 * Contains \Drupal\mymodule\Plugin\RulesAction\MyAction.
 */
namespace Drupal\mymodule\Plugin\RulesAction;
use Drupal\rules\Core\RulesActionBase;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;The namespace must correspond to your module name and class name!&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;4. Rule Action specifications and parameters&lt;/h3&gt;

&lt;p&gt;Comments are very important as they are also specifications. You will define your Action id, description, and parameters. For instance, here is a copied sample from the predefined action DataSet:&lt;/p&gt;

&lt;pre&gt;
/**
 * Provides a 'My action' action.
 *
 * @RulesAction(
 *   id = &quot;rules_myaction&quot;,
 *   label = @Translation(&quot;Set a data value&quot;),
 *   category = @Translation(&quot;Data&quot;),
 *   context = {
 *     &quot;data&quot; = @ContextDefinition(&quot;any&quot;,
 *       label = @Translation(&quot;Data&quot;),
 *       description = @Translation(&quot;Specifies the data to be modified using a data selector, e.g. 'node:author:name'.&quot;),
 *       allow_null = TRUE,
 *       assignment_restriction = &quot;selector&quot;
 *     ),
 *     &quot;value&quot; = @ContextDefinition(&quot;any&quot;,
 *       label = @Translation(&quot;Value&quot;),
 *       description = @Translation(&quot;The new value to set for the specified data.&quot;),
 *       default_value = NULL,
 *       required = FALSE
 *     )
 *   }
 * )
 */
&lt;/pre&gt;

&lt;p&gt;The Rule id is &lt;strong&gt;rules_myaction&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The category of the action in the dropdown menu is &lt;strong&gt;Data&lt;/strong&gt; and it will be labeled &lt;strong&gt;Set a data value&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The current action will have two parameters : the data that will be changed, and the corresponding value.&lt;/p&gt;

&lt;h3&gt;5. Rule Action callback&lt;/h3&gt;

&lt;p&gt;Again, no more plain callback, the function &lt;strong&gt;doExecute&lt;/strong&gt; will be called to execute your Action:&lt;/p&gt;

&lt;pre&gt;
class MyAction extends RulesActionBase {

  /**
   * Executes the Plugin.
   *
   * @param mixed $data
   *   Original value of an element which is being updated.
   * @param mixed $value
   *   A new value which is being set to an element identified by data selector.
   */
  protected function doExecute($data, $value) {
    $typed_data = $this-&amp;gt;getContext('data')-&amp;gt;getContextData();
    $typed_data-&amp;gt;setValue($value);
  }

  /**
   * {@inheritdoc}
   */
  public function autoSaveContext() {
    // Saving is done at the root of the typed data tree, for example on the
    // entity level.
    $typed_data = $this-&amp;gt;getContext('data')-&amp;gt;getContextData();
    $root = $typed_data-&amp;gt;getRoot();
    $value = $root-&amp;gt;getValue();
    // Only save things that are objects and have a save() method.
    if (is_object($value) &amp;amp;&amp;amp; method_exists($value, 'save')) {
      return ['data'];
    }
    return [];
  }

}&lt;/pre&gt;

&lt;p&gt;The class name has to correspond to your file name.&lt;/p&gt;

&lt;p&gt;In this sample, the parameter &lt;strong&gt;$value&lt;/strong&gt; will be set to &lt;strong&gt;$data&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;6. Troubleshooting&lt;/h3&gt;

&lt;pre&gt;
Uncaught PHP Exception Drupal\\Component\\Plugin\\Exception\\PluginException: &quot;Plugin (rules_myaction) instance class &quot;Drupal\\tbh_system\\Plugin\\RulesAction\\MyAction&quot; does not exist.&quot;&lt;/pre&gt;

&lt;p&gt;Your namespace/classname/filename/directoryname is probably wrong.&lt;/p&gt;

&lt;h3&gt;Source&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://fago.gitbooks.io/rules-docs/content/extending_rules/rules_action_plugins.html&quot; hreflang=&quot;en&quot;&gt;Drupal 8 Rules Action documentation&lt;/a&gt;&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>About ToBeHost : the last of my student's projects</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2015/09/24/About-ToBeHost-%3A-the-last-of-my-student-s-projects</link>
        <guid isPermaLink="false">urn:md5:1e13d19d1de92f79d00916da194c7137</guid>
        <pubDate>Thu, 01 Oct 2015 23:55:00 +0200</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>My Life</category>
                          <category>debian</category>
                  <category>drupal</category>
                  <category>hack</category>
                  <category>puppet</category>
                  <category>serie-hosting-panel-drupal-puppet</category>
                  <category>tobehost</category>
                  <category>vhffs</category>
                <description>&lt;p&gt;Hello there, this is not your ordinary reading on this blog. This post is a sort of introduction for a series of posts about the making of a free web hosting provider, implementing a web panel from scratch using &lt;a href=&quot;https://www.drupal.org/&quot;&gt;Drupal&lt;/a&gt; for front-end and &lt;a href=&quot;https://puppetlabs.com/&quot;&gt;Puppet&lt;/a&gt; as back-end.&lt;/p&gt;&lt;p&gt;But first, let me introduce you the reason why we started the project. I said &amp;#8220;we&amp;#8221; because I am not the only one in the boat, but it&amp;#8217;s me who will make all the technical choices, and implement it. I am also the one who was saying &amp;#8220;give up&amp;#8221; to my colleague a few months ago, before going back with this new and exciting crazy idea.&lt;/p&gt;          &lt;h3&gt;Genesis&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;http://www.tobehost.net/&quot;&gt;ToBeHost&lt;/a&gt; is a project we started around 2008~2009. Before that, I was an active member at a free hosting provider (&amp;#8220;Chez Mémé .net&amp;#8221;). When this hosting provider closed, due to the lack of time from its founders, me and a friend I met on this hosting provider stated that we had both the technical and time resources to make our own hosting provider. It was just loaning a dedicated server and configuring all the stuff you need to have your site working. We were not experts (yet), but be were confident in the fact that we had the capacities to learn, and to make it working. This is also the moment where I started &lt;a href=&quot;http://www.catb.org/esr/faqs/hacker-howto.html&quot;&gt;hacking&lt;/a&gt; on GNU/Linux&lt;/p&gt;&lt;p&gt;We tried several web panels. Between love and hate, we finally choose &lt;a href=&quot;http://www.vhffs.org&quot;&gt;VHFFS&lt;/a&gt;. VHFFS is a great piece of software. For the kiddie I was, it was the sort of &amp;#8220;perfect-even-scary&amp;#8221; piece of Linux engineering. Because mass web hosting involves dealing with a lot of &amp;#8220;subsystems&amp;#8221; to make it work, what VHFFS was doing was simply amazing to me. Using &lt;em&gt;libnss&lt;/em&gt; and &lt;em&gt;nscd&lt;/em&gt; to make system user from a database was for me the cleverest way to make system users without having to deal with system commands. Using unix permissions and system users and groups instead of hacky chroots, safe_mode, and open_basedir was definitely feeling right to me. I learned a lot about Linux and Debian, and my first (and actually unique) &lt;a href=&quot;http://listengine.tuxfamily.org/vhffs.org/vhffs-dev/2011/07/msg00025.html&quot;&gt;contributed patch&lt;/a&gt; made me feel so proud of me.&lt;/p&gt;&lt;h3&gt;The long love (and hate) story&lt;/h3&gt;&lt;p&gt;Dealing with a single server, on a student time, was not complicated. When something went wrong, I was looking for the answer by myself because I was (and I am still) afraid of what people can think or say to me on a public IRC channel. We had some downtimes, and a few fears while restoring backups, but things were globally going well.&lt;/p&gt;&lt;p&gt;Some things were a little bit cumbersome, but I was thinking that it was part of the job. Re-compiling PureFTPD ans MySQL package at each upgrade was not actually a problem, because I was eager to learn how to patch, compile, and hack into Debian. I even &lt;a href=&quot;http://uname.pingveno.net/wiki/wiki.php/Vhffs_Nss&quot;&gt;rewrote the SQL queries when we upgraded to Debian Lenny&lt;/a&gt;, which was using libnss2.&lt;/p&gt;&lt;p&gt;The years passed, I was growing and becoming older (hey, don&amp;#8217;t laugh). My years at university was taking much and much time over my &amp;#8220;internet time&amp;#8221;, as I was getting involved in the students&amp;#8217; association and my final exams were approaching. Finally, the project was in an informal standby, we decided that we had to close it, because we were both very busy elsewhere.&lt;/p&gt;&lt;p&gt;We officially closed. We sent the mail to users, I was ready to backup my configuration files and delete the data. We didn&amp;#8217;t do it. Because of our sloppy feelings, and the fact that &amp;#8220;it worked&amp;#8221;, without &amp;#8220;touching anything&amp;#8221;. It was such a pity to let it go.&lt;/p&gt;&lt;h3&gt;The last breath (or not)&lt;/h3&gt;&lt;p&gt;Some months ago, we realized it had been several years that the project was officially dead. I didn&amp;#8217;t stop hacking Linux. I had left my full-time job because I was working too much on projects I didn&amp;#8217;t like (&lt;a class=&quot;ref-post&quot; href=&quot;https://uname.pingveno.net/blog/index.php/post/2013/02/01/Pourquoi-j-ai-chang%C3%A9-de-job&quot;&gt;and some other reasons&lt;/a&gt;), and was running a freelance activity. My colleague was running &lt;a href=&quot;http://hawaii.do/&quot;&gt;a successful IT company&lt;/a&gt; with his associates, and we were working together on some professional projects (we still are).&lt;/p&gt;&lt;p&gt;New tools and software have appeared since my last glance to ToBeHost, and I also learned how to use new tools. I asked my colleague to let the project go, but we finally paid another month for the server.&lt;/p&gt;&lt;p&gt;And then, I thought: web hosting is actually what I am into at that time. I know how to do it the right way, with the smallest administration effort. None of the alternative panels was fitting as well as VHFFS for the work we wanted. Let&amp;#8217;s take all the VHFFS goods (strictly unix permissions, not be afraid of user access to shell, trust user isolation and quota), and add some bullshit (PHP panel, made on top of a CMS), with a little bit of magic (Puppet automation). Let&amp;#8217;s put it together, and see what is coming from it.&lt;/p&gt;&lt;p&gt;Voilà. This is how this project started.&lt;/p&gt;&lt;h3&gt;Addendum&lt;/h3&gt;&lt;p&gt;The project started, and it is pratically ready for beta-test. I will try to write that series of posts and explain how we made it, in order to inspire other people, and to help me keep my ideas clear.&lt;/p&gt;&lt;p&gt;As you may think, it is and it will be &lt;strong&gt;highly experimental&lt;/strong&gt;. I don&amp;#8217;t know if the growing of Puppet objects will be sustainable in the long term. I don&amp;#8217;t know if Drupal will drive me crazy to the point I would rage delete my code. I don&amp;#8217;t know if the whole project will be clean enough to release it opensource. But we will &lt;strong&gt;try&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://www.tobehost.net/nous-contacter/&quot;&gt;Wanna join&lt;/a&gt;&amp;#160;?&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Drupal 7 : create your own image effect for use in image styles</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2015/02/25/Drupal-7-%3A-create-your-own-image-effect-for-use-in-image-styles</link>
        <guid isPermaLink="false">urn:md5:07800b84eeef05debd24db6354b32e72</guid>
        <pubDate>Wed, 25 Feb 2015 18:56:00 +0100</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                          <category>drupal</category>
                  <category>drupal 7</category>
                  <category>effect</category>
                  <category>image</category>
                  <category>module</category>
                  <category>php</category>
                  <category>style</category>
                <description>&lt;p&gt;Drupal comes with many predefined effects, you can combine them in image styles to get the picture you want. But what if you have to make your own effect&amp;#160;? Here is how.&lt;/p&gt;          &lt;h3&gt;Step 1&amp;#160;: create a module&lt;/h3&gt;

&lt;p&gt;If you are a drupal developer, you should know how to make a module. Okay, I am lazy too&amp;#160;:&lt;/p&gt;

&lt;p&gt;myeffect.info&amp;#160;:&lt;/p&gt;

&lt;pre&gt;
name = My Effect
description = &quot;My wonderful border effect&quot;
core = 7.x
dependencies[] = image
files[] = myeffect.module
package = Media&lt;/pre&gt;

&lt;h3&gt;Step 2&amp;#160;: declare your effect&lt;/h3&gt;

&lt;p&gt;Implement hook_image_effect_info&amp;#160;:&lt;/p&gt;

&lt;pre&gt;
function myeffect_image_effect_info() {
  $effects = array(
    'myeffect_image_border' =&amp;gt; array(
      'label' =&amp;gt; t('My Effect - Border'),
      'help' =&amp;gt; t('Add border to an image'),
      'effect callback' =&amp;gt; '_myeffect_image_border_effect',
// Let's make things simpler...
//      'form callback' =&amp;gt; '_myeffect_image_border_form',
//      'summary theme' =&amp;gt; '_myeffect_image_border_summary',
    ),
  );
  return $effects;
}&lt;/pre&gt;

&lt;h3&gt;Step 3&amp;#160;: write the callback&lt;/h3&gt;

&lt;pre&gt;
function _myeffect_image_border_effect(&amp;amp;$image, $data) {
  if (!_myeffect_image_border($image, $data)) {
    watchdog('image', 'Image add border failed using the %toolkit toolkit on %path (%mimetype)', array(
      '%toolkit' =&amp;gt; $image-&amp;gt;toolkit,
      '%path' =&amp;gt; $image-&amp;gt;source,
      '%mimetype' =&amp;gt; $image-&amp;gt;info['mime_type'],
    ), WATCHDOG_ERROR);
    return FALSE;
  }
  return TRUE;
}

function _myeffect_image_border(stdClass $image, $data) {
  if ($image-&amp;gt;toolkit == 'gd') {
    $params = array($image, $data);
    return call_user_func_array('_myeffect_gd_border', $params);
  } else {
    watchdog('image', 'The selected image handling toolkit %toolkit can not correctly process %function.', array(
      '%toolkit' =&amp;gt; $image-&amp;gt;toolkit,
      '%function' =&amp;gt; $function,
    ), WATCHDOG_ERROR);
    return FALSE;
  }
}&lt;/pre&gt;

&lt;h3&gt;Step 4&amp;#160;: make your effect&amp;#160;!&lt;/h3&gt;

&lt;pre&gt;
function _myeffect_gd_border(stdClass $image, $data) {

  $width = $image-&amp;gt;info['width'];
  $height = $image-&amp;gt;info['height'];

  // Note : source image is in $image-&amp;gt;resource
  $dst = imagecreatetruecolor($width, $height);

...

  // Update image object.
  $image-&amp;gt;resource = $dst;
  $image-&amp;gt;info['width'] = $width;
  $image-&amp;gt;info['height'] = $height;

  return TRUE;
}&lt;/pre&gt;

&lt;h3&gt;Source&lt;/h3&gt;

&lt;p&gt;The content of this article is widely based on the module &lt;a href=&quot;https://www.drupal.org/project/iek&quot; hreflang=&quot;en&quot;&gt;Image Effect Kit&lt;/a&gt;, you can download and read it for a more complete example.&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Drupal 7 : integrate a simple payment workflow with Payment module</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2014/11/29/Drupal-7-%3A-integrate-simple-payment-workflow-with-Payment-module</link>
        <guid isPermaLink="false">urn:md5:1d273e31cb8859a6da7277af121d620f</guid>
        <pubDate>Fri, 05 Dec 2014 15:00:00 +0100</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                          <category>drupal</category>
                  <category>drupal 7</category>
                  <category>module</category>
                  <category>payment</category>
                  <category>webshop</category>
                <description>&lt;p&gt;Payment forms are common these days, and Drupal has already many out-of-the-box modules to implement a web shop.&lt;/p&gt;&lt;p&gt;But these modules are often very cumbersome, complicated, and not-so-easy to tweak for your own needs.&lt;/p&gt;&lt;p&gt;So, let&amp;#8217;s (re)start from the beginning: let&amp;#8217;s implement our own Payment form with Payment, and throw Ubercart, Commerce, and all his friends away.&lt;/p&gt;&lt;p&gt;Note that the use of Payment is compatible with Ubercart and Commerce, but please let me make it simpler.&lt;/p&gt;          &lt;h3&gt;Install Payment and Currency&lt;/h3&gt;&lt;p&gt;Download and install &lt;a hreflang=&quot;en&quot; href=&quot;https://www.drupal.org/project/payment&quot;&gt;Payment&lt;/a&gt; and &lt;a hreflang=&quot;en&quot; href=&quot;https://www.drupal.org/project/currency&quot;&gt;Currency&lt;/a&gt;&amp;#160;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a hreflang=&quot;en&quot; href=&quot;https://www.drupal.org/project/payment&quot;&gt;https://www.drupal.org/project/payment&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a hreflang=&quot;en&quot; href=&quot;https://www.drupal.org/project/currency&quot;&gt;https://www.drupal.org/project/currency&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Or using Drush&amp;#160;: &lt;code&gt;drush dl payment currency&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Don&amp;#8217;t forget to enable your new modules Payment and Currency. Note that Payment has several submodules, I don&amp;#8217;t need them for this example.&lt;/p&gt;&lt;h3&gt;Download the payment method(s) you need&lt;/h3&gt;&lt;p&gt;Payment only gives the workflow. Payment comes with several Payment methods available, that are implementing Payment API to hook into the workflow. The topic is integrting Payment, not writting a payment method, so you can choose whatever method(s) you want from the &lt;a hreflang=&quot;en&quot; href=&quot;https://www.drupal.org/project/payment&quot;&gt;Payment project page&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;In this example, I will use Paypal. So if you are still with me, download paypal_payment&amp;#160;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a hreflang=&quot;en&quot; href=&quot;https://www.drupal.org/project/paypal_payment&quot;&gt;https://www.drupal.org/project/paypal_payment&lt;/a&gt;&lt;/li&gt;&lt;li&gt;or using drush&amp;#160;:&lt;code&gt; drush dl paypal_payment&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;PayPal Payment has several submodules, enable all available PayPal Payment submodules.&lt;/p&gt;&lt;h3&gt;Create a module to set up the form&lt;/h3&gt;&lt;p&gt;Inside the module, let&amp;#8217;s make the form. Two solutions: either use the standalone form provided by the module to make a simple payment, or integrate the payment to your own existing form.&lt;/p&gt;&lt;h4&gt;Using the standalone form&lt;/h4&gt;&lt;p&gt;Using the standalone form is pretty straightforward, make a form builder callback function like this:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;function _mycheckoutmodule_form($form, &amp;amp;$form_state, $nid) {&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $payment = new Payment(array(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'context_data' =&amp;gt; array( // Add whatever you want in this array, this is passed to the payment method. If your are using Paypal Payment method, these informations are also POSTed to Paypal&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'nid' =&amp;gt; $nid,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'currency_code' =&amp;gt; 'CHF',&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'description' =&amp;gt; t('Product description'),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'finish_callback' =&amp;gt; '_mycheckoutmodule_payment_complete', // The function providing the page where the user is redirected after the payment&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $payment-&amp;gt;setLineItem(new PaymentLineItem(array(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'amount' =&amp;gt; 20,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'name' =&amp;gt; t('Product name'),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'description' =&amp;gt; t('Product description'),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'tax_rate' =&amp;gt; '0.2',&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'quantity' =&amp;gt; 1,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $form = payment_form_standalone($form, $form_state, $payment);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return $form;&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h4&gt;Integrate with your existing form&lt;/h4&gt;&lt;p&gt;Again, simply change your form builder callback:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;function _mycheckoutmodule_form($form, &amp;amp;$form_state, $node) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // My simple form only has 'email' item&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $form['email'] = array(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; '#type' =&amp;gt; 'textfield',&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; '#title' =&amp;gt; t('Email'),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; '#required' =&amp;gt; true,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; '#element_validate' =&amp;gt; array('_mycheckoutmodule_email_element_validate'), // Please, implement this&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $payment = new Payment(array(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'context_data' =&amp;gt; array( // Add whatever you want in this array, this is passed to the payment method. If you are using Paypal Payment method, these informations are also POSTed to Paypal&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'nid' =&amp;gt; $nid,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'currency_code' =&amp;gt; 'CHF',&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'description' =&amp;gt; t('Product description'),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'finish_callback' =&amp;gt; '_mycheckoutmodule_payment_complete', // The function giving the page wher ethe user is redirected ater the payment&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $payment-&amp;gt;setLineItem(new PaymentLineItem(array(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'amount' =&amp;gt; 20,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'name' =&amp;gt; t('Product name'),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'description' =&amp;gt; t('Product description'),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'tax_rate' =&amp;gt; '0.2',&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'quantity' =&amp;gt; 1,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $form_info = payment_form_embedded($form_state, $payment);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $form = array_merge($form, $form_info['elements']);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // I have a specific #submit callback, so I have to add it, but if you don't have one, just skip theses lines&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $form['#submit'] = array_merge(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array('mycheckoutmodule_form_submit'),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $form_info['submit'],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; array('payment_form_standalone_submit')&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; );&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $form['submit'][] = array(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; '#type' =&amp;gt; 'submit',&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; '#value' =&amp;gt; t('Buy now!'),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; );&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $form['#validate'][] = 'mycheckoutmodule_form_validate'; // You should know how to implement this.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return $form;&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h3&gt;Call your form and display it&lt;/h3&gt;&lt;p&gt;I added a parameter to the form builder function, didn&amp;#8217;t you notice&amp;#160;? Actually I am getting the NID of the product the user wants to purchase, so I pass it to the form builder function.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;// Call the form builder&lt;br /&gt;$form_build = drupal_get_form('_mycheckoutmodule_form', $nid);&lt;br /&gt;$checkout_form = render($form_build);&lt;br /&gt;echo $checkout_form; // Or pass it to a theme&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h3&gt;The &amp;#8220;thank you for your purchase&amp;#8221; page&lt;/h3&gt;&lt;p&gt;The return page after the payment is handled by the function you specified while creating the Payment object.&lt;/p&gt;&lt;p&gt;If the user correctly gets back to the website (keep in mind it&amp;#8217;s not always the case), you have access to the context data you passed to the Payment object, along with the Payment method return codes (given by the payment provider). You can use it to build your &amp;#8220;thank you&amp;#8221; page&amp;#160;:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;function _mycheckoutmodule_payment_complete($payment) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; watchdog('mycheckoutmodule', '&quot;Thank you&quot; displayed for payment ' . $payment-&amp;gt;pid . '.', array(), WATCHDOG_INFO); // Let's spam the logs&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($payment-&amp;gt;statuses[count($payment-&amp;gt;statuses)-1]-&amp;gt;status == 'payment_status_success') { // Actually pretty bad, but statuses stacks in the stored Payment object&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; drupal_set_message('Your payment has been received.', 'success');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; drupal_goto('node/' . $payment-&amp;gt;context_data['nid']);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; drupal_set_message('Your payment is not yet validated, please wait.', 'warning');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; drupal_goto('node/' . $payment-&amp;gt;context_data['nid']);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h3&gt;Check if the Payment succeeded&lt;/h3&gt;&lt;h4&gt;IPN URL (for Paypal)&lt;/h4&gt;&lt;p&gt;If you are using the Paypal payment method, you have to set up your Paypal account with the following URL&amp;#160;: &lt;code&gt;http://yoursite.com/paypal_payment_pps/return&lt;/code&gt;&lt;/p&gt;&lt;h4&gt;The callback function&lt;/h4&gt;&lt;p&gt;The IPN processing is abstracted by Payment module. Payment can provide you informations about current payment by using the Payment objects stored in Drupal&amp;#8217;s database. So, process the payment when receiving the callback&amp;#160;:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;function _mycheckoutmodule_payment_status_changed($payment) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; watchdog('mycheckoutmodule', 'Status for payment ' . $payment-&amp;gt;pid . ' changed.', array(), WATCHDOG_INFO); // Let's spam the logs&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($payment-&amp;gt;statuses[count($payment-&amp;gt;statuses)-1]-&amp;gt;status == 'payment_status_success') {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; watchdog('mycheckoutmodule', 'Status for payment ' . $payment-&amp;gt;pid . ' detected completed.', array(), WATCHDOG_INFO); // spam, spam!&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mycheckoutmodule_process_delivery($payment-&amp;gt;context_data['nid']); // You should implement this to do something once the payment is received&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;You can have a list of the available statuses in the file &lt;code&gt;sites/all/modules/contrib/payment/payment/payment.payment.inc&lt;/code&gt;&lt;/p&gt;&lt;h4&gt;The callback Rule&lt;/h4&gt;&lt;p&gt;I didn&amp;#8217;t find how to get the callback function triggering using an hook to Payment API. But Payment provides Rules conditions to handle the callbacks, let&amp;#8217;s use it.&lt;/p&gt;&lt;p&gt;You can programmatically add a rule to your module, but if you are a lazy man like me, just add it from Rules UI&amp;#160;: define a condition &amp;#8220;payment status changed&amp;#8221; and action &amp;#8220;execute PHP&amp;#8221; to call your function&amp;#160;:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;_mycheckoutmodule_payment_status_changed($payment);&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h3&gt;Known bugs&lt;/h3&gt;&lt;p&gt;There are some cutting edge while using this module&amp;#160;: I didn&amp;#8217;t succeeded at having the price rounded while using the &amp;#8220;tax&amp;#8221; argument. As a walkaround, you can just skip the &amp;#8220;tax&amp;#8221; argument of the form, or set it to 0. You need a simple form, so you maybe you don&amp;#8217;t bother about dislaying the tax rate or not.&lt;/p&gt;</description>
        
              </item>
          <item>
        <title>Drupal 7 : change page title on node form</title>
        <link>https://uname.pingveno.net/blog/index.php/post/2014/11/10/Drupal-%3A-change-page-title-on-node-form</link>
        <guid isPermaLink="false">urn:md5:8b7c0fea8cafc55192f6b58aac77c5a4</guid>
        <pubDate>Mon, 10 Nov 2014 11:19:00 +0100</pubDate>
        <dc:creator>Mathieu</dc:creator>
                  <category>Hacks</category>
                          <category>drupal</category>
                  <category>php</category>
                <description>          &lt;p&gt;Every rule has its exceptions, setting &lt;code&gt;drupal_set_title&lt;/code&gt; directly on form_alter doesn&amp;#8217;t work for node form title. To customize pages like &amp;#8220;Add node&amp;#8221;, or &amp;#8220;Edit node&amp;#8221;&amp;#160;:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;p&gt;Make a module&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add a function to implement hook_form_alter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add a form afterbuild in your hook_form_alter implementation&lt;/strong&gt;: &lt;code&gt;$form['#after_build'][] = '_my_callback_form_set_title'&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In &lt;code&gt;'_my_callback_form_set_title'&lt;/code&gt;, use &lt;code&gt;drupal_set_title&lt;/code&gt; to change the form title: &lt;code&gt;drupal_set_title(...)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Update system table to have the weight of your module greater than Node module&lt;/strong&gt; (on a default install, core modules are weighted 0, so set your module weight to 1).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rebuild registry, clear caches.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
        
              </item>
      </channel>
</rss>
