Planet Drupal

Subscribe to Planet Drupal feed
Drupal.org - aggregated feeds in category Planet Drupal
Updated: 4 min 9 sec ago

Théodore 'nod_' Biadala: Using ES5 with Drupal 8

Tue, 21/01/2014 - 05:20

In fixing contrib javascript I mentioned that as a contrib maintainer or developer you could do a bit more than just run JSHint. This is because Drupal 8 will not support IE8, meaning that core and contrib are free to go crazy! The incredibly useful caniuse.com website holds extensive compatibility tables for the fancy new HTML/JS/SVG features in the works. But talking about ES5 specifically, the ECMAScript 5 compatibility table is what you’re looking for to know what you can rely on.

For core and contrib, here is a peak at what’s coming to a future near you.

Safe

By safe I mean that those are features that won’t bite you horribly. Some of them are already used in Drupal 8 core or are in a patch that’ll be committed soon enough.

"use strict"

This is actually enforced by JSHint — you know the thing that you should be running on your JS — while we’re not relying on the advanced features of the strict mode it is used to make sure there are no leaking variable. I’ve seen too many strays variable in contrib and projects. To use, put "use strict"; at the top of the file-closure.

(function ($, Drupal, drupalSettings) { "use strict"; // Your code. })(jQuery, Drupal, drupalSettings); Function.prototype.bind

It is the native version of the basic usage of jQuery.proxy().

Before var handler = $.proxy(callback, this); After var handler = callback.bind(this); Array.prototype.forEach

Looping is a rather large topic so we’ll stick with the basics. Given the following array:

var valueList = [ 'a', 'e', 'i', 'o', 'u', 'y' ]; Before var i = 0; var il = valueList.length; for (; i < il; i += 1) { } After function callback (value, index) {} valueList.forEach(callback); Object.keys

This one combined with forEach allow you to do painless filtered for each if we take the following object:

var snacks = { banana: 0, chips: 1000 }; Before for (var snack in snacks) { if (snacks.hasOwnProperty(snack)) { } } After function eatSnacks (snack) {} Object.keys(snacks).forEach(eatSnacks);

And that looks much better than the first example. Giving a name to your function gives you extra info on what is it the loop is doing without having to comment it too much. Also makes profiling easier since you’ll have data on the callback function.

Now you’ll probably ask why not use jQuery.each in both cases? or even _.each. First it’s native so there is no need for an extra library. I’m not talking about speed — if your bottleneck is how you do your loops, you don’t need to read all this, otherwise go profile your DOM manipulations. jQuery each doesn’t filter with hasOwnProperty which means that is some script on your page extends either Object.prototype or Array.prototype — on top of breaking jQuery — you’re gonna have a bad time. Underscore does filter properly so it’s fine using that if you have the library on the page anyway.

I still need IE8 support

Does Drupal 8 dropping IE: 6, 7, 8 means you can’t use it in a market like china or big administrations where IE8 is still the default and supported browser?

IE8 module

The IE8 module was started to introduce IE8 compatibility back to Drupal 8 — in fact it was started to help take the decision to drop IE8. While the level of support is still undecided the goal is to allow people who develop for IE8 to be able to use Drupal 8. We’ll see what that means when that time comes. For now you can use the ie8 tag in the issue queue to help up see what’ll go wrong on IE8.

There is a lot more good stuff we can use such as localStorage, document.querySelector but those are DOM-related and have nothing to do with ES5 so expect a follow-up post on those.

Categories: Elsewhere

Appnovation Technologies: The Dark Side of Aggregation

Mon, 20/01/2014 - 23:22
CSS and JavaScript aggregation is one of the easiest ways in all known methods to increase performance of any Drupal site. In this post I discuss how to employ aggregation as a site grows more complex. var switchTo5x = false;stLight.options({"publisher":"dr-75626d0b-d9b4-2fdb-6d29-1a20f61d683"});
Categories: Elsewhere

Drupal core announcements: We still have numerous "fixed" D8 issues that cannot be closed until a Change Record is published

Mon, 20/01/2014 - 23:06

Two weeks ago I wrote that we had 40 "fixed" issues that cannot be closed until a change record is published for them. That number now stands at 39 issues as a result of churn from a few change records being written and a couple new issues fixed and tagged for a change record.

We have documentation about how to write a change record if you have not written one before.

If you start a change record and feel that you need input from the original issue authors, you can use the original issue queue to work out a draft just like jgSnell, SebCorbin and Cottser are doing in Remove first/last/odd/even classes in favor of CSS3 pseudo selectors.

Today is a great day to become involved with getting Drupal 8 to a stable release.

Categories: Elsewhere

Drupal core announcements: The biggest Drupal core sprint and developer camp is coming up in March!

Mon, 20/01/2014 - 18:35

Drupal Developer Days 2014 is coming up quick in Szeged, Hungary from March 24th (Mon) to the 30th (Sun) 2014. Szeged, Hungary may sound like it is the middle of nowhere but what do you need to get together with a bunch of Drupal developer friends and learn about and advance the platform together? As those who have been to DrupalCon Europe 2008 in the same city know, Szeged is the ideal place for just that. Check out our interviews about those experiences.

Here are some quick facts about Drupal Dev Days 2014:

  • A whole week of sprints with two core committers (Alex Pott and Nathaniel Catchpole) as well as the testbot system maintainer (Jeremy Thorson) on location! Could we help more to make progress? Oh, most top European Drupal developers are already signed up to come as well!
  • Three days of sessions and workshops (50 topics providing 56 hours of content). Get lots of readily applicable know-how including website monitoring, e-commerce, practical scrum, Vagrant, product development in real life, Heisencache, IDE tricks and so on. Look into how Drupal is made, see the life of a core maintainer, get gamification tips or discuss a new type of money: Druplicoins!
  • Want to work on upgrading your modules to Drupal 8 but don't know how? No problem! Additionally to learning about all the new Drupal 8 subsystems, there is a bring-your-own-module workshop as well, where mentors will help you upgrade your module!
  • Want to get into Drupal development? Attend the community tools workshop and learn all the tools we use to communicate and work on solutions and learn and enjoy how the Drupal mentoring program works.

A truly fantastic opportunity isn't it? Last but not least its also very cheap. The ticket is only 30 Euros for the whole week! If you want to get to know Drupal 8 or even help make it happen, this is the place to be in March. Note that some cheap hotel deals expire this week. Don't miss out!

Categories: Elsewhere

Stanford Web Services Blog: Overriding Open Framework Styles: Customizing your Main Menu

Mon, 20/01/2014 - 18:00

In this series of posts, I'm going to share some tricks to quickly override some of Open Framework's default styling, such as the main menu, text, and link styles. For anyone who wants a quick way to get to a custom design on Stanford Sites, these posts should get you started on the right path. In this first post we'll cover how to customize the main menu.

Categories: Elsewhere

Propeople Blog: Configuring Varnish for Drupal 7.20

Mon, 20/01/2014 - 17:06

Since the release of Drupal 7.20, all images generated by the ImageCache module have been suffixed by a token. Here’s a detailed explanation that can be found in the release notes:

The security fixes in this release change all image derivative URLs generated by Drupal to append a token as a query string. ("Image derivatives" are copies of images which the Drupal Image module automatically creates based on configured image styles; for example, thumbnail, medium, large, etc.)

Links that previously pointed to an URL like: /sites/default/files/styles/thumbnail/public/field/image/example.png will, from now on, point to something like this: /sites/default/files/styles/thumbnail/public/field/image/example.png?itok=zD_VaCaD.

Nobody seems to have noticed that Varnish is not caching images for authenticated users anymore. The force cache rule for static content no longer works for image derivatives because of the token:
#Always cache static files. if (req.url ~ "\.(png|gif|jpeg|jpg|ico|swf|css|js|html|htm)(\?[a-z0-9]+)?$") { unset req.http.Cookie; }

The solution we came up with at Propeople Drupal Agency is to change the regexp pattern from the above to the following:
if (req.url ~ "\.(png|gif|jpeg|jpg|ico|swf|css|js|html|htm)(\?[\w\d=\.\-]+)?$") {

The initial pattern includes (\?[a-z0-9]+)? in order to cover the css/js files cache token generated by Drupal, which looks like ?xyz. But the new parameter added to images contains more “=-_” character types.

Also, this fix will add support for caching js files like misc/jquery.js?v=1.4.4, which are not cached by default (this fix is for all Drupal versions).

If you have other blocks in varnish.vcl involving images, you should add the following regexp pattern:
# Normalize the Accept-Encoding header. if (req.http.Accept-Encoding) { if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)(\?[\w\d=\.\-]+)?$" || req.url ~ "^/robots\.txt$") {
For more details go to http://varnish-cache.org/wiki/FAQ/Compression.

# Don't set cookies on these file types. if (req.url ~ "(?i)\.(png|gif|jpeg|jpg|ico|swf|css|js|html|htm)(\?[\w\d=\.\-]+)?$") { unset beresp.http.set-cookie; }

In conclusion, all checks where png, jpg and gif extensions are involved should have (\?[\w\d=\.\-]+)?$ instead of $ and (\?[a-z0-9]+)?$.

I hope you find this article useful. If you have any questions, make sure to post them in the comments below, and I would love to help you out. And don’t forget to subscribe to our mailing list to get our Drupal blog feed directly to your mailbox.

Tags: DrupalVarnishHow toCheck this option to include this post in Planet Drupal aggregator: planetTopics: Tech & Development
Categories: Elsewhere

Dcycle: Do not use incremental IDs in your code

Mon, 20/01/2014 - 16:08

Drupal uses incremental IDs such data as taxonomy terms and nodes, but not content types or vocabularies. If, like me, you believe your site's codebase should work with different environments, your incremental IDs can be different on each environment.

But wait, you are thinking, I have only one environment: my production environment. But there are advantages to be able to spawn new environments independently of the production environment without cloning the database upstream:

  • Everything you need to create your website, minus the content, is under version control. The production database, being outside version control, should not be needed to install a new environment. See also "what is a deployment module?".
  • New developers can be up and running with a predictable environment and dummy content.
  • Your automated tests, using Drupal's Simpletest, by default deploy a new environment without cloning the database.
  • For predictable results in your continuous integration server, it is best to deploy a new envrionment. The production database's is unpredictable and unversioned. If you test it, your test results will be unpredictable as well.
  • Maybe you'll need a separate version of your site with different data (for a new market, perhaps).

Even if you choose to clone the database upstream for development, testing and continuous integration, it is still a good idea to avoid referencing incremental IDs of a particular database, because at some point you might decide that it is important to be able to have environments with different databases.

Example #1: using node IDs in CSS and in template files

I have often seen this: particular pages (say, nodes 56 and 400) require particular markup, so we see template files like page--node--56.tpl.php and css like this:

.page-node-56 #content, .page-node-400 #content { background: red; }

When, as developers, we decide to use this type of code on a website, we are tightly coupling our code, which is under version control, to our database, which is not under version control. In other words our project as a whole can no longer be said to be versioned as it requires a database clone to work correctly.

Also, this creates all sorts of problems: if, for example, a new node needs to be created which has the same characteristics as nodes 56 and 400, one must fiddle with the database (to create the node) and the code. Also, creating automatic tests for something like this is hard because the approach is not based on underlying logic.

A better approach to this problem might be to figure out why nodes 56 and 400 are somehow different than the others. The solution will depend on your answer to that question, and maybe these nodes need to be of a different content type; or maybe some other mechanism should be used. In all cases, though, their ID should be irrelevant to their specificity.

Example #2: filtering a view by taxonomy tag

You might have a website which uses Drupal's default implementation of articles, with a tag taxonomy field. You might decide that all articles tagged with "blog" should appear in your blog, and you might create a new view, filtered to display all articles with the "blog" tag.

Now, you might export your view into a feature and, perhaps, make your feature a dependency of a site deployment module (so that enabling this module on a new environment will deploy your blog feature).

It is important to understand that with this approach, you are in effect putting an incremental ID into code. You view is in fact filtering by the ID of the "blog" taxonomy term as it happens to exist on the site used to create the view. When creating the view, we have no idea what this ID is, but we are saying that in order for our view to work, the "blog" taxonomy term needs to be identical on all environments.

Here is an example of how this bug will play out:

  • This being the most important feature of your site, when creating new environments, the "blog" taxonomy term might always have the ID 1 because it is the first taxonomy term created.
  • You might decide that such a feature is too "simple" to warrant automated testing; but if you define an automated test, your test will run on a new database and will need to create the "blog" taxonomy term in order to validate. Because your tests are separate and simple, the "blog" taxonomy term is probably the only term created during testing, so it, too will have ID 1.
  • Your continuous integration server which monitors changes to your versioned code will run tests against every push, but, again, on a new database, so your tests pass and your code will be fine.

This might go on for quite some time until, on a given environment, someone decides to create another label before creating the "blog" label, which will have ID #2 and which will break your feature.

Consider, furthermore, that your client decides to create a new view for "jobs" and use the same tag mechanism as for blog; and perhaps other tags as well. Before long, your entire development cycle becomes dependent on database cloning to work properly.

To come up with a better approach, it is important to understand what we are trying to accomplish; and what taxonomy terms are meant to be used for:

  • The "blog" category here is somehow immutable and means something very specific. Furthermore, the existence of the blog category is required for our site. Even if its name changes, the key (or underlying identity) of the blog category should always be the same.
  • Taxonomy terms are referenced with incremental IDs (like nodes) and thus, when writing our code, we cannot depend on their existence.

In this case, we are using taxonomy terms for the wrong purpose. Taxonomy terms, like nodes, are meant to be potentially different for each environment: our code should not depend on them.

A potential solution in this case would be to create a new field for articles, perhaps a multiple selection field, with "blog" as one of the possible values. Now, when we create a view filtered by the value "blog" in our new field, we are no longer referencing an incremental ID in our code.

I myself made this very mistake with my own website code without realizing it. The code for this website is available on GIthub and the issue for this problem is documented here.

Deploying a fix to an existing site

If you apply these practices from the start of a project, it is relatively straightforward. However, what if a site is already in production with several articles already labelled "blog"? In this case we need to incrementally deploy the fix. For this, a site deployment module can be of use: in your site deployment module's .install file, you can add a new update hook to update all your existing articles labelled "blog", something like:

/** * Use a machine name rather than an incremental ID to display blog items. */ function mysite_deploy_update_7010() { // deploy the new version of the view to the target site features_revert(array('mysite_feature' => array('views_view'))); ... // cycle through your nodes and add "blog" to your new field for any // content labelled "blog". }

Of course, you need to test this first with a clone of your production site, perhaps even adding an automatic test to make sure your function works as expected.

Conclusion

Drupal makes it very easy to mix incremental IDs into views and code, and this will work well if you always use the same database on every environment. However, you will quickly run into problems if you want to write automated tests or deploy new sites without cloning the database. Being aware of this can help you write more logical, consistent and predictable code.

Tags: blogplanet
Categories: Elsewhere

Acquia: Preventing Drupal Headaches! The file field

Mon, 20/01/2014 - 11:48

In our structured Drupal training program, we teach the "right way" to do things. We listen to our support team of client advisors who see all the permutations of "you're doing it wrong" in Drupal, and make sure we're leading learners in the right direction. When there's something particularly essential we use words like "Important" and set off warnings with a little exclamation mark icon.

Categories: Elsewhere

Wunderkraut blog: Using the Drupal 7 Form API states system to create conditions between form elements

Mon, 20/01/2014 - 09:43

In this article we will look at how you can leverage the power of the Drupal 7 Form API states system to create dependencies between your form fields. In other words, when you programmatically write your forms, you’ll be able to make the behaviour of the elements depend on others.

To illustrate this power, we’ll write some code, but first, let’s see some theory.

What are the states and what do they do?

The states are simple properties or HTML attributes of DOM elements. When creating your form elements using the Form API, you can apply various states to them depending on the states of others. Thus there are 2 kinds of elements: those which act as the condition for others and those which depend on these conditions to change their state. I like the way Jeff Robbins of Lullabot categorises the elements by the possible states they can have: callers and listeners.

The possible states for the first group (the ones that trigger change in others)

  • empty
  • filled
  • checked
  • unchecked
  • expanded
  • collapsed
  • value

The possible states for the second group (the ones that get applied onto elements):

  • enabled
  • disabled
  • required
  • optional
  • visible
  • invisible
  • checked
  • unchecked
  • expanded
  • collapsed

And what does Drupal do? It provides all the necessary javascript to make all these behavioral alterations on the fly so you don’t have to worry about javascript or jQuery.

Example module

To illustrate how this all works, we are going to build a tiny module which declares a path to a form. Using this form, we will play around with some elements and see all this in action. So let’s dive in. You can download this small module if you want to follow along.

Assuming you have done the necessary to create your empty module, we can go ahead and declare the menu path using hook_menu():

/** * Implements hook_menu(). */   function states_menu() {   $items['states-example'] = array( 'title' => 'Demonstrating the Form API states system', 'page callback' => 'drupal_get_form', 'page arguments' => array('states_example_form'), 'type' => MENU_NORMAL_ITEM, 'access arguments' => array('access content'), );   return $items; }

This registers the states-example path which will render the states_example_form declared below:

function states_example_form($form, &$form_state) {   $form = array();   $form['name'] = array( '#title' => t('Your name'), '#type' => 'textfield', );   $form['submit'] = array( '#type' => 'submit', '#value' => t('Submit'), );   return $form; }

If you clear the cache and go to that path, you should see the form with 2 form elements: the name field and the submit button. No biggie. One thing to keep in mind for later is that the array key 'name' will be the actual DOM name of the form element.

Lets now add another element below the name field that will depend on the latter and show up only if the user enters something in the name field:

$form['preferences'] = array( '#title' => t('Your preference'), '#type' => 'select', '#options' => array('moto' => 'Motorcycles', 'cars' => 'Cars'), // Show this field only if the name field is filled. '#states' => array( 'visible' => array( 'input[name="name"]' => array('filled' => TRUE), ), ), );

Lets scan through this array and see what’s what. Above the comment we can see that the element is a select list with 2 options and a title. Below the comment we declare that to this element will be applied the state visible when and if the DOM element of the type input with the name="name" (your classic css/jQuery selector and which happens to be the first element in our form) gets filled. Otherwise, the opposite state is applied - in this case, invisible.

So in the browser when the form is loaded on the page, only the name field is visible. When the user starts typing the name, the preferences field appears. Refresh the page and check it out. Drupal adds the necessary javascript for this to happen.

You can also do it the other way around. You can apply the state invisible when another element => array('filled' => FALSE). It will have the same effect except you declare it differently.

Next, let’s add another element that will depend on the preferences field:

$form['brands'] = array( '#title' => t('Your favorite brand'), '#type' => 'select', '#options' => array('Toyota', 'BMW', 'Audi'), // The reverse of the previous field: hide this field if there is no name '#states' => array( 'visible' => array( 'select[name="preferences"]' => array('value' => 'cars'), ), ), );

This is another select list but the visibility of this element depends on the actual value of the previous one. So in the browser, this will only appear if and when the user selects that they prefer cars over motorcycles.

Let’s look at the next 2 elements:

$form['marriage'] = array( '#title' => t('Are you married?'), '#type' => 'checkbox', );   $form['spouse_preferences'] = array( '#title' => t('Your spouse\'s preference'), '#type' => 'radios', '#options' => array('moto' => 'Motorcycles', 'cars' => 'Cars'), // Show this field only if the user name is filled and if s/he is married. '#states' => array( 'visible' => array( 'input[name="name"]' => array('filled' => TRUE), 'input[name="marriage"]' => array('checked' => TRUE), ), ), );

The first one is a simple checkbox that will show no matter what. But the second one is another select list and here we can see that the visibility of this depends on 2 previous elements. So this will show only when and if the user fills in a name and checks the box confirming that s/he is married. A so called AND condition, if you will. I will tell you write off the bat that you cannot do OR conditions with the states system - at least not that I could figure out. If you manage to find a way, let me know.

And the last two elements we will look at in this article:

$form['kids'] = array( '#title' => t('How many kids do you have?'), '#type' => 'select', '#options' => array(0, 1, 2), );   $form['kids_preferences'] = array( '#title' => t('Your kids\' preference'), '#type' => 'radios', '#options' => array('moto' => 'Motorcycles', 'cars' => 'Cars'), // Show this field only if the user has kids. '#states' => array( 'visible' => array( 'input[name="marriage"]' => array('checked' => TRUE), ), 'disabled' => array( 'select[name="kids"]' => array('value' => '0'), ), ), );

Again the first one will show no matter what, but this time it's a select list. The second one depends on two other elements for two different state changes. First, it will become visible only if the the user checks the box that s/he is married. Second, it will become disabled if the user selects that s/he has 0 kids. Neat.

Conclusion

As i mentioned in the beginning of the article, there are a number of different states available for elements and Drupal handles all the javascript for you. We cannot go over all of them here nor try all the different combinations of what you can do with the states system. I thus encourage you experiment further on your own. You can even download this little module and use it as a starting point.

And as always, Drupal.org is your friend and you can find some more information on the states system at the following pages:

Categories: Elsewhere

Web Omelette: Redirecting the block configure page back to itself

Mon, 20/01/2014 - 09:01

After working with Drupal for a while, you begin to love some of its features to death. But you can also develop some pet-peeves. One of mine is how when you edit a block in the administration and save it, you are redirected onto the block overview page - you know, the one with the big list of blocks. Now think you are on a site with a bunch of regions and blocks and you are fine tuning a particular one while testing how it outputs. Every time you have to go back and search for it to edit it again.

I decided to write a little custom code to change that default behaviour more to my liking. In this article we will look at how you can redirect the user back to the block edit page after the block has been saved. Basically how to redirect to itself so you can edit again immediately after you saved the block. It's quite easy actually, it only takes 2 functions:

function module_name_form_block_admin_configure_alter(&$form, &$form_state) {
  $form['#submit'][] = 'module_name_form_block_admin_configure_submit';
} function module_name_form_block_admin_configure_submit($form, &$form_state) {
  $module = $form['module']['#value'];
  $delta = $form['delta']['#value'];
  $form_state['redirect'] = 'admin/structure/block/manage/' . $module . '/' . $delta . '/configure';
}

Let's see what these do. The first one is an implementation of hook_form_FORM_ID_alter() and we use it to hook into the block edit form and include a custom submit callback to the right array. You can read more about how to do these kind of things here. The value we included is the name of the second function above that gets called after the default block submit handler.

What happens in the second function? First off, we gather the name of the module that created the block. For instance the Search form block is created by the Search module and the Navigation block by the System module (these are default blocks that come with Drupal core in case you were wondering). For custom blocks made in the UI, the name will be block.

Then, we gather the delta value. This is the unique identifier of the block (integer for custom blocks or strings for modules implementing blocks in code). Finally, we create a redirect to the specific URL which includes both these values (i.e., back to the edit form for that block).

Easy peasy, just remember to replace module_name with the machine name of your block.

Now when you have to keep editing a particular block, you won't have to search through all those names to find it back again and again. You are right there in the zone making changes. I think it's also good for content editor experience, not just administrators.

Hope this helps.

In Drupal var switchTo5x = true;stLight.options({"publisher":"dr-8de6c3c4-3462-9715-caaf-ce2c161a50c"});
Categories: Elsewhere

Daniel Pocock: Debian solving Drupal's third-party library challenge

Sun, 19/01/2014 - 23:47

The tremendously successful Drupal community observes stringent requirements about many things, in particular, licensing and the prohibition of bundling third-party JavaScript.

While these policies may seem onerous at first glance, it turns out there is another project with a written guarantee to provide third-party code in a form that meets the expectations of Drupal and does so in a way that completely automates all that tedious effort into one-click oblivion. I'm talking about the Debian GNU/Linux operating system.

Drupal's libraries module

The libraries module for Drupal appeared as an initial attempt to help track third-party JavaScript.

The module has been available in Debian for almost a year and has recently been provided in the wheezy-backports distribution for people running the stable version of Debian.

The library provides a standard way for other modules to reference third-party JavaScript but it still leaves the web master with some manual work to go out and download all the necessary JavaScript and copy it into the right place. This is where Debian comes to the rescue.

Using the module in practice

I've recently uploaded JSCommunicator to Debian and wanted to provide a convenient way for people to get it in Drupal.

Therefore, in addition to providing the JSCommunicator packages, I created an extra package, drupal7-mod-jscommunicator.

JSCommunicator itself depends on other JavaScript, specifically, the JsSIP library. I repeated the same process for JsSIP. This gives us the following collection of four related packages:

Third-party library Library itself Drupal module, packaged JSCommunicator libjs-jscommunicator drupal7-mod-jscommunicator JsSIP libjs-jssip drupal7-mod-jssip

If you explore the package details in Debian's package catalog you will notice that each package depends on the other packages it requires.

Debian's package management utility, apt-get, can transitively resolve all the relationships between this set of packages. In fact, on a newly built server, you can simply run the command:

apt-get install drupal7-mod-jscommunicator

and the apt-get utility will install Apache, MySQL, Drupal itself, the libraries module, all the related JavaScript libraries and the final Drupal module of JSCommunicator itself. It really is that easy. Here is an example of the output displayed by the command on a freshly built server:

# apt-get -d install drupal7-mod-jscommunicator Reading package lists... Done Building dependency tree Reading state information... Done The following extra packages will be installed: apache2 apache2-bin apache2-data curl dbconfig-common drupal7 drupal7-mod-jssip drupal7-mod-libraries fontconfig-config fonts-dejavu-core javascript-common libaio1 libapache2-mod-php5 libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap libarchive-extract-perl libc6 libcurl3 libdbd-mysql-perl libdbi-perl libedit2 libfontconfig1 libgcrypt11 libgd3 libhtml-template-perl libjbig0 libjpeg8 libjs-jssip libjson-c2 liblocale-gettext-perl liblog-message-simple-perl liblua5.1-0 libmodule-pluggable-perl libmysqlclient18 libonig2 libperl4-corelibs-perl libpng12-0 libpod-latex-perl libqdbm14 librtmp0 libssh2-1 libterm-ui-perl libtext-charwidth-perl libtext-iconv-perl libtext-soundex-perl libtiff5 libuuid-perl libvpx1 libxml2 libxpm4 locales mysql-client mysql-client-5.5 mysql-common mysql-server mysql-server-5.5 mysql-server-core-5.5 perl perl-base perl-modules php5 php5-cli php5-common php5-gd php5-json php5-mysql php5-readline ssl-cert wwwconfig-common Suggested packages: apache2-doc apache2-suexec-pristine apache2-suexec-custom apache2-utils php-pear glibc-doc libclone-perl libmldbm-perl libnet-daemon-perl libplrpc-perl libsql-statement-perl rng-tools libgd-tools libipc-sharedcache-perl libterm-readkey-perl tinyca perl-doc libterm-readline-gnu-perl libterm-readline-perl-perl make libb-lint-perl libcpanplus-dist-build-perl libcpanplus-perl libfile-checktree-perl liblog-message-perl libobject-accessor-perl php5-user-cache openssl-blacklist postgresql-client The following NEW packages will be installed: apache2 apache2-bin apache2-data curl dbconfig-common drupal7 drupal7-mod-jscommunicator drupal7-mod-jssip drupal7-mod-libraries fontconfig-config fonts-dejavu-core javascript-common libaio1 libapache2-mod-php5 libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap libarchive-extract-perl libcurl3 libdbd-mysql-perl libdbi-perl libfontconfig1 libgd3 libhtml-template-perl libjbig0 libjpeg8 libjs-jssip libjson-c2 liblog-message-simple-perl liblua5.1-0 libmodule-pluggable-perl libmysqlclient18 libonig2 libperl4-corelibs-perl libpng12-0 libpod-latex-perl libqdbm14 librtmp0 libssh2-1 libterm-ui-perl libtext-soundex-perl libtiff5 libvpx1 libxpm4 mysql-client mysql-client-5.5 mysql-common mysql-server mysql-server-5.5 mysql-server-core-5.5 php5 php5-cli php5-common php5-gd php5-json php5-mysql php5-readline ssl-cert wwwconfig-common The following packages will be upgraded: libc6 libedit2 libgcrypt11 liblocale-gettext-perl libtext-charwidth-perl libtext-iconv-perl libuuid-perl libxml2 locales perl perl-base perl-modules 12 upgraded, 60 newly installed, 0 to remove and 222 not upgraded. Need to get 37.2 MB of archives. After this operation, 152 MB of additional disk space will be used. Do you want to continue [Y/n]? Libraries joins core in Drupal 8

With the libraries module joining the core in Drupal 8, there will be further opportunity for Drupal users to consolidate on their use of Debian to completely automate the management of all third-party libraries and modules throughout their Drupal system(s).

Categories: Elsewhere

ShooFlyDesign: Fixing Drupal's Last-Modified header for RSS feeds

Sun, 19/01/2014 - 22:21

If you use Drupal with Twitterfeed or other services that consume its RSS feeds, you may find that new posts aren't recognized. I recently had this problem with a client's website, but thanks to some excellent support from Twitterfeed (Excellent support, and on a free service no less. Thanks, Mario!), I was able to track down the problem and fix it.

Read more
Categories: Elsewhere

groups.drupal.org frontpage posts: Florida Drupalcamp Open for Registration!

Sun, 19/01/2014 - 14:59

Florida DrupalCamp is now taking registrations and session submissions! Register at http://fldrupalcamp.org! The event will be taking place at the beautiful campus of Florida Technical College in Orlando, Florida on Saturday, March 8th.

This year, we’re doing away with the traditional keynote speaker, and bringing in four (yes four!) amazing featured speakers from around the country! We’ll be announcing a new featured speaker every week - starting with the illustrious Jen Lampton! Read more about Jen at https://fldrupalcamp.org/featured-speaker/jen-lampton

Early-bird registration is only $25 and includes lunch and an awesome tshirt! Register today (before we raise the price on you)!

http://fldrupalcamp.org


Categories: Elsewhere

Berliners blog: Dynamically define blocks in Drupal 8 with derivatives

Sat, 18/01/2014 - 22:31

During the Drupal 8 port of my relatively new Mefibs module I realized that block creation in code got somewhat more complex than it used to be in Drupal 7 and earlier. It took me quite a while to figure out how this works, especially because there is not a lot of documentation for Drupal 8 yet. So I had to dig my way through core to see how it's done there and finally I got around it. The following is a comparison between how we used to do this in Drupal 7 and how it's done in Drupal 8.

Defining a single block

Let start with the ground work. In Drupal 8 blocks are now plugins. Defining a block in code is straight forward. You need to create a class located in lib/Drupal/mymodule/Plugin/Block/MyModuleBlock.php inside your module directory, containing:

<?php /** * @file * Contains \Drupal\mymodule\Plugin\Block\MyModuleBlock. */ namespace Drupal\mymodule\Plugin\Block; use Drupal\block\BlockBase; /** * Provides a Custom block. * * @Block( * id = "mymodule_block", * admin_label = @Translation("MyModule block"), * category = @Translation("MyModule") * ) */ class MyModuleBlock extends BlockBase { /** * Build the content for mymodule block. */ public function build() { return array( '#markup' => 'My awesome content', ); } }

This creates a single block that outputs only the string "My awesome content". As you can see, there is little code. The annotation in the comment, which is a new concept in Drupal 8, informs the plugin system about our custom block:

  • id: This defines the ID of the block which is used to identify the block. This is also used in HTML id attributes and class names.
  • admin_label: This designates the label used on the block configuration page.
  • category: This allows to control in which category on the block configuration page the block appears. You can use one of the existing categories or define a custom new one.

Your block plugin class will usually extend BlockBase. Inspecting this class will give you an idea of other methods that can be used to achieve specific goals, like access control or custom setting forms for the block. In order to fully define and display a block it is sufficient though to implement the build() method from BlockPluginInterface.

Voilà, there is the block. So this is the equivalent of implementing hook_block_info() and hook_block_view() in Drupal 7.

Defining multiple blocks

As you may notice though, this only defines a single block. There is only one class with a single build() method and no obvious way of extending this to support multiple instances of the same block type. In Drupal 7 blocks are defined in hook_block_info(), which returns an array of block description arrays. So it would have been sufficient to return multiple blocks in an array, keyed by the block id, like this:

function mymodule_block_info() { $blocks = array(); $myblocks = array( 'mymodule_block_first' => t('MyModule Block: First'), 'mymodule_block_second' => t('MyModule Block: Second'), ); foreach ($myblocks as $block_id => $block_label) { $blocks[$block_id] = array( 'info' => $block_label, 'cache' => DRUPAL_NO_CACHE, ); } return $blocks; }

In this example the available blocks are defined directly in the hook implementation, but they could also come from a database query or from another source, you name it. The important aspect is, that the logic to define multiple blocks was the same as for defining a single block. You just returned more of them. As they all had their proper block ids, which are passed to hook_block_view() or hook_block_configure() they could all be handled independently, but still be defined using the same logic.

Now in Drupal 8 this got more complicated. It took me a while, but finally I found a simple example in the core system module that defines menu blocks. A menu block is structurally exactly what I was after: A block definition that adheres to the same logic, though it can be created by a user in the UI so that you never know in advance how many blocks there will be or what their block ids might be.

That is where derivatives appear on the scene. Might be that this is obvious for someone coming from a strong OO background, but I had never heard of them before, so they didn't catch my attention on the first screening of the core block implementations. For those of you who, just like me, do not know what derivatives are, I will cite a phrase from the documentation:
"Derivatives provide a simple way to expand a single plugin so that it can represent itself as multiple plugins in the user interface."

Gotcha! Cool, so how are they used? It boils down to this:

  • Create a new class called, let's say, MyModuleBlock and save that in lib/Drupal/mymodule/Plugin/Derivative/MyModuleBlock.php. This class must implement DerivativeInterface and can extend DerivativeBase for convenience.
  • Implement the interface method getDerivativeDefinitions(). You can also implement getDerivativeDefinition() but it's usually not necessary when the derivative class extends DerivativeBase.
  • Reference the derivative class in the annotation of your block plugin class.
  • In the block plugin class, use $this->getDerivativeId() wherever you need the actual id of the block instance that is processed.

To extend the first example, the block plugin class would look something like this:

<?php /** * @file * Contains \Drupal\mymodule\Plugin\Block\MyModuleBlock. */ namespace Drupal\mymodule\Plugin\Block; use Drupal\block\BlockBase; /** * Provides a Custom block. * * @Block( * id = "mymodule_block", * admin_label = @Translation("MyModule block"), * category = @Translation("MyModule"), * derivative = "Drupal\mymodule\Plugin\Derivative\MyModuleBlock" * ) */ class MyModuleBlock extends BlockBase { /** * Build the content for mymodule block. */ public function build() { $block_id = $this->getDerivativeId(); return array( '#markup' => mymodule_build_block_content($block_id), ); } }

It didn't change much. We added the derivative class to the annotation and we retrieve the block id to pass it on to a function that retrieves content based on the given argument. That's it.

Now for the derivative class, we will simply use the logic from the earlier Drupal 7 example:

<?php /** * @file * Contains \Drupal\mymodule\Plugin\Derivative\MyModuleBlock. */ namespace Drupal\mymodule\Plugin\Derivative; use Drupal\Core\Plugin\Discovery\ContainerDerivativeInterface; /** * Provides block plugin definitions for mymodule blocks. * * @see \Drupal\mymodule\Plugin\Block\MyModuleBlock */ class MyModuleBlock extends DerivativeBase implements ContainerDerivativeInterface { /** * {@inheritdoc} */ public function getDerivativeDefinitions(array $base_plugin_definition) { $myblocks = array( 'mymodule_block_first' => t('MyModule Block: First'), 'mymodule_block_second' => t('MyModule Block: Second'), ); foreach ($myblocks as $block_id => $block_label) { $this->derivatives[$block_id] = $base_plugin_definition; $this->derivatives[$block_id]['admin_label'] = $block_label; $this->derivatives[$block_id]['cache'] = DRUPAL_NO_CACHE; } return $this->derivatives; } }

As you can see, this is very similar to the way it had been done in Drupal 7 in hook_form_info(). The form changes, but essentially we return an array with all our block definitions, keyed by an internal block ID that allows us to differentiate which block we are processing.

The given example is very simplistic and you wouldn't use derivatives for this, because obviously you already know what blocks will be needed when you write the code. Instead you would create two block plugins in separate classes. But it should make the basic idea of derivatives clear. The getDerivativeDefinitions() method from the system module for example looks like this:

/** * {@inheritdoc} */ public function getDerivativeDefinitions(array $base_plugin_definition) { foreach ($this->menuStorage->loadMultiple() as $menu => $entity) { $this->derivatives[$menu] = $base_plugin_definition; $this->derivatives[$menu]['admin_label'] = $entity->label(); $this->derivatives[$menu]['cache'] = DRUPAL_NO_CACHE; } return $this->derivatives; }

In this example it is obvious why the blocks can't simply be defined in different block plugin classes, because they are not known at the time the code is written. So instead it needs to load all available menu entities from the storage controller and create one block for each menu.

That's it. I hope it helps someone. If you find errors or want to share something, please leave a comment.

Category: Drupal Planet
Categories: Elsewhere

Cheppers blog: #DrupalWorkParty Preliminary Stats and Thank-you's

Sat, 18/01/2014 - 13:05

January 15 2014 Work Party: Give Drupal a Birthday Present: Tackle a D8 Issue! generated a ton of twitter traffic reaching over 100,000. Check out the #DrupalWorkParty twitter wall for tweets and pictures of birthday cakes. (Thanks Pantheon for hosting community sites!). There were 14 issues worked on and tagged for DrupalWorkParty. And, 81 more people worked on core that day.

Categories: Elsewhere

Károly Négyesi: Drupal 8 progress from my / MongoDB perspective: update #25

Sat, 18/01/2014 - 06:38

Migrate in core works. Yesterday, after our weekly call (I am so thankful for eliza411 for organizing these calls, they are absolutely invaluable) a clear roadmap have emerged and I have written a rudimentary but functional drush command to run our migrations. Then I pointed it to a Drupal 6 database... and it worked. Just like that. Today penyaskito has finished the aggregator feed migration that eliza411 and mpgeek started and also written the aggregator item migration. These also work. We are basically done with the configuration migration and these are the first two content entities to work. Test instructions are posted for the curious. Despite every migration is integration tested and most sources (and some destinations too) are unit tested there is a limit to what we can test: for example, we check that the contents of the variable we believe in D6 contained the site slogan ends up where we think it should end up in Drupal 8 but there's no real way to check that the slogan that appeared in D6 really appears in D8 short of someone running the d6_system_site migration and checking this fact.

Categories: Elsewhere

Palantir: Diving In With Sculpin: A Designer's Holiday-Fueled Adventure

Fri, 17/01/2014 - 21:58

The Palantir design team has been refining our process to build responsive and modular in-browser prototypes and to create more reusable code. We've also been asked to create smaller-scale websites for clients who don't need all the bells and whistles that Drupal can provide. We think we’ve found a solution in a great tool called Sculpin.

Sculpin is a static site generator created by Beau Simensen. It is similar to other static site generators like Jekyll and Phrozn. Since Sculpin uses Twig like Drupal 8 does (and Drupal is our domain), we believe Sculpin to be a prototyping tool well-suited for Palantir’s design team. Using Twig templates starting in the design phase puts design prototypes one step closer to the real thing. The initial code we create will be reusable and can help us focus on object-oriented design from the very beginning.

We took Sculpin for a spin using Palantir’s 2013 Holiday site as a first experiment, and I was Dr. Frankenstein. As a designer at Palantir, I mostly work with HTML, Sass, and sometimes a little PHP and Javascript. Before this project, I had never worked directly with a templating system. This post won’t get too far into the technical nitty-gritty, but my observations about Sculpin should be useful for someone who, like me, is just getting started with Sculpin and Twig.

Anyway, after reading some Twig documentation and playing around with the Sculpin blog skeleton, I was ready to get started. Our Holiday site proved to be a great, low-pressure way to experiment with and discover the benefits and challenges of using Sculpin. Here’s what I learned during this first try:

Doing what it does best: blogging

Building Palantir’s holiday site in Sculpin was the perfect test of Sculpin’s basic functionality. Out of the box, Sculpin is meant for blogs. It comes with the “Sculpin Posts Bundle” baked-in, which essentially allows you to have a series of posts with some blogging functionality.

Creating and populating posts is simple. Once you create one HTML Twig template, all you have to do is create a markdown file and dump your content into it. A basic markdown file in Sculpin consists of YAML front matter and content. In the YAML, you can specify different variables.

This is also where you specify which type of template to use. Sculpin looks at your markdown files and magically* populates the content into your specified template.

The power of Twig

Twig is insanely useful. I’ve never personally used a templating engine before, and I was blown away. This might be obvious to some, but basically you create an HTML template with some empty content blocks. In the YAML front matter of your markdown file, you specify which template to use and in the body, you place the content for the blocks. Twig looks at the markdown file and takes the content you placed in each block and populates it in the HTML Twig template you specified.

This might not do much for you if you have only have a few posts, but when you have 25 posts, like I did for the Holiday site, populating markdown files is much easier than filling out 25 HTML files. Its usefulness really shines when you have to update a style or move some things around. You only have to update one template rather than 25 separate docs.

Struggles and roadblocks

My Sculpin experimentation wasn’t all rainbows and lollipops. I did run into a few roadblocks along the way including an installation hiccup involving a “timezone undefined” error, some concerns regarding the usability of markdown files for non-technical users, and a “--generate” bug that was giving me multiple outputs of the same post that linked nowhere. Granted, when I was creating our Holiday site at the end of last year, Sculpin’s documentation was much more sparse. A lot of progress has been made since then; it has since been updated and is more thorough with a lot of great new examples.

I don’t want to get into the technical side of these issues here, and a few of them have been resolved. There will likely be a more technically oriented post on its way soon. But I did want to mention them in case our readers are having any similar issues. Comment below, and we’ll compare notes.

The results: our Holiday site

When all was said and done, Sculpin gave me the flexibility and ease of use I desired to create our simple, blog-style Holiday site on a relatively tight deadline.

For the homepage, we chose a card-style layout. The cards are just a blog list with some fancy styles. The images, titles, and author’s names have been pulled into the card from the YAML front matter that is part of each markdown file.

On an internal page, I used two buckets for content: the introduction area and the main content area. I also included a sidebar share feature on each page using Twig’s include function. I took advantage of the pagination functionality and created a simple navigation at the top of the article page with “Next” “Last” and a “Home” button.

Again, here’s the link to the site, which is fully responsive and has a little bit of content for everybody.

Where I net out

Sculpin is a great way to prep for the impending release of Drupal 8, because it is relatively easy to get started and allowed this Twig novice to start experimenting with the powerful functionality Twig offers. And, if you need to create a small, blog-friendly site, don’t be afraid to get creative with your site by pushing the limitations of what Sculpin can do for you. In the end, I found Sculpin to be a formidable static site generator.

Final note to Beau: Why did you name it Sculpin?

*Palantir can neither confirm nor deny the use of actual magic in the creation of our Holiday site or in Sculpin’s capabilities.

Categories: Elsewhere

Forum One: Manually Migrating Comments from Drupal to Disqus

Fri, 17/01/2014 - 20:32

Even if you've never heard of Disqus before, you've almost certainly seen it. With slick social integration, support for a variety of platforms (including WordPress, Blogger, Tumblr, and Drupal) and a rapidly expanding user base, Disqus has become one of the most popular hosting services for website comments. If you've had misgivings about the commenting system you're using – or just envied the functionality and polish of other systems – you may get to a point where you decide (as we did for our Forum One blogs) to make the switch to Disqus.

Making this switch is fairly straightforward – but what about all those wonderful comments that your blogs have earned over the years? You don't want to lose all the valuable discussion, tips and virtual high fives from your online fans, do you? Probably not. So if you're using Drupal and looking to upgrade to Disqus from a system like Mollom, there are various resources that already exist for manually migrating those comments, but nothing explains the process from A-Z, so I've compiled this step-by-step guide to show you how to manually migrate your comments from Drupal.

There are two primary ways to migrate comments: (1) Using the API to automate the whole process by directly connecting to Disqus from Drupal and move the comments for you (which isn't working at the moment); or (2) Using the Disqus XML export tool to migrate comments from Drupal in XML format which you can then import manually into Disqus.

Versions
  • Disqus module (Do NOT use 6.x-1.9 which was the stable version at the time of writing this. In normal Drupal fashion the Dev version is the one to use which is 6.x-1.x-dev released Nov 22, 2013 which contains the extra features needed to do this.)
  • This was done in Drupal 6 though D7 is very similar
Step 1 - Module Enabled

Enable both Disqus and Disqus Migrate modules (Disqus Migrate provides migration tools for moving comments between Disqus and the Drupal comment system). Disqus has a great reference for this.

Note: There are additional steps to enable Disqus (ie. downloading and installing the API library, adding your Disqus keys and verifying connection with Disqus, as well as actual Drupal access permissions) which are well documented in the list of references I've provided at the foot of this article. Since those steps are primarily used for setting up the module rather than carrying out the actual migration, I will not review those steps here.

Step 2 - Export Drupal Comments

 

  • Navigate to the Disqus export page /admin/content/comment/disqus_export which contains two buttons, Export Awaiting Comments Using API (which doesn't work as of writing this) and Export All Comments to XML File which is the one you should click.
  • Select Export All Comments to XML File (This option is explained as Exporting via XML will just gather all of your websites comments and format them for importing manually into Disqus)
  • Save the file to your local file system.

At this point you will have all the comments from your site in XML format which we will not import into Disqus.

Step 3 - Import Drupal Comments Into Disqus

 

  • Log into Disqus and navigate to Admin -> Discussions (Tab) -> Import (Tab)
  • Select the Generic WXR sub-tab option.
  • Select the Upload WXR file browser button and select your XML file you saved locally.
  • Select Upload and Import button.

Upon completing this, the comments will be imported to Disqus and you might want to do some house cleaning of those comments using the Disqus Admin interface tools.

Step 4 - Optional, but pretty much needed

After the comments are imported you may notice that some comments that exist on your Drupal nodes are not being displayed in Disqus. This is most likely caused by URL aliases. Since Disqus maps comments to nodes by path, this means that example.com/node/32 and example.com/how-to-play-ball may be the same node, but Disqus doesn't know that – so the result is that those comments will only show for the URL that was in the export XML file. What we need to do now is provide Disqus URL mapping.

  • In Disqus navigate to Admin -> Discussions (Tab) -> Tools (Tab)
  • Select Start URL Mapper. This takes you to a page that will give you a list of comment paths Disqus knows so you can provide manual path mapping information OR you can have Drupal create a mapping file for you. I chose to do this using a custom script.

    This page shows you the format it expects the CSV format (comma separated value) file to be in:
    http://example.com/old-path/old/posta.html, http://example.com/new-path/new/posta.html
    http://example.com/old-path/old/postb.html, http://example.com/new-path/new/postb.html

  • Follow the link to download the CSV file from Disqus to your local file system and name it disqus-urls.csv.
  • Copy this CSV file to your Drupal root directory.
  • Create a file with the following PHP code in that same Drupal directory called disqus-custom-script.php

<?php

$base = 'http://forumone.com/';

$n = strlen($base);

foreach (file('disqus-urls.csv') as $url) {

  $path = substr(trim($url), $n);

  $source = drupal_get_normal_path($path);

  if ($source != $path) {

    echo "$base$path, $base$source\n";

  }

  else {

  $source = drupal_get_path_alias($path);

  echo "$base$path, $base$source\n";

  }

}

  • Browse to the PHP file (or execute your preferred way so you can see echo output). Browsing to it with yoursite.com/disqus-custom-script.php assuming you named your PHP file that and saved it in the root directory as asked.

    This will give you output that can be saved into a CSV file and will be in the exact format that Disqus expects.
     
  • In Disqus navigate back to Admin -> Discussions (Tab) -> Tools (Tab) -> Start URL Mapper (Button) and upload the text file containing the output from our PHP script.

Make sure you give it a few minutes to complete, as the mapping in Disqus isn't instantaneous, but you should start seeing your comments appear where they should for the URLs that were in the mapping CSV file.

That's it! Below I've provided a list of references that you can use when following these steps. If this guide is helpful for you, or if you discover a different solution, please leave us a comment ;)

References

Disqus Module

Disqus setup instructions for Drupal

Disqus URL mapper

Imported DISQUS Comments Not Showing Up On Drupal Nodes

There are two primary ways to migrate comments from Drupal to Disqus. The API way that automates the whole process by directly connecting to Disqus from Drupal and moves the comments for you. The second way is an XML export tool that Disqus migrate provides to migrate comments from Drupal in XML format which you can import into Disqus manually which is what I will show you how to do.

Categories: Elsewhere

Blink Reaction: Drupal's 13th Birthday Party in NYC

Fri, 17/01/2014 - 19:16
Wednesday night, 60 or so New York City Drupalists got together to celebrate Drupal's 13th birthday! There was pizza (from SGD), beer (from our gracious meetup host CPX Interactive), and a fabulous (if I may say so) birthday cake we at Blink Reaction chipped in. The treats were accompanied by yet another excellent and informative program of lightning talks and presentations from Drupalers both local and remote.
Categories: Elsewhere

Pages