Programming https://janezurevc.name/ en Multi-file uploads in Drupal 8? https://janezurevc.name/multi-file-uploads-drupal-8 <span>Multi-file uploads in Drupal 8?</span> <span><span lang="" about="https://janezurevc.name/users/slashrsm" typeof="schema:Person" property="schema:name" datatype="" xml:lang="">slashrsm</span></span> <span>Sun, 03.02.2013 - 19:39</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><p>EDIT (20.4.2013): This <a href="https://drupal.org/node/625958#comment-7323412">has been committed</a> and is now part of D8 core.</p> <p>Back at DrupalCon Munich code sprint I started to work<a href="https://drupal.org/node/625958"> on a core issue </a>that is focused on implementing <a href="https://www.w3.org/TR/html-markup/input.file.html#input.file.attrs.multiple">HTML5 multiple uploads support</a> in Drupal. Since I've always been interested in file handling I immediatley found this very attractive. From the other hand I always strugeled when it comes to files in Drupal. There are so many solutions and none of them is really user friendly. I thought that this feature would make Drupal's UX much better. During my travel back home from Munich and the days after I spent some time working on the issue, but then it stuck somwhere in the middle due to my lack of time.</p> <p>In January I started to work for <a href="https://examiner.com">Examiner.com</a> where I got so-called Drupal day at the end of every sprint. That helped me to focus on this issue once again (and I am very thankful for that). During last 2 or 3 weeks I managed to finish the patch (in terms of features):</p> <ul><li>file and managed_file FAPI elements have been updated to accept #multiple option. Once this option is enabled element adds "multiple" argument to it's input tag, which enables multi-file uploads in recent versions of all major browsers. Old browsers should gracefully degrade to single-upload without any problems. </li> <li>File & Image field widgets leverage new #multiple option in it's underlaying form elements to improve experience for multi-value fields. Users will no longer upload galleries on file at a time. Everything can be now done in a single step.</li> <li>Existing tests were corrected to pass with newly added features (FAPI element behaviour changed a bit).</li> </ul><p>I've already been testing, but patch still needs a lot of testing and reviews. More information can be found<a href="https://drupal.org/node/625958"> in the issue queue</a>.</p> </div> Sun, 03 Feb 2013 18:39:01 +0000 slashrsm 55 at https://janezurevc.name Drupal's Plupload integration - file_validate() https://janezurevc.name/drupals-plupload-integration-filevalidate <span>Drupal's Plupload integration - file_validate()</span> <span><span lang="" about="https://janezurevc.name/users/slashrsm" typeof="schema:Person" property="schema:name" datatype="" xml:lang="">slashrsm</span></span> <span>Mon, 19.11.2012 - 09:39</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><p><a href="https://drupal.org/user/78090">Kevin Hankens</a> posted <a href="https://drupal.org/node/1814744">an issue</a> in <a href="https://drupal.org/project/plupload">Plupload's integration module</a> a while ago. He complained about the way how module invokes <em>file_validate()</em> at uploads. After a bit of research I agreed with him. </p> <p>Plupload module invokes <em>file_validate()</em> with file object that carries nonexistent file uri. Uri, that is passed to validation, is representing a location where file <strong>is supposed to be uploaded</strong>. At that moment the file is actually located on a completely different (temporary) location. Validation hooks are unable to load file and do various of operations as a result of this.</p> <p>We propose a patch that fixes this. Problem is, that this solution also breaks API compatibility. As this issue definitely needs to be fixed, I'd still not like to commit something, that would make people willing to kill me. :)</p> <p>I invite all developers with interest in Plupload to check <a href="https://drupal.org/node/1814744">this issue</a> and provide feedback. </p> </div> Mon, 19 Nov 2012 08:39:36 +0000 slashrsm 50 at https://janezurevc.name Relation Migrate integration and *reference upgrade path https://janezurevc.name/relation-migrate-integration-and-reference-upgrade-path <span>Relation Migrate integration and *reference upgrade path</span> <span><span lang="" about="https://janezurevc.name/users/slashrsm" typeof="schema:Person" property="schema:name" datatype="" xml:lang="">slashrsm</span></span> <span>Mon, 06.08.2012 - 23:35</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><p>There was<a href="https://drupal.org/node/1606404#comment-6305944"> my patch</a> <a href="https://drupalcode.org/project/relation.git/commit/79571cc">committed</a> to <a href="https://drupal.org/project/relation">Relation module</a> (which is great - if you have not tried it yet definitely do) today, that adds <a href="https://drupal.org/project/migrate">Migrate</a> support to Relation and uses it to provide upgrade path from Term/<a href="https://drupal.org/project/references">User/Node</a>/<a href="https://drupal.org/project/entityreference">Entity</a> reference fields to Relation. I hope that this feature will be useful to a lot of people. In order to use new functionality you'd need to enable <em>Relation migrate</em>, which comes together with Relation.</p> <p><a href="https://janezurevc.name/sites/default/files/enable_relation_migrate.png"><br /><img src="https://janezurevc.name/sites/default/files/enable_relation_migrate.png" data-entity-type="file" data-entity-uuid="d38843c3-d3a0-4dd5-b705-5f3ef54f74c6" /></a></p> <h2>Migrate integration</h2> <p>Module implements class <a href="https://drupalcode.org/project/relation.git/blob/refs/heads/7.x-1.x:/relation_migrate/relation_migrate.migration.inc#l8"><em>MigrateDestinationRelation</em></a>, which is a destination plugin for Migrate. You can use this class in your custom migrate scripts in a very similar way as you'd use <a href="https://drupalcode.org/project/migrate.git/blob/refs/heads/7.x-2.x:/plugins/destinations/node.inc#l14"><em>MigrateDestinationNode</em></a>, which is most likely used when migrating nodes. The only difference will be in mapping, which should be done in<em> </em><em>prepare()</em> or <em>prepareRow().</em> This is required because of the complexity of <em>relation_endpoint</em> field, which requires a lot of information in order to properly build a relation. Here is an example of typical mapping definition:</p> <pre> public function prepare(stdClass $relation, stdClass $source_row) { $relation->endpoints[LANGUAGE_NONE] = array( array('entity_type' => $source_row->source_type, 'entity_id' => $source_row->source_id), array('entity_type' => $source_row->destination_type, 'entity_id' => $source_row->destination_id), ); } </pre><p>This example is taken from <a href="https://drupalcode.org/project/relation.git/blob/refs/heads/7.x-1.x:/relation_migrate/relation_migrate.migration.inc#l49">actual implementation</a> of *reference upgrade path in <em>Relation migrate</em>.</p> <h2>Term/User/Node/Entity reference upgrade path</h2> <p><a href="https://janezurevc.name/sites/default/files/relation_type.png"><img alt="" data-entity-type="file" data-entity-uuid="bbdfafac-fd54-43a2-8905-5e26f77d9c04" src="https://janezurevc.name/sites/default/files/styles/large/public/relation_type.png" /></a></p> <p>A typical request by people thinking about using Relation on their existing sites is upgrade path from *reference modules. Migrate integration now allows us to do this. You shouldn't spend more than a few clicks to have this done. I will demonstrate this feature on a standard Drupal 7 installation. I have generated 50 nodes that are tagged with taxonomy terms. This is done via <em>field_tags</em> field, which is obviously a <em>Taxonomy reference.</em> I will first create new Relation type and configure it to allow relations from nodes to terms.</p> <p><a href="https://janezurevc.name/sites/default/files/relation_configuration.png"><img alt="" data-entity-type="file" data-entity-uuid="32ab0464-4653-48ee-9b00-fa54f608ecbd" src="https://janezurevc.name/sites/default/files/relation_configuration.png" /></a></p> <p>Now I have to configure Relation migrate. In order to do that I have to navigate to configuration page (found under <em>Structure -> Relation types -> Migration</em>). You'll find configuration for every type of reference field here. Currently we support Term (core), Node (References), User (References) and Entity reference. As I already mentioned I use standard installation for this demo, but other supported fields should appear here if there are any. Now I just have to enable upgrade path for <em>field_tags</em> and select relation type that should be used for this upgrade.</p> <p>If I navigate to <em>Content -> Migrate</em> (Migrate UI must be enabled) i find four migration classes, each for every supported reference field type. I can see that I have some unmigrated term references, which are obviously tags on my nodes. I select this class and start the migiration process.</p> <p><a href="https://janezurevc.name/sites/default/files/migration_classes.png"><img alt="" data-entity-type="file" data-entity-uuid="47896efa-e2aa-4714-a209-9df818ac998d" src="https://janezurevc.name/sites/default/files/styles/migration_classes.png" /></a></p> <p>When migrate script completes it's job I end up with a lot of new relation, which are tags on my nodes.</p> <p><a href="https://janezurevc.name/sites/default/files/relations.png"><img alt="" data-entity-type="file" data-entity-uuid="d764e31e-edcf-4a30-9803-3ddf42e1a4ea" src="https://janezurevc.name/sites/default/files/relations.png" /></a></p> <p>Described functionality is currently available in 7.x-1.x-dev release of Relation module. It is relatively new and as such not very well tested. Please report back in the issue queue if you find any bugs or encounter any problems. I'd be glad to help. Hope you will enjoy Relation module and it's Migrate integration.</p> </div> Mon, 06 Aug 2012 21:35:19 +0000 slashrsm 43 at https://janezurevc.name Strange behaviour (race condition) during node_save() https://janezurevc.name/strange-behaviour-race-condition-during-nodesave <span>Strange behaviour (race condition) during node_save()</span> <span><span lang="" about="https://janezurevc.name/users/slashrsm" typeof="schema:Person" property="schema:name" datatype="" xml:lang="">slashrsm</span></span> <span>Tue, 10.07.2012 - 15:33</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><h2>Problem</h2> <p>We have a <a href="https://www.slovenskenovice.si">bigger media website</a> on <a href="https://drupal.org">Drupal</a> 7 with an editorial team of ~20 members. Lately they started to complain about<strong> strange behavior when updating content on site</strong>. They said, that <strong>changes were not saved at all</strong>. If they opened a node form immediately after saving it Drupal served old (outdated) content. I first suspected Varnish, but it turned out that Varnish worked OK. Later I realized that the <strong>problem obviously lies in field cache</strong>. </p> <h2>Debugging</h2> <p>We use <a href="https://drupal.org/project/memcache">Memcached</a> for most of cache bins on the site. When testing further I realized, that <strong>field cache returns outdated data even after the changes were saved</strong>. The strangest thing was, that everything worked well if I moved <em>cache_field</em> back to database. I first suspected bugs in Memcached itself or Memcache PHP extension. More testing convinced me that I was wrong. After A LOT of unsuccessful debugging I realized, that something sets field cache for a given node immediately after that node was updated (and field cache cleared). Data that was saved to field cache was unfortunately outdated, <strong>which resulted in a unsynchronized state of field cache</strong>. We had correct data in DB, but it's cached version was wrong.</p> <p>At the end I realized, that issue happened because of a http call, that we implemented in one of <em>hook_node_update()</em> implementations. We have an outside service, that needs to know when we update our articles. To achieve this we called their callback, which caused their servers to immediately visit updated content. This generally happened while <em>node_save()</em> was still in progress. Diagram shows what was happening:</p> <p style="text-align:center; float: none;"><img alt="" data-entity-type="file" data-entity-uuid="78c5140b-e429-4ae7-8820-32b9eda63b81" src="https://janezurevc.name/sites/default/files/flow1.png" /></p> <p>API docs for <em>hook_node_update() </em>states:</p> <blockquote><p>This hook is invoked from node_save() after the node is updated in the node table in the database, ...</p></blockquote> <p>That made me believe, that <strong>node was actually saved into DB</strong>, when my hook was called by Drupal. <strong>But that is not true....</strong> If we look at the code of <em>node_save()</em>, we see that it uses <em>db_transaction()</em> (which is a smart thing to do):</p> <pre> function node_save($node) { $transaction = db_transaction(); .... </pre><p>But, what isn't so obvious is a fact, that <strong>every DB query</strong> called from <em>node_save()</em> or <strong>any function directly or indirectly called by it</strong> will not be executed immediately. It will be executed at the very end of <em>node_save()</em>, though. <a href="https://api.drupal.org/api/drupal/includes%21database%21database.inc/class/DatabaseTransaction/7">Docs for DatabaseTransaction</a> confirm that:</p> <blockquote><p>This class acts as a wrapper for transactions. To begin a transaction, simply instantiate it. When the object goes out of scope and is destroyed it will automatically commit.</p></blockquote> <p>Taking this into consideration we have to correct our flow diagram:</p> <p style="text-align:center; float:none;"><img alt="" data-entity-type="file" data-entity-uuid="a4809cb9-1399-459d-8c03-3b283d2c2dd9" src="https://janezurevc.name/sites/default/files/flow2.png" /></p> <p style="float: none; text-align: left; ">And here was our problem. </p> <h2 style="float: none; text-align: left; ">Solution</h2> <p>One solution would be to do remote calls at cron. This was unfortunately not possible as our managers strictly requested that there should be no delay between content update and remote service call. Another solution was, to set some flag in form of a static variable and to call remote server in some other hook, that will happen later in a request flow. Not the best option, but it should work for now.</p> <p>I also <a href="https://drupal.org/node/1677830">submitted a core issue</a> about this, as I believe we should at least update docs for core hooks, to let people know about this fact.</p> <p>The last mistery I had was about Memcached/DB. Why was this problem not present, when I used DB to store cache? The answer is quite obvious when you think a bit. Cache clear operation will be affected by database transaction, as you use DB to store cache. That means, that clear will be executed when all other queries are commited (at the very end of <em>node_save()</em>) resulting in outdated cache being deleted.</p> <p>Have this happened to any other? How would/did you fix this at your site? I'd love to hear about other people experience....</p> </div> Tue, 10 Jul 2012 13:33:40 +0000 slashrsm 41 at https://janezurevc.name JavaScript patterns https://janezurevc.name/javascript-patterns <span>JavaScript patterns</span> <span><span lang="" about="https://janezurevc.name/users/slashrsm" typeof="schema:Person" property="schema:name" datatype="" xml:lang="">slashrsm</span></span> <span>Wed, 02.05.2012 - 21:22</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><p><a href="https://shichuan.github.com/javascript-patterns/">https://shichuan.github.com/javascript-patterns/</a></p> </div> Wed, 02 May 2012 19:22:40 +0000 slashrsm 36 at https://janezurevc.name slovenskenovice.si - biggest Slovenian Drupal site https://janezurevc.name/slovenskenovicesi-biggest-slovenian-drupal-site <span>slovenskenovice.si - biggest Slovenian Drupal site</span> <span><span lang="" about="https://janezurevc.name/users/slashrsm" typeof="schema:Person" property="schema:name" datatype="" xml:lang="">slashrsm</span></span> <span>Mon, 05.12.2011 - 23:15</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><p><img alt="" data-entity-type="file" data-entity-uuid="8503d0db-5bb7-4b29-8c0b-119938f59d5c" src="https://janezurevc.name/sites/default/files/sn-screenshoot.com_.png" /></p> <p><a href="https://www.slovenskenovice.si">Slovenske novice</a> are Slovenian national daily newspaper with largest circulation on national level. Last week we lunched redesign of it's web variant, which is a news portal with about 200.000 unique visitors and 4.5 million impressions per month. This numbers wil definetely become larger soon, as they have monthly growth between 10 and 15%.</p> <p>Site was developed on <a href="https://drupal.org">Drupal 7</a>. We extensively used <a href="https://drupal.org/project/panels">Panels</a> and <a href="https://drupal.org/project/views">Views</a>. Search is based on <a href="https://lucene.apache.org/solr/">Apache Solr</a>, driven by <a href="https://drupal.org/project/search_api">Search API framework</a>. To achieve performance we used <a href="https://drupal.org/project/memcache">Memcached</a>, <a href="https://drupal.org/project/varnish">Varnish</a>, <a href="https://drupal.org/project/apc">APC</a> and developed some own cache expiration rules. This is how we achieved performance we needed and flexibility requested by editorial team. Everything is hosted on our own HA LAMP stack.</p> <p>Just two days after launch we had national elections in Slovenia, which are also a big media event. Our site broke the record in daily visits and everything was working smooth.</p> <p>Since a custom CMS, which was developed inside company about 10 years ago, was used before, one of the most important aspects of this project was experience for editorial team. They learned how to use Drupal surprisingly fast. There were some minor issues reported, but in general Drupal works really got for them.</p> <p>Site was developed by core development team:</p> <ul><li><a href="https://drupal.org/user/19501">Tadej Baša</a>, <a href="https://twitter.com/paranojik">@paranojik</a></li> <li><a href="https://drupal.org/user/282629">Primož Hmeljak</a>, <a href="https://twitter.com/theprimsi">@theprimsi</a></li> <li>Tim Rijavec, <a href="https://twitter.com/timrijavec">@timrijavec</a></li> <li><a href="https://drupal.org/user/744628">Janez Urevc</a> (me :)), <a href="https://twitter.com/slashrsm">@slashrsm</a></li> </ul><p>We also had some themeing help from <a href="https://drupal.org/user/123987">Iztok Smolič</a> (<a href="https://twitter.com/Iztok">@Iztok</a>). </p> <p>We will publish some more information about project in the following weeks.</p> </div> Mon, 05 Dec 2011 22:15:27 +0000 slashrsm 29 at https://janezurevc.name Survey about satisfaction with Scrum https://janezurevc.name/survey-about-satisfaction-scrum <span>Survey about satisfaction with Scrum</span> <span><span lang="" about="https://janezurevc.name/users/slashrsm" typeof="schema:Person" property="schema:name" datatype="" xml:lang="">slashrsm</span></span> <span>Fri, 18.11.2011 - 23:30</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><p>I am currently working on my bachelor thesis at Faculty of Computer and Information Science in Ljubljana. The topic of my thesis is implementation of Scrum methodology in a webdev department of the biggest national daily newspaper company, <a href="https://www.delo.si">Delo</a>. </p> <p>I would like to compare my conclusions about it's strengths, weaknesses and challenges in implementing the Scrum methodology in real environment with the opinions of people who faced this method in their professional career. I therefore kindly ask you to <a href="https://www.surveymonkey.com/s/RFFTRML">participate in the survey</a>, which will take you about 10 minutes.</p> <p>I will share my conclusions here. Thank you for your time!</p> </div> Fri, 18 Nov 2011 22:30:00 +0000 slashrsm 28 at https://janezurevc.name DrupalCon Denver 2011 - Media derivatives: take control over your files https://janezurevc.name/drupalcon-denver-2011-media-derivatives-take-control-over-your-files <span>DrupalCon Denver 2011 - Media derivatives: take control over your files</span> <span><span lang="" about="https://janezurevc.name/users/slashrsm" typeof="schema:Person" property="schema:name" datatype="" xml:lang="">slashrsm</span></span> <span>Mon, 07.11.2011 - 22:45</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><p><a href="https://drupal.org/project/media_derivatives">Derivatives API</a> is a Drupal project I developed during this year's Summer of Code. It is a framework, that tries to implement a simple, reliable and powerfull framework for asset derivation in Drupal. It can cover a lot of different use cases. We are in the times of emerging new technologies of HTML5, mobile publishing, responsive web, ... I believe that Derivatives API has it's piece in a puzzle of support of this new technologies on Drupal. </p> <p>In cooperation with my mentor, <a href="https://drupal.org/user/48877">Kevin Reynen</a>, I proposed<a href="https://denver2012.drupal.org/program/sessions/media-derivatives-take-control-over-your-files"> a session at DrupalCon Denver</a>, where we'd like to present this project to the wider public. Session will cover basic functionalities of the project, some possible use cases and it's extension with your own plugins. </p> <p>Would you like to hear about this project on DrupalCon? Please <a href="https://denver2012.drupal.org/program/sessions/media-derivatives-take-control-over-your-files">vote for our session</a>.</p> <p>Do you have any suggestions or questions? Feel free to comment here or on session proposal.</p> <p>Hope to see you in Denver!</p> </div> Mon, 07 Nov 2011 21:45:07 +0000 slashrsm 26 at https://janezurevc.name How to add custom contextual links to views? https://janezurevc.name/how-add-custom-contextual-links-views <span>How to add custom contextual links to views?</span> <span><span lang="" about="https://janezurevc.name/users/slashrsm" typeof="schema:Person" property="schema:name" datatype="" xml:lang="">slashrsm</span></span> <span>Tue, 20.09.2011 - 18:23</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><p>Today I had a task to add nodequeue manipulation contextual links to some view. First I found <a href="https://deglos.com/comment/63">this blog post</a>, which explains, how to make desired menu items contextual links ready. As Marcus states in his post, I first needed to alter nodequeue menu items:</p> <pre> function MYMODULE_menu_alter(&$items) { $items['admin/structure/nodequeue/%nodequeue/edit']['context'] = MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE; $items['admin/structure/nodequeue/%nodequeue/view']['context'] = MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE; } </pre><p>Nodequeue admin pages were now ready to be added to any contextual links on site. Since Marcus explains how to alter contextual links on blocks, I had to figure out how to do it with views. Solution turned out to be very simple. Contextual links are added to view in <em>views-view.tpl.php</em>, where <em>$title_suffix</em> is displayed. I just needed to add nodequeue contextual links to that variable (which is a render array in fact).</p> <pre> function MYTHEME_preprocess_views_view(&$vars) { $vars['title_suffix']['contextual_links']['#contextual_links']['sn_fpmain_news'] = array( // 3 is queue id in my case; it could be any other page argument 'admin/structure/nodequeue', array(3) ); } </pre><p>And here is the result:</p> <p><img alt="" data-entity-type="file" data-entity-uuid="c71fff4b-596e-4714-b005-5aa2a391a65d" src="https://janezurevc.name/sites/default/files/zaslonska_slika.png" /></p> <p style="clear: both;">Is there any better way to do this?</p> </div> Tue, 20 Sep 2011 16:23:09 +0000 slashrsm 20 at https://janezurevc.name 5 day challenge (i'm in!:) https://janezurevc.name/5-day-challenge-im <span>5 day challenge (i'm in!:)</span> <span><span lang="" about="https://janezurevc.name/users/slashrsm" typeof="schema:Person" property="schema:name" datatype="" xml:lang="">slashrsm</span></span> <span>Sat, 17.09.2011 - 23:09</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><p>Today <a href="https://acquia.com/blog/5-days-5-challenges-drupal">Jakub Suchy proposed a really cool thing</a> on his blog. Idea is about spending 30 minutes each day in the next week to contribute something to Drupal. He proves, that only 63 people doing this, can do as much work as an individual could do in a month.</p> <p>Since I immediately loved this idea, I decided to join. Here is my plan for <a href="https://twitter.com/#!/search/realtime/d5dchallenge">#d5dChallenge</a>:</p> <ul><li><b>Day 1:</b> improve <a href="https://drupal.org/project/media_derivatives">Media derivatives API</a> views support,</li> <li><strong>Day 2:</strong> write some docs for Media derivatives API,</li> <li><b>Day 3:</b> work on YouTube uploader engine for Media derivatives API,</li> <li><strong>Day 4:</strong> spend some time in Media issue queue; find some issue to review or submit a simple patch; find some issues I could help with <a href="https://groups.drupal.org/node/173749">during Media code sprint</a>,</li> <li><strong>Day 5:</strong> do some research about Rules integration development and plan Rules integration for Media derivatives API.</li> </ul><p>What do you think about this list? You can also propose something else, if you think I should rather work on some other tasks during this week.</p> <p>Will you join too? I hope there will be even more than 63 of us!</p> </div> Sat, 17 Sep 2011 21:09:01 +0000 slashrsm 19 at https://janezurevc.name