Planet Drupal

Syndicate content
Drupal.org - aggregated feeds in category Planet Drupal
Updated: 21 min 25 sec ago

Chromatic: Code Standards: How Do We Implement Them?

Thu, 08/04/2016 - 20:06
pThis is the second post in a series about coding standards. In our first post, we talked about code standards and why they are so important. In this post, we’ll talk about how to implement Drupal coding standards in your projects./p pOther posts in this series:/p ol lia href=https://chromatichq.com/blog/code-standards-what-are-theyCode Standards: What Are They?/a/li lia href=https://chromatichq.com/blog/code-standards-how-do-we-implement-themCode Standards: How Do We Implement Them?/a/li liCode Standards: Formatting/li liCode Standards: Documentation/li liCode Standards: The t() function/li liCode Standards: Object Oriented Coding amp; Drupal 8/li liCode Standards: Twig in Drupal 8/li /ol h3Read the coding standards and keep them handy./h3 pIt’s a good idea to read over the Drupal coding standards so you have an idea of what’s expected. Even if you’re familiar with them, we can always use a refresher. They’re also a living document, so there’s a good chance something may have been changed or added since the last time you gave them a go-over. Use this post as a reason to read them again! Make sure you have them bookmarked for reference, as well. a href=https://www.drupal.org/coding-standardshttps://www.drupal.org/coding-standards/a/p h3Set up your editor for success/h3 pThe easiest way to keep your code clean and up to par is by having your editor do the work! There are a lot of editors out there, and even the ones that don’t have many bells and whistles can be set up to help you keep standards in mind when you’re coding./p h4Sublime Text/h4 pa href=https://chromatichq.com/blog/sublime-text-configuration-front-endersThis post/a from Chris is a couple years old, and geared towards front-end developers, but has lots of great a href=https://www.sublimetext.com/Sublime Text/a setup tips and plugins for every developer./p pThere’s some great info on drupal.org as well: a href=https://www.drupal.org/node/1346890https://www.drupal.org/node/1346890/a. Here you can find the basic configuration for adhering to Drupal coding standards, a script to set it up on OSX and Linux, and great plugins to help with development. Now you don’t need to worry about line length, spaces, tabs, line endings, and more. It’ll all be handled for you!/p h4PhpStorm/h4 pIf you’re using a href=https://confluence.jetbrains.com/display/PhpStorm/WelcomePhpStorm/a, their website has extensive instructions for getting set up with Drupal configuration a href=https://confluence.jetbrains.com/display/PhpStorm/Drupal+Development+using+PhpStorm#DrupalDevelopmentusingPhpStorm-CoderandPHPCodeSnifferIntegrationhere/a./p pIf you’re using another editor, you can see if it’s listed here: a href=https://www.drupal.org/node/147789https://www.drupal.org/node/147789/a/p pIf not, I’d suggest googling it, and if you don’t find instructions, create them and add them to the list!/p h3Review your own code - Use coder/h3 pThe easiest way to make sure you’re conforming to coding standards is to use a program like codesniffer. You can install coder, which is a Drupal module that allows you to check your code from the command line using custom rules and PHP Codesniffer. Here’s an example of what you might see:/p pimg src=http://blog-media.chromaticsites.com.s3.amazonaws.com/code-standards/codesniffer.png alt=Example Coder output //p pLet’s walk through this screenshot./p ol liI’ve navigated to a module directory - here, I’m checking the a href=https://www.drupal.org/project/countriescountries/a module. /li liThe alias I have set up for codesniffer, using custom Drupal rules, is strongdrupalcs/strong./li liI want to test the file at strongtests/countries.test/strong./li liSometimes this command can take a little while. If it seems like it’s hanging, especially if you’ve checked a directory, it may be too much, so try a single file at a time./li liThe first thing you’ll see is which file you checked, and the full path. Here, it’s strong/Applications/MAMP/htdocs/countries/tests/countries.test/strong/li liNext, you’ll see how many errors and warnings, and how many lines they affect - there can be multiple errors per line, and coder will catch them all. /li liNext, each error or warning will be listed line by line. /li /ol pI find it’s easiest to go in order, because sometimes one error causes others - coder can only understand so much, so if you have, for example, an array that has one line indented improperly, it may also think the subsequent lines are indented improperly, even if they’re correct./p pChristopher did a great post on PHP Codesnifffer last year, check it out a href=https://chromatichq.com/blog/learn-and-enforce-coding-standards-php-codesnifferhere/a./p pGenerally, you want to run coder every time you make a change, and before you commit your code or submit a patch. This way, you’re always writing clean code, and anyone reviewing your code is reviewing it for content, and they don’t have to worry about style. Of course, everyone is human and we all make mistakes. Sometimes you’ll push up a tiny change without running coder, and not realize there was a style issue. That’s why team code reviews are so important!/p h3Team code reviews - make the time/h3 pThe most successful teams build in time to review one another’s code. There’s no substitute for code reviews by another person, and making sure that you view them as an essential part of your process - the same goes for reviews on drupal.org. When planning time and resources for a project, make sure that there is time set aside for code reviews. When you’re working on contrib projects, make sure you take a look at issues marked Need Review, and test them. If you want a way to dive into a project or just Drupal and contrib work in general, reviewing patches is a great way to get acclimated. You get exposed to other people’s code, and if you find something that needs to be corrected, that will stick with you and you’ll remember it./p pTwo things to remember when reviewing other people’s code, or when receiving reviews of your own:/p ol liTreat others as you would like to be treated. Be kind, courteous, respectful, and constructive. Be aware of your tone. It’s easy to come off more harshly than you intended, especially when working quickly. Take just a second to re-read your comments, especially if you’re communicating with someone you’re not acquainted with./li liTake everything in stride, and don’t take it personally. Those reviewing your code want it to be good, and corrections aren’t a personal attack. This can be especially hard when you start out, and even after years, you can still get a comment that comes off in a way that hurts your feelings. Don’t dwell on it! Thank them, make the corrections, submit them, and chances are, they’ll thank you, too./li /ol pNow you know what code standards are, why they’re important, and how you can get started implementing them in your code. Set up your editor, install coder, and get ready for our next code standards post on formatting! We’ll talk about the nitty gritty of how you should format your Drupal code./p p[1] Hero photo attribution: a href=https://www.flickr.com/photos/ursonate/charlene mcbride/a/p

Chromatic: Civil Comments Drupal Module

Thu, 08/04/2016 - 20:06
blockquote pa href=https://www.civilcomments.com/Civil Comments/a is a platform that brings real-world social cues to comments sections via crowd-sourced moderation and powerful community management tools. Civil Comments is the first commenting platform specifically designed to improve the way people treat each other online./p /blockquote pUnlike others who have thrown up their hands and accepted that the comments sections of the Internet would either be dominated by bullies and trolls, or become a moderation burden for a site's editors, the team at Civil is attempting to solve the problem with community moderation. It is an exciting new take on a widespread problem, and Chromatic is thrilled to bring a href=https://www.drupal.org/project/civilcommentsCivil Comments integration to Drupal/a with a new contrib module./p pIt should be noted (and is on the a href=https://www.drupal.org/project/civilcommentsproject page/a!) that there is not currently a free version of Civil Comments. For the time being, it is only available with a subscription as Civil continues work on the platform, but from what I understand a free version is on the horizon./p pA special thanks to a href=https://chromatichq.com/users/christopher-torgalsonChristopher Torgalson/a and a href=https://chromatichq.com/users/alannaAlanna Burke/a, whose contributions helped get this project off the ground!/p

Chromatic: Digging Into Drupal 8: Code Snippets for Site Builders

Thu, 08/04/2016 - 20:06
pThe more I work with Drupal 8, the more I realize how much has changed for developers in the Drupal community. While the transition to a modern, object-oriented system is what's best for the longevity of the platform, it certainly doesn't come without challenges. As someone who doesn't come from an OOP background, I've found the transition difficult at times. In many cases, I know exactly emwhat/em I want to do, just not emhow/em to do it the Drupal 8 way. On top of this, tutorials and blog posts on D8 are all over the map in terms of accuracy. Many posts written during D8's development cycle are no longer applicable because of API changes, etc./p pBelow is a list of snippets that might be helpful to site builders or developers more familiar with D7 hooks and procedural. It might also be useful to OOP folks who are new to Drupal in general. My goal below is to add to and update these snippets over time./p h2Routes amp; Links/h2 h3Determine the Current Drupal Route/h3 pNeed to know what the current Drupal route is or need to run some logic against the current route? You can get the current route like so:/p precode$route = \Drupal::routeMatch()-gt;getRouteName(); /code/pre pTo some, the code\Drupal::routeMatch()/code syntax might look foreign (it did to me). Here's a rundown of what's happening here:/p pFirst, code\Drupal/code. This is calling the global Drupal class, which, in Drupal 8, is a bridge between procedural and OO methods of writing Drupal code. The following comes from a href=https://api.drupal.org/api/drupal/core%21lib%21Drupal.php/class/Drupal/8.2.xthe documentation/a:/p blockquote pThis class acts as a unified global accessor to arbitrary services within the system in order to ease the transition from procedural code to injected OO code./p /blockquote pRight. Moving on to code::routeMatch()/code. Here we're using the coderouteMatch()/code method which Retrieves the currently active route match object. Simple enough. But what is :: all about? a href=http://stackoverflow.com/a/3173511This StackOverflow answer/a helped me to understand what that's all about./p pFrom there, the a href=https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Routing!RouteMatch.php/function/RouteMatch%3A%3AgetRouteName/8.2.xgetRouteName()/a method returns the current route name as a string. Here are some example routes: codeentity.node.canonical/code, codeview.frontpage/code and codenode.type_add/code./p h3Is this the Front Page Route?/h3 pNeed to check if the current route is the front page route? There's a service and method for that:/p precode// Is the current route/path the front page? if ($is_front = \Drupal::service('path.matcher')-gt;isFrontPage()) {} /code/pre pHere we're calling the codepath.matcher/code service (defined in code/core/core.services.yml/code) and using the codeisFrontPage()/code method. For more on services, check out the a href=https://api.drupal.org/api/drupal/core!core.api.php/group/container/8.2.xServices and Dependency Injection Container/a documentation on api.drupal.org which helped me understand how all of these bits work together and the emwhy/em of their structure./p h3Get the Requested Path/h3 pNeed to know what the current page's requested path was, as opposed to the route? You can do this:/p precode$current_uri = \Drupal::request()-gt;getRequestUri(); /code/pre h3Redirect to a Specific Route/h3 pNeed to redirect to a specific page? In Drupal 7, you would likely handle this with codedrupal_goto()/code in your page callback function. In Drupal 8, you can use codeRedirectResponse()/code for that. Here is the a href=https://www.drupal.org/node/2023537relevant changelog/a./p pHere are some examples, borrowed heavily from said changelog. First, in procedural PHP:/p precodeuse Symfony\Component\HttpFoundation\RedirectResponse; function my_redirect() { return new RedirectResponse(\Drupal::url('user.page')); } /code/pre pHere is how you would use a Drupal 8 controller to accomplish the same thing:/p precodeuse Drupal\Core\Controller\ControllerBase; class MyControllerClass extends ControllerBase { public function foo() { //... return $this-gt;redirect('user.page'); } } /code/pre h3Links on the Fly/h3 pDrupal 7 and prior relied heavily on the a href=https://api.drupal.org/api/drupal/includes%21common.inc/function/l/7.xl() function/a. (In fact, I would wager this was my most used function over the years. In Drupal 8, if you need to create links on the fly, utilize the a href=https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Link.php/class/Link/8.2.xLink class/a/p precode$link = \Drupal\Core\Link::fromTextAndUrl($text, $url); /code/pre h2Working with Entities/h2 h3Query Database for Entities/h3 pIf you need to query the database for some nodes (or any other entity) you should use the entityQuery service. The syntax a href=https://www.drupal.org/node/1343708should be pretty familiar/a to most D7 developers who have used EntityFieldQuery:/p precode// Query for some entities with the entity query service. $query = \Drupal::entityQuery('node') -gt;condition('status', 1) -gt;condition('type', 'article') -gt;range(0, 10) -gt;sort('created', 'DESC'); $nids = $query-gt;execute(); /code/pre h3Loading Entities/h3 pIf you need to load the actual entities, you can do so a number of ways:/p pWhile the following will technically work in Drupal 8:/p precode$node = entity_load_multiple('node', $nids); /code/pre pThis method has been a href=https://api.drupal.org/api/drupal/core!includes!entity.inc/function/entity_load_multiple/8.2.xdeprecated in Drupal 8/a and will be removed before Drupal 9, in favor of methods overriding codeEntity::loadMultiple()/code. To future-proof your code, you would do something like the following:/p precode$nodes = \Drupal::entityTypeManager()-gt;getStorage('node')-gt;loadMultiple($nids); /code/pre pHere's how you would do similar for a single node:/p precode$node = \Drupal::entityTypeManager()-gt;getStorage('node')-gt;load($nid); /code/pre pHere are a few other entity snippets that might be useful:/p precode// Link to an entity using the entity's link method. $author_link = $user-gt;toLink(); // Do the same thing, but customize the link text. $author_link = $user-gt;toLink('Some Custom Text'); // Given a node object, here's how to determine its type: $type = $node-gt;getType(); // To get the full user entity of the node's author: $author = $node-gt;getOwner(); // To get the raw ID of the author of a node: $author_id = $node-gt;getOwnerId(); /code/pre h2Image Styles/h2 pNeed to whip up an image using a particular image style on the fly? This will work for that:/p precode// Create an instance of an image using a specific image style, given a path to a file. $style = \Drupal\image\Entity\ImageStyle::load('yourStyle_image'); $img_path = $user-gt;field_profile_some_image-gt;entity-gt;getFileUri(); $img_style_url = $style-gt;buildUrl($img_path); /code/pre pThat's it for now. I intend to keep this post updated as we learn more and more about the new world of Drupal 8. If you have a snippet worth sharing, a href=https://twitter.com/chromatichqdrop us a line/a via Twitter and we’ll add it to this post (with credit of course)./p

Chromatic: Javascript Theme Functions in Drupal 7

Thu, 08/04/2016 - 20:06
pLike it or not, sometimes you have to output HTML in javascript./p pRecently, I ran across a line of code something like this while reviewing a pull-request for a client:/p precode class=javascriptvar inputMarkup = 'lt;spangt;lt;label data-val=' + inputText + ' for=checkbox-' + index + ' data-tid=' + tid + 'gt;' + inputText + 'lt;/labelgt;lt;input type=checkbox id=checkbox-' + index + ' data-tid=' + tid + ' data-val=' + inputText + ' /gt;lt;/spangt;'; /code/pre pAside from the fact that this code was hard to read (and therefore would be more difficult to maintain), the same code was used with no significant modification in three separate locations in the pull-request./p pIn PHP, most developers familiar with Drupal would immediately reach for one of the well-known parts of Drupal's theme system, a href=https://chromatichq.com/blog/badcamp-2015-transitioning-theme-and-theme-functions-render-arrays-and-templatesrender arrays, codetheme()/code, or a code*.tpl.php/code file/a. In javascript, however, I seldom see much use of a href=https://www.drupal.org/node/304258Drupal 7's extensive javascript API/a (also made available in a a href=http://read.theodoreb.net/drupal-jsapi/index.htmlnicely browseable--though not quite up-to-date--form/a by a href=https://www.drupal.org/u/nod_nod_/a)./p pIn this case, the relatively difficult-to-read code, combined with the fact that it was repeated several times across more than one file were clear signs that it should be placed into a theme function./p pThe a href=https://www.drupal.org/node/304258#drupal-themecodeDrupal.theme()/code/a function in the javascript API works much like codetheme()/code in PHP. When using theming functions in PHP, we never call them directly, instead using a href=https://api.drupal.org/api/drupal/includes!theme.inc/function/theme/7.xthe codetheme()/code function/a./p pIn javascript, it's similar; when output is required from a given theme function, we call codeDrupal.theme()/code with the name of the theme function required, and any variable(s) it requires./p pFor example, drupal.org shows the following usage:/p precode class=jsDrupal.theme('myThemeFunction', 50, 100, 500); /code/pre pThe example uses codeDrupal.theme()/code to call the theme function, codemyThemeFunction()/code, and pass it the arguments it requires (code50/code, code100/code, and code500/code in this instance). A theme function can accept whatever number of arguments is necessary, but if your theme function requires more than one parameter, it's good practice to define the function to take a single javascript object containing the parameters required by the function./p pSo in the case of my code-review, I suggested we use a theme function like this:/p precode class=js/** * Provides a checkbox and label wrapped in a span. * * @param {object} settings * Configuration object for function. * @param {int} settings.index * A numeric index, used for creating an `id` attribute and corresponding * `for` attribute. * @param {string} settings.inputText * The text to display as the label text and in various attributes. * @param {int} settings.tid * A Drupal term id. * * @return {string} * A string of HTML with a checkbox and label enclosed by a span. */ Drupal.theme.checkboxMarkup = function(settings) { use strict; var checkboxId = 'checkbox-' + settings.index; var inputText = Drupal.checkPlain(settings.inputText); var checkboxMarkup = ''; // Assemble the markup--string manipulation is fast, but if this needs // to become more complex, we can switch to creating dom elements. checkboxMarkup += 'lt;spangt;'; checkboxMarkup += 'lt;label data-val=' + inputText + ' for=' + checkboxId + ' data-tid=' + settings.tid + 'gt;'; checkboxMarkup += inputText; checkboxMarkup += 'lt;/labelgt;'; checkboxMarkup += 'lt;input type=checkbox value=' + inputText + ' id=' + checkboxId + ' data-tid=' + settings.tid + ' data-val=' + inputText + 'gt;'; checkboxMarkup += 'lt;/spangt;'; return checkboxMarkup; }; /code/pre pThis allowed the calling code to be much simpler:/p precode class=js// Creates themed checkbox. checkboxMarkup = Drupal.theme('checkboxMarkup', { index: i, inputText: $('.inputText').val(), tid: $('.tid') }); $container.append(checkboxMarkup); /code/pre pThe HTML generation is now also more loosely coupled, and more portable, meaning that we can easily use codeDrupal.theme.checkboxMarkup()/code elsewhere in this project--or in any other Drupal project./p

Chromatic: May the Git --FORCE Be With You [Advanced Git Webinar]

Thu, 08/04/2016 - 20:06
h3This webinar has passed. Keep an eye on our blog for future webinars./h3 pYou know how to get things done with git: pull, add, commit, push; but have you mastered it like a Jedi does the force? Nothing is a more lasting record of our work then our git commits. In a galaxy where companies ask you for your Github account in lieu of, or in addition to a resume, we have one more reason to make sure that our commit history is as readable as our code itself./p pIn this one hour session, we will cover:/p ul liRewriting commits/li liReordering commits/li liCombining commits/li liThe perfect commit message/li liFinding bugs using git/li liAvoiding common pitfalls/li /ul pJoin us for this session and you will leave a jedi-level git master!/p blockquote pThese Are Not the Commits You're Looking For/p /blockquote

Chromatic: Chromatic Site Launch Guide

Thu, 08/04/2016 - 20:06
pWhen we prepare to launch a site, we all generally follow a rough checklist of items (if only in our own minds!) to ensure sure that all systems are go. At Chromatic, we wanted to produce a repeatable process that we could share not only amongst ourselves, but also with the community; and so the a href=/chromatic-site-launch-guideChromatic Site Launch Guide/a was born./p pWe are hosting this guide outside of our blog as it is a living document and will change over time. Feel free to bookmark it and refer back to it the next time you are preparing to launch a site. The content is generated from a a href=https://github.com/ChromaticHQ/site-launch-guiderepository on Github/a, which means modifications via pull requests are welcome!/p

Chromatic: Chromatic at DrupalCon New Orleans

Thu, 08/04/2016 - 20:06
pDrupalCon New Orleans is nearly here and Chromatic will be attending in full force! Here's the rundown of what you need to know:/p h2Learn About Render Arrays from Gus Childs/h2 pa href=https://chromatichq.com/users/gusGus/a will be presenting his session on Drupal 8 render arrays on Tuesday at 1pm in the Blackmesh Room (267-268): a href=https://events.drupal.org/neworleans2016/sessions/aha-understanding-and-using-render-arrays-drupal-8Aha! Understanding and Using Render Arrays in Drupal 8/a. If you're ever been confused by render arrays or just want to learn the best practices for how you're strongsupposed/strong to use them, be sure not to miss this session. Gus happens to be an awesome presenter to boot!/p h2Schedule or Attend a BoF in the Chromatic Room/h2 pWe're once again sponsoring a Birds of a Feather room. BoFs are a great way for folks to get together and discuss interesting topics in a more informal setting. There's already some great BoFs scheduled for the Chromatic room, including a href=https://events.drupal.org/neworleans2016/bofs/drupal-vm-and-local-drupal-development-teamsone on Drupal VM and Local Development/a from the well-known a href=https://www.drupal.org/u/geerlingguygeerlingguy/a. We have a couple BoFs of our own too:/p ul lia href=https://events.drupal.org/neworleans2016/bofs/worklife-balance-how-do-you-manage-itWork/life balance - How Do You Manage It?/a/li lia href=https://events.drupal.org/neworleans2016/bofs/elements-great-user-storyticket-0Elements of a Great User Story/Ticket/a/li /ul pIf you have a great idea for a BoF, a href=https://events.drupal.org/neworleans2016/birds-featherschedule one/a for the Chromatic room!/p h2Connect with Us at one of the Summits/h2 pIn addition to attending the conference proper, we're once again sending our leadership to the a href=https://events.drupal.org/neworleans2016/business-summitBusiness Summit/a, as well as sending a couple of folks to the a href=https://events.drupal.org/neworleans2016/media-and-publishing-summitMedia amp; Publishing Summit/a./p h2Grab Some Swag/h2 pEvery year, DrupalCon attendees rave about how awesome and comfortable our t-shirts are. That's because we don't believe in making swag that we ourselves wouldn't love to wear. This year is no different. For NOLA, we've made a limited run of some special vintage baseball tees, printed on 3/4 sleeve American Apparel 50/50 cotton. These shirts are our best yet and a href=https://chromatichq.com/blog/vintage-tee-giveaway-drupalcon-new-orleanswe want to give you one for FREE/a!/p pSee you in New Orleans!/p

Evolving Web: Creating Landing Pages with Drupal 8 and Paragraphs

Thu, 08/04/2016 - 17:53
a href=https://evolvingweb.ca/%20%20___ img src=https://evolvingweb.ca/sites/default/files/styles/medium/public/2016-08/FTNALSRJ-2016.08.04-09-21-09.png?itok=nRPGYjFF width=191 height=220 alt=Landing page layout typeof=Image class=img-responsive / /apAs Drupal themers and site builders, we often have to look for creative solutions to build landing pages. Landing pages are special pages often used for marketing campaigns, to attract particular audiences, or to aggregate content about a certain topics./p pWe want lading pages to be attractive and entice users to click, but we often also need them to be flexible so we can communicate different things. We want landing pages to look great the day we launch a website, but also to be flexible so that a site admin can change the content or add a new page and it still looks great./pa href=https://evolvingweb.ca/blog/creating-landing-pages-drupal-8-and-paragraphs hreflang=enread more/a

Jeff Geerling's Blog: How to attach a CSS or JS library to a View in Drupal 8

Thu, 08/04/2016 - 17:21
div class=field field-name-body field-type-text-with-summary field-label-hiddendiv class=field-itemsdiv class=field-item even property=content:encodedpFile this one under the 'it's obvious, but only after you've done it' category—I needed to attach a CSS library to a view in Drupal 8 via a custom module so that, wherever the view displayed on the site, the custom CSS file from my module was attached. The process for CSS and JS libraries is pretty much identical, but here's how I added a CSS file as a library, and made sure it was attached to my view:/p h2Add the CSS file as a library/h2 pIn Drupal 8, a href=https://www.drupal.org/node/2169605codedrupal_add_css()/code, codedrupal_add_js()/code, and codedrupal_add_library()/code were removed/a (for various reasons), and now, to attach CSS or JS assets to views, nodes, etc., you need to use Drupal's code#attached/code functionality to 'attach' assets (like CSS and JS) to rendered elements on the page./p pIn my custom module (codecustom.module/code), I added the CSS file codecss/custom_view.css/code:/p/div/div/div

OSTraining: There Will Never Be a Drupal 9

Thu, 08/04/2016 - 15:09
pYes, that's a big statement in the title, so let me explain./p pLots of OSTraining customers are looking into Drupal 8 and they have questions about Drupal 8's future. If they invest in the platform today, how long will that invesment last.nbsp;/p pThis is just my personal opinion, but I think an investment in Drupal 8 will last a long, long time./p pDrupalnbsp;8 took five years. It was a mammoth undertaking, and no-one in the Drupalnbsp;community has the energy for a similar re-write.nbsp;/p

Frederic Marand: How to display time and memory use for Drush commands

Thu, 08/04/2016 - 14:08
pWhen you use Drush, especially in crontabs, you may sometimes be bitten by RAM or duration limits. Of course, running Drush with the -d option will provide this information, but it will only do so at the end of an annoyingly noisy output debugging the whole command run./p pOn the other hand, just running the Drush command within a codetime/code command won't provide fine memory reporting. Luckily Drush implements hooks to make acquiring this information easily, so here is a small gist you can use as a standalone Drush plugin or add to a module of your own:/p pa href=http://blog.riff.org/2016_08_04_how_to_display_time_and_memory_use_for_drush_commands target=_blankread more/a/p

lakshminp.com: Drupal composer workflow - part 2

Thu, 08/04/2016 - 09:41
div class=field-bodypIn the a href=http://www.lakshminp.com/drinking-drupal-composer-kool-aidprevious post/a, we saw how to add and manage modules and module dependencies in Drupal 8 using Composer./p pIn this post we shall see how to use an exclusive composer based Drupal 8 workflow. Let's start with a vanilla Drupal install. The recommended way to go about it is to use a href=https://github.com/drupal-composer/drupal-projectDrupal Composer project/a./p precode$ composer create-project drupal-composer/drupal-project:8.x-dev drupal-8.dev /code/pre pIf you are a careful observer(unlike me), you will notice that a downloaded Drupal 8 package ships with the vendor/ directory. In other words, we need not install the composer dependencies when we download it from d.o. On the other hand, if you git cloned Drupal 8, it won't contain the vendor/ directory, hence the extra step to run #96;composer install#96; in root directory. The top level directory contains a codecomposer.json/code and the name of the package is codedrupal/drupal/code, which is more of a wrapper for the codedrupal/core/code package inside the codecore//code directory. The a href=https://packagist.org/packages/drupal/coredrupal/core/a package installs Drupal core and its dependencies. The a href=https://packagist.org/packages/drupal/drupaldrupal/drupal/a helps you build a site around Drupal core, maintains dependencies related to your site and modules etc./p pa href=https://packagist.org/packages/drupal-composer/drupal-projectDrupal project/a takes a slightly different project structure.It installs core and its dependencies similar to drupal/drupal. It also installs the latest stable versions of drush and drupal console./p precode$ composer create-project drupal-composer/drupal-project:8.x-dev d8dev --stability dev --no-interaction /code/pre h2New directory structure/h2 pEverything Drupal related goes in the codeweb//code directory, including codecore/code, codemodules/code, codeprofiles/code and codethemes/code. Contrast this with the usual structure where there is a set of top level directories named codecore/code, codemodules/code, codeprofiles/code and codethemes/code./p pdrush and drupal console(both latest stable versions) gets installed inside codevendor/bin/code directory.The reason Drush and Drupal console are packaged on a per project basis is to avoid any dependency issues which we might normally face if they are installed globally./p h2How to install Drupal/h2 pDrupal can be installed using the typical codesite-install/code command provided by drush./p precode$ cd d8dev/web $ ../vendor/bin/drush site-install --db-url=mysql://lt;db-user-namegt;:lt;db-passwordgt;@localhost/lt;db-namegt; -y /code/pre h2Downloading modules/h2 pModules can be downloaded using composer. They get downloaded in the codeweb/modules/contrib/code directory./p precode$ cd d8dev $ composer require drupal/devel:8.1.x-dev /code/pre pThe following things happen when we download a module via composer./p ol liComposer updates the top level composer.json and adds codedrupal/devel:8.1.x-dev/code as a dependency./li /ol precode class=language-js require: { composer/installers: ^1.0.20, drupal-composer/drupal-scaffold: ^2.0.1, cweagans/composer-patches: ~1.0, drupal/core: ~8.0, drush/drush: ~8.0, drupal/console: ~1.0, drupal/devel: 8.1.x-dev }, /code/pre ol liComposer dependencies(if any) for that module get downloaded in the top level vendor directory. These are specified in the codecomposer.json/code file of that module. At the time of writing this, Devel module does not have any composer dependencies./li /ol precode class=language-js license: GPL-2.0+, minimum-stability: dev, require: { } } /code/pre pMost modules in Drupal 8 were(are) written without taking composer into consideration. We use the codedrush dl/code command every time which parses our request and downloads the appropriate version of the module from drupal.org servers. Downloading a module via composer requires the module to have a composer.json as a minimal requirement. So how does composer download all Drupal contrib modules if they don't have any composer.json? The answer lies in a not so secret sauce ingredient we added in our top level composer.json:/p precoderepositories: [ { type: composer, url: https://packagist.drupal-composer.org } ], /code/pre pComposer downloads all packages from a central repository called a href=https://packagist.org/Packagist/a. It is the a href=https://www.npmjs.com/npmjs/a equivalent of PHP. Drupal provides its own flavour of Packagist to serve modules and themes exclusively hosted at Drupal.org. Drupal packagist ensures that contrib maintainers need not add composer.json to their project./p pLet's take another module which does not have a codecomposer.json/code, like Flag(at the time of writing this). Let's try and download flag using composer./p precode$ composer require drupal/flag:8.4.x-dev ./composer.json has been updated gt; DrupalProject\composer\ScriptHandler::checkComposerVersion Loading composer repositories with package information Updating dependencies (including require-dev) - Installing drupal/flag (dev-8.x-4.x 16657d8) Cloning 16657d8f84b9c87144615e4fbe551ad9a893ad75 Writing lock file Generating autoload files gt; DrupalProject\composer\ScriptHandler::createRequiredFiles /code/pre pNeat. Drupal Packagist parses contrib modules and serves the one which matches the name and version we gave when we ran that composer require command./p h2Specifying package sources/h2 pThere is one other step you need to do to complete your composer workflow, i.e., switching to the official Drupal.org a href=https://www.drupal.org/node/2718229composer repository/a. The actual codecomposer.json/code contains Drupal packagist as the default repository./p precoderepositories: [ { type: composer, url: https://packagist.drupal-composer.org } ], /code/pre pAdd the Drupal.org composer repo using the following command:/p precode$ composer config repositories.drupal composer https://packages.drupal.org/8 /code/pre pNow, your repositories entry in codecomposer.json/code should look like this:/p precoderepositories: { 0: { type: composer, url: https://packagist.drupal-composer.org }, drupal: { type: composer, url: https://packages.drupal.org/8 } } /code/pre pTo ensure that composer indeed downloads from the new repo we specified above, let's remove the drupal packagist entry from codecomposer.json/code./p precode$ composer config --unset repositories.0 /code/pre pThe repositories config looks like this now:/p precoderepositories: { drupal: { type: composer, url: https://packages.drupal.org/8 } } /code/pre pNow, let's download a module from the new repo./p precode$ composer require drupal/token -vvv /code/pre pAs a part of the verbose output, it prints the following:/p precode... Loading composer repositories with package information Downloading https://packages.drupal.org/8/packages.json Writing /home/lakshmi/.composer/cache/repo/https---packages.drupal.org-8/packages.json into cache ... /code/pre pwhich confirms that we downloaded from the official package repo./p h2Custom package sources/h2 pSometimes, you might want to specify your own package source for a custom module you own, say, in Github. This follows the usual conventions for adding VCS package sources in Composer, but I'll show how to do it in Drupal context./p pFirst, add your github URL as a VCS repository using the codecomposer config/code command./p precode$ composer config repositories.restful vcs https://github.com/RESTful-Drupal/restful /code/pre pYour composer.json will look like this after the above command is run successfully:/p precoderepositories: { drupal: { type: composer, url: https://packages.drupal.org/8 }, restful: { type: vcs, url: https://github.com/RESTful-Drupal/restful } } /code/pre pIf you want to download a package from your custom source, you might want it to take precedence to the official package repository, as order really matters for composer. I haven't found a way to do this via cli, but you can edit the composer.json file and swap both package sources to look like this:/p precoderepositories: { restful: { type: vcs, url: https://github.com/RESTful-Drupal/restful }, drupal: { type: composer, url: https://packages.drupal.org/8 } } /code/pre pNow, lets pick up restful 8.x-3.x. We can specify a Github branch by prefixing with a dev-./p precode$ composer require drupal/restful:dev-8.x-3.x-not-ready /code/pre pOnce restful is downloaded, composer.json is updated accordingly./p precoderequire: { composer/installers: ^1.0.20, drupal-composer/drupal-scaffold: ^2.0.1, cweagans/composer-patches: ~1.0, drupal/core: ~8.0, drush/drush: ~8.0, drupal/console: ~1.0, drupal/devel: 8.1.x-dev, drupal/flag: 8.4.x-dev, drupal/mailchimp: 8.1.2, drupal/token: 1.x-dev, drupal/restful: dev-8.x-3.x-not-ready }, /code/pre h2Updating drupal core/h2 pDrupal core can be updated by running:/p precode$ composer update drupal/core gt; DrupalProject\composer\ScriptHandler::checkComposerVersion Loading composer repositories with package information Updating dependencies (including require-dev) - Removing drupal/core (8.1.7) - Installing drupal/core (8.1.8) Downloading: 100% Writing lock file Generating autoload files Downloading: 100% Downloading: 100% Downloading: 100% Downloading: 100% Downloading: 100% Downloading: 100% Downloading: 100% Downloading: 100% Downloading: 100% Downloading: 100% Downloading: 100% Downloading: 100% Downloading: 100% Downloading: 100% Downloading: 100% gt; DrupalProject\composer\ScriptHandler::createRequiredFiles /code/pre pAs the output reads, we updated core from 8.1.7 to 8.1.8. We will revisit the Writing lock file part in a moment. After this step is successful, we have to run drush updatedb to do any database updates. This applies to even updating modules./p precode$ cd d8dev/web $ ../vendor/bin/drush updatedb /code/pre h2Updating modules/h2 pOne of the cool things I like about composer workflow is, I can update selective modules, or even a single module. This is a href=http://drupal.stackexchange.com/questions/3871/drush-updatedb-for-a-single-modulenot possible/a using drush. The command for updating a module, say, devel is:/p precode$ composer update drupal/devel gt; DrupalProject\composer\ScriptHandler::checkComposerVersion Loading composer repositories with package information Updating dependencies (including require-dev) Nothing to install or update Generating autoload files gt; DrupalProject\composer\ScriptHandler::createRequiredFiles /code/pre pHmmm. Looks like devel is already the latest bleeding edge version. To quickly revise and ensure what composer related artifacts we need to check in to version control,/p h3Should you check in the vendor/ directory?/h3 pComposer a href=https://getcomposer.org/doc/faqs/should-i-commit-the-dependencies-in-my-vendor-directory.mdrecommends/a that you shouldn't, but there are some environments that don't support composer(ex. a href=https://docs.acquia.com/article/drupal_8_using_composer_acquia_cloudAcquia Cloud/a), in which case you have to check in your vendor folder too./p h3Should you check in the composer.json file?/h3 pBy now, you should know the answer to this question :)/p h3Should you check in the composer.lock file?/h3 pDamn yes. composer.lock contains the exact version of the dependencies which are installed. For example, if your project depends on Acme 1.#42;, and you install 1.1.2 and your co-worker runs codecomposer install/code after a month or so, it might install Acme 1.1.10, which might introduce version discrepancies in your project. To prevent this, codecomposer install/code will check if a lock file exists, and install only that specific version recorded or locked down in the lock file. The only time the lock file changes is when you run a codecomposer update/code to update your project dependencies to their latest versions. When that happens, composer updates the lock file with the newer version that got installed./p /div span class=tag-link a href=/categories/drupalDrupal/a,/span span class=tag-link a href=/categories/drupal-8Drupal 8/a,/span span class=tag-link a href=/categories/drupal-planetDrupal Planet/a/span

Metal Toad: Avoiding Drupal 7 #AJAX Pitfalls

Thu, 08/04/2016 - 04:10
span class=field field-node--title field-name-title field-type-string field-label-hidden data-quickedit-field-id=node/1116/title/en/rssAvoiding Drupal 7 #AJAX Pitfalls/span span class=field field-node--created field-name-created field-type-created field-label-hidden data-quickedit-field-id=node/1116/created/en/rssAugust 3rd, 2016/span span class=field field-node--uid field-name-uid field-type-entity-reference field-label-hidden data-quickedit-field-id=node/1116/uid/en/rss a title=View user profile. href=/people/marcusbernal lang= about=/people/marcusbernal typeof=schema:Person property=schema:name datatype=Marcus Bernal/a/span div class=field field-node--body field-name-body field-type-text-with-summary field-label-hidden data-quickedit-field-id=node/1116/body/en/rss div class=field-items div class=field-itempRather than provide a basic how-to tutorial on Drupal's form API #AJAX functionality, I decided to address a few pitfalls that often frustrate developers, both junior and senior alike. To me, it seems that most of the problems arise from the approach rather than the direct implementation of the individual elements./p captionTL;DR/caption ulliTry to find a reasonable argument for not using span class=geshifiltercode class=text geshifilter-text#ajax/code/span./li liDo emnot/em do any processing in the callback function, it's too late, I'm sorry./li liForce button names that are semantic and scalable./li liTemplate buttons and remove unnecessary validation from span class=geshifiltercode class=text geshifilter-text#ajax/code/span actions./li liUse span class=geshifiltercode class=text geshifilter-text'#theme_wrappers' =gt; array('container')/code/span rather than span class=geshifiltercode class=text geshifilter-text'#preffix'/code/span and span class=geshifiltercode class=text geshifilter-text'#suffix'/code/span./li /ulh3Is AJAX Even Needed?/h3 pSince span class=geshifiltercode class=text geshifilter-text#ajax/code/span hinders accessibility and adds that much more complexity, before continuing on with the approach, reconsider others. Drupal will automatically handle the no js accessibility issue, providing full page refreshes with unsubmitted forms, but issues will still exist for those using screen readers. Because the time to request and receive the new content is indeterminate, screen readers will fail at providing the users with audible descriptions of the new content. Simply by choosing to use span class=geshifiltercode class=text geshifilter-text#ajax/code/span, you will automatically exclude those needing visual assistance. So, if it is simply hiding/showing another field or sets of fields, then span class=geshifiltercode class=text geshifilter-text#states/code/span would be a better fit. If the task is to select something out of a large selection, a multiple page approach or even an entity reference with an autocomplete field could suffice./p pThis example is a simplified version of a new field type used to select data from a Solr index of another site's products. The number of products was in the 200k's and the details needed to decide on a selection was more than just the product names, so building checkboxes/radios/select box would be too unwieldy and an autocomplete could not provide enough information. Also, the desired UX was to use a modal rather than multiple pages./p h3Callback is a Lie/h3 pAn misconception that many developers, including past myself, have is that the AJAX callback function is the place to perform bulk of the logic. I have come to approach this function as just one that returns the portion of the form that I want. Any logic that changes the structure or data of a form should be handled in the form building function, because there it will be persistent as Drupal will store those changes but ignore any done within AJAX callback. So, the role of the callback function is simply a getter for a portion of the span class=geshifiltercode class=text geshifilter-text$form/code/span array. At first, it may seem easier to just hardcode the logic to return the sub array, but I recommend a dynamic solution that relies on the trigger's nested position relative to the AJAX container./p div class=geshifilter div class=php geshifilter-php style=font-family:monospace; pre style=font-family: monospace; font-weight: normal; font-style: normalspan style=color: #000000; font-weight: bold;function/span product_details_selector_field_widget_formspan style=color: #009900;(/spanspan style=color: #339933;amp;/spanspan style=color: #000088;$form/spanspan style=color: #339933;,/span span style=color: #339933;amp;/spanspan style=color: #000088;$form_state/spanspan style=color: #339933;,/span span style=color: #000088;$field/spanspan style=color: #339933;,/span span style=color: #000088;$instance/spanspan style=color: #339933;,/span span style=color: #000088;$langcode/spanspan style=color: #339933;,/span span style=color: #000088;$items/spanspan style=color: #339933;,/span span style=color: #000088;$delta/spanspan style=color: #339933;,/span span style=color: #000088;$element/spanspan style=color: #009900;)/span span style=color: #009900;{/span span style=color: #339933;.../span span style=color: #666666; font-style: italic;// Add a property to nested buttons to declare the relative depth/span span style=color: #666666; font-style: italic;// of the trigger to the AJAX targeted container/span span style=color: #000088;$form/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'container'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'modal'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'next_page'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'#nested_depth'/spanspan style=color: #009900;]/span span style=color: #339933;=/span span style=color: #cc66cc;1/spanspan style=color: #339933;;/span span style=color: #339933;.../span span style=color: #009900;}/span/pre/div /div pThen, for the callback, some blind logic can easily return the portion of form to render and return./p div class=geshifilter div class=php geshifilter-php style=font-family:monospace; pre style=font-family: monospace; font-weight: normal; font-style: normalspan style=color: #009933; font-style: italic;/** * AJAX callback to replace the container of the product_details_selector. *//span span style=color: #000000; font-weight: bold;function/span product_details_selector_ajax_returnspan style=color: #009900;(/spanspan style=color: #000088;$form/spanspan style=color: #339933;,/span span style=color: #000088;$form_state/spanspan style=color: #009900;)/span span style=color: #009900;{/span span style=color: #666666; font-style: italic;// Trim the array of array parents for the trigger down to the container/span span style=color: #000088;$array_parents/span span style=color: #339933;=/span span style=color: #000088;$form_state/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'triggering_element'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'#array_parents'/spanspan style=color: #009900;]/spanspan style=color: #339933;;/span span style=color: #000088;$pop_count/span span style=color: #339933;=/span span style=color: #cc66cc;1/spanspan style=color: #339933;;/span span style=color: #666666; font-style: italic;// The trigger is always included, so always have to pop/span span style=color: #b1b100;if/span span style=color: #009900;(/spana href=http://www.php.net/issetspan style=color: #990000;isset/span/aspan style=color: #009900;(/spanspan style=color: #000088;$form_state/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'triggering_element'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'#nested_depth'/spanspan style=color: #009900;]/spanspan style=color: #009900;)/spanspan style=color: #009900;)/span span style=color: #009900;{/span span style=color: #000088;$pop_count/span span style=color: #339933;+=/span span style=color: #000088;$form_state/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'triggering_element'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'#nested_depth'/spanspan style=color: #009900;]/spanspan style=color: #339933;;/span span style=color: #009900;}/span span style=color: #b1b100;for/span span style=color: #009900;(/spanspan style=color: #000088;$i/span span style=color: #339933;=/span span style=color: #cc66cc;0/spanspan style=color: #339933;;/span span style=color: #000088;$i/span span style=color: #339933;lt;/span span style=color: #000088;$pop_count/spanspan style=color: #339933;;/span span style=color: #000088;$i/spanspan style=color: #339933;++/spanspan style=color: #009900;)/span span style=color: #009900;{/span span style=color: #b1b100;if/span span style=color: #009900;(/spana href=http://www.php.net/emptyspan style=color: #990000;empty/span/aspan style=color: #009900;(/spanspan style=color: #000088;$array_parents/spanspan style=color: #009900;)/spanspan style=color: #009900;)/span span style=color: #009900;{/span span style=color: #b1b100;break/spanspan style=color: #339933;;/span span style=color: #666666; font-style: italic;// Halt the loop whenever there are no more items to pop/span span style=color: #009900;}/span a href=http://www.php.net/array_popspan style=color: #990000;array_pop/span/aspan style=color: #009900;(/spanspan style=color: #000088;$array_parents/spanspan style=color: #009900;)/spanspan style=color: #339933;;/span span style=color: #009900;}/span span style=color: #666666; font-style: italic;// Return the nested array /span span style=color: #b1b100;return/span drupal_array_get_nested_valuespan style=color: #009900;(/spanspan style=color: #000088;$form/spanspan style=color: #339933;,/span span style=color: #000088;$array_parents/spanspan style=color: #009900;)/spanspan style=color: #339933;;/span span style=color: #666666; font-style: italic;// This function is so awesome/span span style=color: #009900;}/span/pre/div /div pWith this approach, any future modifications to the $form array outside of the container are inconsequential to this widget. And if this widget's array is modified outside of the module, the modifier will just have to double check the span class=geshifiltercode class=text geshifilter-text#nested_depth/code/span values rather than completely overriding the callback function./p h3Name the Names/h3 pFor clarity, from here on span class=geshifiltercode class=text geshifilter-textname/code/span will refer to what will be used for the HTML attributes span class=geshifiltercode class=text geshifilter-textid/code/span and span class=geshifiltercode class=text geshifilter-textname/code/span for containers (divs) and buttons, respectively./p pLike with everything in programming, naming is the initial task that can make development, current and future, a simple walk through the business logic or a spaghetti mess of oh yeahs. This is especially true for span class=geshifiltercode class=text geshifilter-text#ajax/code/span which requires the use of HTML ID attributes to place the new content as well as handling user actions (triggers). For most developers, this step is brushed over because the idea of their work being used in an unconventional or altered way is completely out of their purview. But a solid approach will reduce the frustration of future developers including yourself for this span class=geshifiltercode class=text geshifilter-text#ajax/code/span widget right now./p pIn this example and most cases these triggers will be buttons, but Drupal 7 also allowed for other triggering elements, such as the select box or radio buttons. Now, this leaves a weird situation where these other triggers have semantic names, but buttons will simply be named 'op'. For a simple form, this is no big deal, but for something complex, determining which action to take relies on the comparison of the button values. This gets much harder to do when you have multiple fields of the same type, bring in translation, and/or the client decides to change the wording later on in the project. So, my suggestion is to override the button names and base the logic on them./p div class=geshifilter div class=php geshifilter-php style=font-family:monospace; pre style=font-family: monospace; font-weight: normal; font-style: normalspan style=color: #666666; font-style: italic;// drupal_html_class() converts _ to - as well as removing dangerous characters/span span style=color: #000088;$trigger_prefix/span span style=color: #339933;=/span drupal_html_classspan style=color: #009900;(/spanspan style=color: #000088;$field/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'field_name'/spanspan style=color: #009900;]/span span style=color: #339933;./span span style=color: #0000ff;'-'/span span style=color: #339933;./span span style=color: #000088;$langcode/span span style=color: #339933;./span span style=color: #0000ff;'-'/span span style=color: #339933;./span span style=color: #000088;$delta/spanspan style=color: #009900;)/spanspan style=color: #339933;;/span span style=color: #666666; font-style: italic;// Short trigger names/span span style=color: #000088;$show_trigger/span span style=color: #339933;=/span span style=color: #000088;$trigger_prefix/span span style=color: #339933;./span span style=color: #0000ff;'-modal-open'/spanspan style=color: #339933;;/span span style=color: #000088;$next_trigger/span span style=color: #339933;=/span span style=color: #000088;$trigger_prefix/span span style=color: #339933;./span span style=color: #0000ff;'-modal-next'/spanspan style=color: #339933;;/span span style=color: #000088;$prev_trigger/span span style=color: #339933;=/span span style=color: #000088;$trigger_prefix/span span style=color: #339933;./span span style=color: #0000ff;'-modal-prev'/spanspan style=color: #339933;;/span span style=color: #000088;$search_trigger/span span style=color: #339933;=/span span style=color: #000088;$trigger_prefix/span span style=color: #339933;./span span style=color: #0000ff;'-modal-search'/spanspan style=color: #339933;;/span span style=color: #000088;$add_trigger/span span style=color: #339933;=/span span style=color: #000088;$trigger_prefix/span span style=color: #339933;./span span style=color: #0000ff;'-add'/spanspan style=color: #339933;;/span span style=color: #000088;$remove_trigger/span span style=color: #339933;=/span span style=color: #000088;$trigger_prefix/span span style=color: #339933;./span span style=color: #0000ff;'-remove'/spanspan style=color: #339933;;/span span style=color: #000088;$cancel_trigger/span span style=color: #339933;=/span span style=color: #000088;$trigger_prefix/span span style=color: #339933;./span span style=color: #0000ff;'-cancel'/spanspan style=color: #339933;;/span span style=color: #666666; font-style: italic;// Div wrapper/span span style=color: #000088;$ajax_container/span span style=color: #339933;=/span span style=color: #000088;$trigger_prefix/span span style=color: #339933;./span span style=color: #0000ff;'-ajax-container'/spanspan style=color: #339933;;/span/pre/div /div pThe prefix in the example is built as a field form widget example. It is unique to field's name, language, and delta so that multiple instances can exist in the same form. But if your widget is not a field, it is still best to start with someting that is dynamically unique. Then, semantics are used to fill out the rest of the trigger names needed as well as the container's ID./p h3Button Structure/h3 pIdeally, every button within the span class=geshifiltercode class=text geshifilter-text#ajax/code/span widget should simply cause a rebuild of the same container, regardless of the changes triggered within the nested array. Since the callback is reduced to a simple getter for the container's render array, the majority of trigger properties can be templated. Now, all buttons that are built off of this template, barring intentional overrides, will prevent validation of elements outside of the widget, prevent submission, and have the same span class=geshifiltercode class=text geshifilter-text#ajax/code/span command to run./p div class=geshifilter div class=php geshifilter-php style=font-family:monospace; pre style=font-family: monospace; font-weight: normal; font-style: normalspan style=color: #000088;$ajax_button_template/span span style=color: #339933;=/span a href=http://www.php.net/arrayspan style=color: #990000;array/span/aspan style=color: #009900;(/span span style=color: #0000ff;'#type'/span span style=color: #339933;=gt;/span span style=color: #0000ff;'button'/spanspan style=color: #339933;,/span span style=color: #666666; font-style: italic;// Not 'submit'/span span style=color: #0000ff;'#value'/span span style=color: #339933;=gt;/span tspan style=color: #009900;(/spanspan style=color: #0000ff;'Button Template'/spanspan style=color: #009900;)/spanspan style=color: #339933;,/span span style=color: #666666; font-style: italic;// To be replaced/span span style=color: #0000ff;'#name'/span span style=color: #339933;=gt;/span span style=color: #0000ff;'button-name'/spanspan style=color: #339933;,/span span style=color: #666666; font-style: italic;// To be replaced/span span style=color: #0000ff;'#ajax'/span span style=color: #339933;=gt;/span a href=http://www.php.net/arrayspan style=color: #990000;array/span/aspan style=color: #009900;(/span span style=color: #0000ff;'callback'/span span style=color: #339933;=gt;/span span style=color: #0000ff;'product_details_selector_ajax_return'/spanspan style=color: #339933;,/span span style=color: #0000ff;'wrapper'/span span style=color: #339933;=gt;/span span style=color: #000088;$ajax_container/spanspan style=color: #339933;,/span span style=color: #0000ff;'method'/span span style=color: #339933;=gt;/span span style=color: #0000ff;'replace'/spanspan style=color: #339933;,/span span style=color: #0000ff;'effect'/span span style=color: #339933;=gt;/span span style=color: #0000ff;'fade'/spanspan style=color: #339933;,/span span style=color: #009900;)/spanspan style=color: #339933;,/span span style=color: #0000ff;'#validate'/span span style=color: #339933;=gt;/span a href=http://www.php.net/arrayspan style=color: #990000;array/span/aspan style=color: #009900;(/spanspan style=color: #009900;)/spanspan style=color: #339933;,/span span style=color: #0000ff;'#submit'/span span style=color: #339933;=gt;/span a href=http://www.php.net/arrayspan style=color: #990000;array/span/aspan style=color: #009900;(/spanspan style=color: #009900;)/spanspan style=color: #339933;,/span span style=color: #0000ff;'#limit_validation_errors'/span span style=color: #339933;=gt;/span a href=http://www.php.net/arrayspan style=color: #990000;array/span/aspan style=color: #009900;(/spana href=http://www.php.net/arrayspan style=color: #990000;array/span/aspan style=color: #009900;(/spanspan style=color: #009900;)/spanspan style=color: #009900;)/spanspan style=color: #339933;,/span span style=color: #666666; font-style: italic;// Prevent standard Drupal validation/span span style=color: #0000ff;'#access'/span span style=color: #339933;=gt;/span span style=color: #009900; font-weight: bold;TRUE/spanspan style=color: #339933;,/span span style=color: #666666; font-style: italic;// Display will be conditional based on the button and the state/span span style=color: #009900;)/spanspan style=color: #339933;;/span   span style=color: #666666; font-style: italic;// Limit the validation errors down to the specific item's AJAX container/span span style=color: #666666; font-style: italic;// Once again, the field could be nested in multiple entity forms/span span style=color: #666666; font-style: italic;// and the errors array must be exact. If the widget is not a field, /span span style=color: #666666; font-style: italic;// then use the '#parents' key if available./span span style=color: #b1b100;if/span span style=color: #009900;(/spanspan style=color: #339933;!/spana href=http://www.php.net/emptyspan style=color: #990000;empty/span/aspan style=color: #009900;(/spanspan style=color: #000088;$element/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'#field_parents'/spanspan style=color: #009900;]/spanspan style=color: #009900;)/spanspan style=color: #009900;)/span span style=color: #009900;{/span span style=color: #b1b100;foreach/span span style=color: #009900;(/spanspan style=color: #000088;$element/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'#field_parents'/spanspan style=color: #009900;]/span span style=color: #b1b100;as/span span style=color: #000088;$field_parent/spanspan style=color: #009900;)/span span style=color: #009900;{/span span style=color: #000088;$ajax_button_template/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'#limit_validation_errors'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #cc66cc;0/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #009900;]/span span style=color: #339933;=/span span style=color: #000088;$field_parent/spanspan style=color: #339933;;/span span style=color: #009900;}/span span style=color: #009900;}/span span style=color: #000088;$ajax_button_template/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'#limit_validation_errors'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #cc66cc;0/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #009900;]/span span style=color: #339933;=/span span style=color: #000088;$field/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'field_name'/spanspan style=color: #009900;]/spanspan style=color: #339933;;/span span style=color: #000088;$ajax_button_template/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'#limit_validation_errors'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #cc66cc;0/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #009900;]/span span style=color: #339933;=/span span style=color: #000088;$langcode/spanspan style=color: #339933;;/span span style=color: #000088;$ajax_button_template/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'#limit_validation_errors'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #cc66cc;0/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #009900;]/span span style=color: #339933;=/span span style=color: #000088;$delta/spanspan style=color: #339933;;/span span style=color: #000088;$ajax_button_template/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'#limit_validation_errors'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #cc66cc;0/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #009900;]/span span style=color: #339933;=/span span style=color: #0000ff;'container'/spanspan style=color: #339933;;/span/pre/div /div pLimiting the validation errors will prevent other, unrelated fields from affecting the modal's functionality. Though, if certain fields are a requirement they can be specified here. This example will validate any defaults, such as required fields, that exist within the container./p div class=geshifilter div class=php geshifilter-php style=font-family:monospace; pre style=font-family: monospace; font-weight: normal; font-style: normalspan style=color: #000088;$form/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'container'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'modal'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'page_list_next'/spanspan style=color: #009900;]/span span style=color: #339933;=/span a href=http://www.php.net/arrayspan style=color: #990000;array/span/aspan style=color: #009900;(/span span style=color: #0000ff;'#value'/span span style=color: #339933;=gt;/span tspan style=color: #009900;(/spanspan style=color: #0000ff;'Next'/spanspan style=color: #009900;)/spanspan style=color: #339933;,/span span style=color: #0000ff;'#name'/span span style=color: #339933;=gt;/span span style=color: #000088;$next_trigger/spanspan style=color: #339933;,/span span style=color: #0000ff;'#access'/span span style=color: #339933;=gt;/span span style=color: #009900; font-weight: bold;FALSE/spanspan style=color: #339933;,/span span style=color: #0000ff;'#page'/span span style=color: #339933;=gt;/span span style=color: #cc66cc;1/spanspan style=color: #339933;,/span span style=color: #666666; font-style: italic;// For page navigation of Solr results/span span style=color: #009900;)/span span style=color: #339933;+/span span style=color: #000088;$ajax_button_template/spanspan style=color: #339933;;/span span style=color: #666666; font-style: italic;// Keys not defined in the first array will be set from the values in the second/span   span style=color: #666666; font-style: italic;// Fade effect within the modal is disorienting/span span style=color: #000088;$element/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'container'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'modal'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'search_button'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'#ajax'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'effect'/spanspan style=color: #009900;]/span span style=color: #339933;=/span span style=color: #0000ff;'none'/spanspan style=color: #339933;;/span span style=color: #000088;$element/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'container'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'modal'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'page_list_prev'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'#ajax'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'effect'/spanspan style=color: #009900;]/span span style=color: #339933;=/span span style=color: #0000ff;'none'/spanspan style=color: #339933;;/span span style=color: #000088;$element/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'container'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'modal'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'page_list_next'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'#ajax'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'effect'/spanspan style=color: #009900;]/span span style=color: #339933;=/span span style=color: #0000ff;'none'/spanspan style=color: #339933;;/span/pre/div /div pThe span class=geshifiltercode class=text geshifilter-text#page/code/span key is arbitrary and simply used to keep track of the page state without having to clutter up the span class=geshifiltercode class=text geshifilter-text$form_state/code/span, especially since the entire array of the triggering element is already stored in that variable. Other buttons within the widget do not need to track the page other than previous and next. Clicking the search button should result in the first page of a new search while cancel and selection buttons will close the modal anyway./p h3Smoking Gun/h3 pDetermining the widget's state can now start easily with checks on the name and data of the trigger./p div class=geshifilter div class=php geshifilter-php style=font-family:monospace; pre style=font-family: monospace; font-weight: normal; font-style: normalspan style=color: #000088;$trigger/span span style=color: #339933;=/span span style=color: #009900; font-weight: bold;FALSE/spanspan style=color: #339933;;/span span style=color: #b1b100;if/span span style=color: #009900;(/spanspan style=color: #339933;!/spana href=http://www.php.net/emptyspan style=color: #990000;empty/span/aspan style=color: #009900;(/spanspan style=color: #000088;$form_state/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'triggering_element'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'#name'/spanspan style=color: #009900;]/spanspan style=color: #009900;)/spanspan style=color: #009900;)/span span style=color: #009900;{/span span style=color: #000088;$trigger/span span style=color: #339933;=/span span style=color: #000088;$form_state/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'triggering_element'/spanspan style=color: #009900;]/spanspan style=color: #339933;;/span span style=color: #009900;}/span span style=color: #000088;$trigger_name/span span style=color: #339933;=/span span style=color: #000088;$trigger/span ? span style=color: #000088;$trigger/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'#name'/spanspan style=color: #009900;]/span span style=color: #339933;:/span span style=color: #009900; font-weight: bold;FALSE/spanspan style=color: #339933;;/span   span style=color: #000088;$open_modal/span span style=color: #339933;=/span span style=color: #009900; font-weight: bold;FALSE/spanspan style=color: #339933;;/span span style=color: #b1b100;if/span span style=color: #009900;(/spana href=http://www.php.net/strposspan style=color: #990000;strpos/span/aspan style=color: #009900;(/spanspan style=color: #000088;$trigger_prefix/span span style=color: #339933;./span span style=color: #0000ff;'-modal'/spanspan style=color: #339933;,/span span style=color: #000088;$trigger_name/spanspan style=color: #009900;)/span span style=color: #339933;===/span span style=color: #cc66cc;0/spanspan style=color: #009900;)/spanspan style=color: #009900;)/span span style=color: #009900;{/span span style=color: #000088;$open_modal/span span style=color: #339933;=/span span style=color: #009900; font-weight: bold;TRUE/spanspan style=color: #339933;;/span span style=color: #009900;}/span   span style=color: #339933;.../span span style=color: #666666; font-style: italic;// Hide or show modal/span span style=color: #000088;$form/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'container'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'modal'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'#access'/spanspan style=color: #009900;]/span span style=color: #339933;=/span span style=color: #000088;$open_modal/spanspan style=color: #339933;;/span   span style=color: #339933;.../span span style=color: #666666; font-style: italic;// Obtain page number regardless of next or previous/span span style=color: #000088;$search_page/span span style=color: #339933;=/span span style=color: #cc66cc;1/spanspan style=color: #339933;;/span span style=color: #b1b100;if/span span style=color: #009900;(/spana href=http://www.php.net/issetspan style=color: #990000;isset/span/aspan style=color: #009900;(/spanspan style=color: #000088;$trigger/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'#page'/spanspan style=color: #009900;]/spanspan style=color: #009900;)/spanspan style=color: #009900;)/span span style=color: #009900;{/span span style=color: #000088;$search_page/span span style=color: #339933;=/span span style=color: #000088;$trigger/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'#page'/spanspan style=color: #009900;]/spanspan style=color: #339933;;/span span style=color: #009900;}/span   span style=color: #339933;.../span span style=color: #666666; font-style: italic;// Calculate if a next page button should be shown/span span style=color: #000088;$next_offset/span span style=color: #339933;=/span span style=color: #009900;(/spanspan style=color: #000088;$search_page/span span style=color: #339933;+/span span style=color: #cc66cc;1/spanspan style=color: #009900;)/span span style=color: #339933;*/span span style=color: #000088;$per_page/spanspan style=color: #339933;;/span span style=color: #b1b100;if/span span style=color: #009900;(/spanspan style=color: #000088;$next_offset/span span style=color: #339933;gt;/span span style=color: #000088;$search_results/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'total'/spanspan style=color: #009900;]/spanspan style=color: #009900;)/span span style=color: #009900;{/span span style=color: #000088;$form/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'container'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'modal'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'next_page'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'#access'/spanspan style=color: #009900;]/span span style=color: #339933;=/span span style=color: #009900; font-weight: bold;TRUE/spanspan style=color: #339933;;/span span style=color: #666666; font-style: italic;// or '#disabled' if the action is too jerky/span span style=color: #009900;}/span/pre/div /div h3Theming/h3 pNow, to where most developers start their problem solving, how to build the AJAX-able portion. Drupal requires an element with an ID attribute to target where the new HTML is inserted. Ideally, it is best to make the target element and the AJAX content one and the same. There are a couple of ways for doing this, the most common that I see is far too static and therefore difficult to modify or extend./p div class=geshifilter div class=php geshifilter-php style=font-family:monospace; pre style=font-family: monospace; font-weight: normal; font-style: normalspan style=color: #666666; font-style: italic;// Div wrapper for AJAX replacing/span span style=color: #000088;$element/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'contianer'/spanspan style=color: #009900;]/span span style=color: #339933;=/span a href=http://www.php.net/arrayspan style=color: #990000;array/span/aspan style=color: #009900;(/span span style=color: #0000ff;'#prefix'/span span style=color: #339933;=gt;/span span style=color: #0000ff;'lt;div id='/span span style=color: #339933;./span span style=color: #000088;$ajax_container/span span style=color: #339933;./span span style=color: #0000ff;'gt;'/spanspan style=color: #339933;,/span span style=color: #0000ff;'#suffix'/span span style=color: #339933;=gt;/span span style=color: #0000ff;'lt;/divgt;'/spanspan style=color: #339933;,/span span style=color: #009900;)/spanspan style=color: #339933;;/span/pre/div /div pThis does solve the solution for the time being. It renders any child elements properly while wrapping with the appropriate HTML. But if another module, function, or developer wants to add other information, classes for instance, they would have to recreate the entire span class=geshifiltercode class=text geshifilter-text#prefix/code/span string. What I propose is to use the span class=geshifiltercode class=text geshifilter-text#theme_wrappers/code/span key instead./p div class=geshifilter div class=php geshifilter-php style=font-family:monospace; pre style=font-family: monospace; font-weight: normal; font-style: normalspan style=color: #666666; font-style: italic;// Div wrapper for AJAX replacing/span span style=color: #000088;$element/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'container'/spanspan style=color: #009900;]/span span style=color: #339933;=/span a href=http://www.php.net/arrayspan style=color: #990000;array/span/aspan style=color: #009900;(/span span style=color: #0000ff;'#theme_wrappers'/span span style=color: #339933;=gt;/span a href=http://www.php.net/arrayspan style=color: #990000;array/span/aspan style=color: #009900;(/spanspan style=color: #0000ff;'container'/spanspan style=color: #009900;)/spanspan style=color: #339933;,/span span style=color: #0000ff;'#attributes'/span span style=color: #339933;=gt;/span a href=http://www.php.net/arrayspan style=color: #990000;array/span/aspan style=color: #009900;(/span span style=color: #0000ff;'id'/span span style=color: #339933;=gt;/span span style=color: #000088;$ajax_container/spanspan style=color: #339933;,/span span style=color: #009900;)/spanspan style=color: #339933;,/span span style=color: #009900;)/spanspan style=color: #339933;;/span   span style=color: #b1b100;if/span span style=color: #009900;(/spana href=http://www.php.net/in_arrayspan style=color: #990000;in_array/span/aspan style=color: #009900;(/spanspan style=color: #000088;$trigger_name/spanspan style=color: #339933;,/span span style=color: #000088;$list_triggers/spanspan style=color: #009900;)/spanspan style=color: #009900;)/span span style=color: #009900;{/span span style=color: #000088;$element/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'container'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'#attributes'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'class'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #009900;]/span span style=color: #339933;=/span span style=color: #0000ff;'product-details-selector-active-modal'/spanspan style=color: #339933;;/span span style=color: #009900;}/span   span style=color: #666666; font-style: italic;// Div inner-wrapper for modal styling/span span style=color: #000088;$element/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'container'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'modal'/spanspan style=color: #009900;]/span span style=color: #339933;=/span a href=http://www.php.net/arrayspan style=color: #990000;array/span/aspan style=color: #009900;(/span span style=color: #0000ff;'#theme_wrappers'/span span style=color: #339933;=gt;/span a href=http://www.php.net/arrayspan style=color: #990000;array/span/aspan style=color: #009900;(/spanspan style=color: #0000ff;'container'/spanspan style=color: #009900;)/spanspan style=color: #339933;,/span span style=color: #0000ff;'#attributes'/span span style=color: #339933;=gt;/span a href=http://www.php.net/arrayspan style=color: #990000;array/span/aspan style=color: #009900;(/span span style=color: #0000ff;'class'/span span style=color: #339933;=gt;/span a href=http://www.php.net/arrayspan style=color: #990000;array/span/aspan style=color: #009900;(/spanspan style=color: #0000ff;'dialog-box'/spanspan style=color: #009900;)/spanspan style=color: #339933;,/span span style=color: #009900;)/spanspan style=color: #339933;,/span span style=color: #009900;)/spanspan style=color: #339933;;/span   span style=color: #000088;$element/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'container'/spanspan style=color: #009900;]/spanspan style=color: #009900;[/spanspan style=color: #0000ff;'product_details'/spanspan style=color: #009900;]/span span style=color: #339933;=/span a href=http://www.php.net/arrayspan style=color: #990000;array/span/aspan style=color: #009900;(/span span style=color: #0000ff;'#theme_wrappers'/span span style=color: #339933;=gt;/span a href=http://www.php.net/arrayspan style=color: #990000;array/span/aspan style=color: #009900;(/spanspan style=color: #0000ff;'container'/spanspan style=color: #009900;)/spanspan style=color: #339933;,/span span style=color: #0000ff;'#attributes'/span span style=color: #339933;=gt;/span a href=http://www.php.net/arrayspan style=color: #990000;array/span/aspan style=color: #009900;(/span span style=color: #0000ff;'class'/span span style=color: #339933;=gt;/span a href=http://www.php.net/arrayspan style=color: #990000;array/span/aspan style=color: #009900;(/spanspan style=color: #0000ff;'product-details'/spanspan style=color: #009900;)/spanspan style=color: #339933;,/span span style=color: #009900;)/spanspan style=color: #339933;,/span span style=color: #0000ff;'#access'/span span style=color: #339933;=gt;/span span style=color: #009900; font-weight: bold;TRUE/spanspan style=color: #339933;,/span span style=color: #009900;)/spanspan style=color: #339933;;/span/pre/div /div pI have experienced in the past that using span class=geshifiltercode class=text geshifilter-text#theme/code/span, causes the form elements to be rendered wrong, losing their names and their relationships with the data. The themes declared within span class=geshifiltercode class=text geshifilter-text#theme_wrappers/code/span will render later in the pipeline, so form elements will not lose their identity and the div container can be built dynamically. That is, simply to add a class, one just needs to add another array element to span class=geshifiltercode class=text geshifilter-text$element['container']['#attributes']['class']/code/span./p h3Conclusion/h3 pI do not propose the above to be hard-set rules to follow, but they should be helpful ideas that allow for more focus to be put into the important logic rather than basic functional logistics. View the form as transforming throughout time as the user navigates while the AJAX functionality is simply a way to refresh a portion of that form and the complexity of building your form widget will reduce down to the business logic needed./p /div /div /div

Mediacurrent: Pixel #039;Perfection#039; front-end development. Or, Avoiding awkward conversations with the Quality Assurance team

Wed, 08/03/2016 - 21:32
img typeof=foaf:Image src=http://www.mediacurrent.com/sites/default/files/styles/thumb_blog_spotlight/public/pixelperfect.png?itok=v3pOHA5S width=200 height=152 / h3What is 'pixel perfect'?/h3 pPixel perfection is when the finished coded page and the design file are next to each other, you can not tell them apart. To quote a href=http://webdesign.tutsplus.com/articles/great-design-hurts-striving-for-pixel-perfection--webdesign-1016Brandon Jones/a :/p blockquotep...so precise, so pristine, so detailed that the casual viewer can’t tell the difference./p/blockquote

Chromatic: In Search of a Better Local Development Server

Wed, 08/03/2016 - 19:26
h2The problem with development environments/h2 pIf you're a developer and you're like me, you have probably tried out a emlot/em of different solutions for running development web servers. A list of the tools I've used includes:/p ul liFull LAMP stack on an Ubuntu workstation,/li liFull LAMP stack on an OS X workstation,/li lia href=https://www.apachefriends.org/index.htmlXAMPP/a/li lia href=https://www.mamp.info/en/MAMP/a/li lia href=https://bitnami.com/stack/lampBitnami LAMP Stack/a/li lia href=https://www.acquia.com/downloadsAcquia Dev Desktop/a/li /ul pThat's not even a complete list — I know I've also tried other solutions a href=https://en.wikipedia.org/wiki/List_of_Apache%E2%80%93MySQL%E2%80%93PHP_packagesfrom the wider LAMP community/a, still others a href=https://www.drupal.org/search/site/vagrantfrom the Drupal community/a, and I've rolled my own virtual-machine based servers too./p pAll of these tools have their advantages, but I was never wholly satisfied with any of them. Typically, I would encounter problems with stability when emmultiple/em sites on emone/em server needed different configurations, or problems customizing the environment emenough/em to make it useful for certain projects. Even the virtual-machine based solutions often suffered from the same kinds of problems — even when I experimented with version-controlling critical config files such as vhost configurations, codephp.ini/code and codemy.cnf/code files, and building servers with configuration management tools like a href=https://en.wikipedia.org/wiki/Chef_(software)Chef/a and a href=https://en.wikipedia.org/wiki/Puppet_%28software%29Puppet/a./p h2Drupal VM/h2 pEventually, I found a href=http://www.drupalvm.com/Drupal VM/a, a very well-thought-out virtual machine-based development tool. It’s based on a href=https://www.vagrantup.com/Vagrant/a and another configuration management tool, a href=https://en.wikipedia.org/wiki/Ansible_(software)Ansible/a. This was immediately interesting to me, partly because a href=https://chromatichq.com/blog/automated-servers-and-deployments-ansible-jenkinsAnsible is the tool we use internally/a to configure project servers, but also because the whole point of configuration management is to reliably produce identical configuration whenever the software runs. (Ansible also relies on a href=https://en.wikipedia.org/wiki/YAMLYAML/a for configuration, so it fits right in with Drupal 8)./p h2My VM wishlist/h2 pSince I've worked with various VM-based solutions before, I had some fairly specific requirements, some to do with how I work, some to do with how the Chromatic team works, and some to do with the kinds of clients I'm currently working with. So I wanted to see if I could configure Drupal VM to work within these parameters:/p h31. The VM must be emindependently/em version-controllable/h3 pChromatic is a distributed team, and I don't think any two of us use identical toolchains. Because of that, we don't currently want to include any development environment code in our actual project repositories. But we emdo/em need to be able to control the VM strongconfiguration/strong in git. By this I mean that we need to keep every setting on the virtual server emoutside/em of the server in version-controllable text files./p pVersion-controlling a development server in this way also implies that there will be little or no need to perform administrative tasks such as creating or editing virtual host files or php.ini files (in fact, configuration of the VM in git means that we emmust/em not edit config files in the VM since they would be overridden if we recreate or reprovision it)./p pFurthermore, it means that there's relatively little need to actually log into the VM, and that most of our work can be performed using our day-to-day tools (i.e. what we've configured on our own workstations, and not whatever tools exist on the VM)./p h32. The VM must be manageable as a git submodule/h3 pOn a related note, I wanted to be able to add the VM to the development server repository and never touch its files—I'm interested in maintaining the emconfiguration/em of the VM, but not so much the VM itself./p pIt may help to explain this in Drupal-ish terms; when I include a contrib module in a Drupal project, I expect to be able to interact with that module without needing to modify it. This allows the module to be updated independently of the main project. I wanted to be able to work with the VM in the same way./p h33. The VM must be able to be recreated from scratch at any time/h3 pThis is a big one for me. If I somehow mess up a dev server, I want to be able to check out the latest version of the server in git, boot it and go back to work immediately. Specifically, I want to be able to restore (all) the database(s) on the box more or less automatically when the box is recreated./p pSimilarly, I usually work at home on a desktop workstation. But when I need to travel or work outside the house, I need to be able to quickly set up the project(s) I'll be working on on my laptop./p pFinally, I want the VM configuration to be easy to share with my colleagues (and sometimes with clients directly)./p h34. The VM must allow multiple sites emper/em server/h3 pSome of the clients we work with have multiple relatively small, relatively similar sites. These sites sometimes require similar or identical changes. For these clients, I emmuch/em prefer to have a single VM that I can spin up to work on one or several of their sites at once. This makes it easier to switch between projects, and saves a great deal of disk space (the great disadvantage to using virtual machines is the amount of disk space they use, so putting several sites on a single VM can save a emlot/em of space)./p pAnd of course if we can have multiple sites per server, then we can also have a single site per server when that's appropriate./p h35. The VM must allow interaction via the command line/h3 pa href=https://chromatichq.com/blog/working-vim-never-leave-your-terminalI've written before/a about how I do most of my work in a terminal. When I need to interact with the VM, I want to emstay/em in the terminal, and not have to find or launch a specific app to do it./p h36. The VM must create drush aliases/h3 pThe single most common type of terminal command for me to issue to a VM is codedrush @alias {something}/code. And when running the command emon a separate server/em (the VM!), the command emmust/em be prefixed with an alias, so a VM that can create drush aliases (or help create them) is very, very useful (especially in the case where there are multiple sites on a single VM)./p h37. The VM must not be emtoo/em opinionated about the stack/h3 pGiven the variations in clients' production environments, I need to be able to use any current version of PHP, use Apache or Nginx, and vary the server OS itself./p h2My VM setup/h2 pHappily, it turns out that Drupal VM can not only satisfy all these requirements, but is either capable of all of them out of the box, or makes it very straightforward to incorporate the required functionality. Items 4, 5, 6, and 7, for example, are stock./p pBut before I get into the setup of items 1, 2, and 3, I should note that this is emnot/em the only way to do it./p pDrupal VM is a) a href=http://docs.drupalvm.com/extensively documented/a, and b) flexible enough to accommodate any of several very different workflows and project structures than what I'm going to describe here. If my configuration doesn't work with your workflow, or my workflow won't work with your configuration you can probably still use Drupal VM if you need or want a VM-based development solution./p pFor Drupal 8 especially, I would simply a href=https://github.com/drupal-composer/drupal-projectuse Composer to install Drupal/a, and a href=http://docs.drupalvm.com/en/latest/other/drupalvm-composer-dependency/install Drupal VM as a dependency/a./p pNote also that if you just need a quick Drupal box for more generic testing, you don't need to do emany/em of this, you can just a href=https://github.com/geerlingguy/drupal-vm#user-content-quick-start-guideget started immediately/a./p h3Structure/h3 pWe know that Drupal VM is based on Ansible and Vagrant, and that both of those tools rely on config files (YAML and ruby respectively). Furthermore, we know that Vagrant can a href=https://www.vagrantup.com/docs/synced-folders/index.htmlkeep folders on the host and guest systems in sync/a, so we also know that we'll be able to handle a href=https://github.com/ChromaticHQ/Blog-Posts/issues/60#mvw-1item 1 from my wishlist/a--that is, we can maintain separate repositories for the server and for projects./p pThis means we can have our development server as a standalone directory, and our project repositories in another. For example, we might set up the following directory structure where codeexample.com/code contains the project repository, and codedevserver/code contains the Drupal VM configuration./p precodeServers └── devserver/ Sites └── example.com/ /code/pre h4Configuration files/h4 pThanks to a href=https://github.com/geerlingguy/drupal-vm/issues/305#issuecomment-178141283some recent changes/a, Drupal VM can be configured with a href=http://docs.drupalvm.com/en/latest/other/overriding-configurations/#overriding-drupal-vms-defaultconfigyml-with-configymlan external /aa href=http://docs.drupalvm.com/en/latest/other/overriding-configurations/#overriding-drupal-vms-defaultconfigyml-with-configymlconfig.yml/aa href=http://docs.drupalvm.com/en/latest/other/overriding-configurations/#overriding-drupal-vms-defaultconfigyml-with-configyml file/a , a href=http://docs.drupalvm.com/en/latest/other/overriding-configurations/#overriding-variables-with-a-localconfigymla local config.yml file/a, and a href=http://docs.drupalvm.com/en/latest/other/overriding-configurations/#extending-the-vagrantfile-with-vagrantfilelocalan external /aa href=http://docs.drupalvm.com/en/latest/other/overriding-configurations/#extending-the-vagrantfile-with-vagrantfilelocalVagrantfile.local/aa href=http://docs.drupalvm.com/en/latest/other/overriding-configurations/#extending-the-vagrantfile-with-vagrantfilelocal file/a using a href=http://docs.drupalvm.com/en/latest/other/drupalvm-composer-dependency/#create-a-delegating-vagrantfilea delegating /aa href=http://docs.drupalvm.com/en/latest/other/drupalvm-composer-dependency/#create-a-delegating-vagrantfileVagrantfile/a./p pThe codeconfig.yml/code file is required in this setup, and can be used to override any or all of the default configuration in Drupal VM's own default.config.yml file./p pThe codeVagrantfile.local/code file is optional, but useful in case you need to alter Drupal VM's default Vagrant configuration./p pThe delegating codeVagrantfile/code is the key to tying together our main development server configuration and the Drupal VM submodule. It defines the directory where configuration files can be found, and loads the Drupal VM Vagrantfile./p pThis makes it possible to create the structure we need to satisfy a href=https://github.com/ChromaticHQ/Blog-Posts/issues/60#mvw-2item 2 from /aa href=https://github.com/ChromaticHQ/Blog-Posts/issues/60#mvw-2my/aa href=https://github.com/ChromaticHQ/Blog-Posts/issues/60#mvw-2 wishlist/a--that is, we can add Drupal VM as a git submodule to the dev server configuration:/p precodeServer/ ├── Configuration/ | ├── config.yml | └── Vagrantfile.local ├── Drupal VM/ └── Vagrantfile /code/pre h3Recreating the VM/h3 pOne motivation for all of this is to be able to recreate the ementire/em development environment quickly. As mentioned above, this might be because the VM has become corrupt in some way, because I want to work on the site on a different computer, or because I want to share the site—server and all—with a colleague./p pMostly, this is simple. To the extent that the entire VM (along with the project running inside it!) is version-controlled, I can just ask my colleague to check out the relevant repositories and (at most!) override the codevagrant_synced_folders/code option in a href=http://docs.drupalvm.com/en/latest/other/overriding-configurations/#overriding-variables-with-a-localconfigymla /aa href=http://docs.drupalvm.com/en/latest/other/overriding-configurations/#overriding-variables-with-a-localconfigymlcodelocal.config.yml/code/a with their own path to the project directory./p pIn checking out the server emrepository/em (i.e. we are not sharing an actual virtual disk image), my colleague will get the entire VM configuration including:/p ul liMachine settings,/li liServer OS,/li liDatabases,/li liDatabase users,/li liApache or Nginx vhosts,/li liPHP version,/li liphp.ini settings,/li liWhatever else we've configured, such as a href=http://docs.drupalvm.com/en/latest/extras/solr/SoLR/a, a href=http://docs.drupalvm.com/en/latest/extras/xdebug/Xdebug/a, a href=http://docs.drupalvm.com/en/latest/extras/varnish/Varnish/a, etc./li /ul pSo, with no custom work at all—even the delegating Vagrant file comes from the Drupal VM documentation—we have set up everything we need, with two exceptions:/p ol liEntries for code/etc/hosts/code file, and/li liDatabases!/li /ol pFor these two issues, we turn to the Vagrant plugin ecosystem./p h4code/etc/hosts/code entries/h4 pThe simplest way of resolving development addresses (such as e.g. example.dev) to the IP of the VM is to create entries in the host system's /etc/hosts file:/p precode192.168.99.99 example.dev /code/pre pManaging these entries, if you run many development servers, is tedious./p pFortunately, there's a plugin that manages these entries emautomatically/em, a href=https://github.com/cogitatio/vagrant-hostsupdaterVagrant Hostsupdater/a. Hostsupdater simply adds the relevant entries when the VM is created, and removes them again (configurably) when the VM is halted or destroyed./p h4Databases/h4 pImporting the database into the VM is usually a one-time operation, but since I'm trying to set up an easy process for working with multiple sites on one server, I sometimes need to do this multiple times — especially if I've destroyed the actual VM in order to save disk space etc./p pSimilarly, exporting the database isn't an everyday action, but again I sometimes need to do this multiple times and it can be useful to have a selection of recent database dumps./p pFor these reasons, I partially automated the process with the help of a Vagrant plugin. a href=https://github.com/emyl/vagrant-triggersVagrant Triggers/a is a Vagrant plugin that allows code to be executed …on the host or guest before and/or after Vagrant commands. I use this plugin to dump emall/em non-system databases on the VM on vagrant halt, delete any dump files over a certain age, and to import any databases that can be found in the dump location on the first vagrant up./p pNote that while I use these scripts for convenience, I don't rely on them to safeguard critical data./p pWith these files and a directory for database dumps to reside in, my basic server wrapper now looks like this:/p precodeServer/ ├── Vagrantfile ├── config/ ├── db_dump.sh ├── db_dumps/ ├── db_import.sh └── drupal-vm/ /code/pre h2My workflow/h2 h3New projects/h3 pAll of the items on my wishlist were intended to help me achieve a specific workflow when I needed to add a new development server, or move it to a different machine:/p ol liClone the project repo./li liClone the server repo./li liChange codeconfig.yml/code: ul liCreate/modify one or more vhosts./li liCreate/modify one or more databases./li liChange VM hostname./li liChange VM machine name./li liChange VM IP./li liCreate/modify one or more cron jobs./li /ul/li liAdd a database dump (if there is one) to the db_dumps directory./li liRun vagrant up./li /ol h3Sharing projects/h3 pIf I share a development server with a colleagues, they have a similar workflow to get it running:/p ol liClone the project repo./li liClone the server repo./li liCustomize codelocal.config.yml/code to override emmy/em settings: ul liChange VM hostname (in case of VM conflict)./li liChange VM machine name (in case of VM conflict)./li liChange VM IP (in case of VM conflict)./li liChange vagrant synced folders local path (if different from mine)./li /ul/li liAdd a database dump to the dumps directory./li liRun vagrant up./li /ol h3Winding down projects/h3 pWhen a project completes that either has no maintenance phase, or where I won't be involved in the ongoing maintenance, I like to remove the actual virtual disk that the VM is based on. This saves ≥10GB of hard drive space (!):/p precode$ vagrant destroy /code/pre pBut since a) every aspect of the server configuration is contained in codeconfig.yml/code and codeVagrantfile.local/code, emand/em b) since we have a way of automatically importing a database dump, resurrecting the development server is as simple as pulling down a new database and re-provisioning the VM:/p precode$ scp remotehost:/path/to/dump.sql.gz /path/to/Server/db_dumps/dump.sql.gz $ vagrant up /code/pre h2Try it yourself/h2 pSince I wanted to reuse this structure for each new VM I need to spin up, I created a href=https://github.com/ctorgalson/dvm-servera git repository containing the code/a. Download and test it--the README contains detailed setup instructions for getting the environment ready if you don't already use Vagrant./p

Miloš Bovan: Final code polishing of Mailhandler

Wed, 08/03/2016 - 17:54
span property=schema:nameFinal code polishing of Mailhandler/span div property=schema:text class=field field--name-body field--type-text-with-summary field--label-hidden field--itempemThis blog post summarizes week #11 of the a href=https://summerofcode.withgoogle.com/projects/#4520809229975552Google Summer of Code 2016 project - Mailhandler/a./em br /br / Time flies and it is already the last phase of this year’s Google Summer of Code 2016. The project is not over yet and I would like to update you on the progress I made last week. In the a href=http://blog.bovan.me/2016/07/gsoc-16-week-10-mailhandler-updateslast blog post/a I was writing about the problems I faced in week 10 and how we decided to do code refactoring instead of UI/UX work. The plan for the last week was to update Mailhandler with the newly introduced changes in Inmail as well as work on new user-interface related issues. Since this was the last week of issues work before doing the project documentation, I used the time to polish the code as much as possible./p p dir=ltrAs you may know, Inmail got new features on the default analyzer result. Since this change was suggested by Mailhandler, the idea was to remove Mailhandler specific analyzer result and use the default one instead. It allows the core module (and any other Inmail-based module) to use the standardized result across all enabled analyzers. The main benefit of this is to support better collaboration between analyzer plugins.br / Even though Mailhandler updates were not planned to take a lot of time, it turned to be opposite. Hopefully, the long patch passed all the tests and was fixed in a href=https://www.drupal.org/node/2776263Use DefaultAnalyzerResult instead of Mailhandler specific one/a issue.br / It was needed to not only replace the Mailhandler-specific analyzer result but to use user context and context concept in general as well. Each of the 5 Mailhandler analyzers were updated to “share” their result. Also, non-standard features of each of the analyzers are available as contexts. Later on, in the handler processing phase, handler plugins can access those contexts and extract the needed information./p p dir=ltrThe second part of the available work time was spent on user interface issues, mostly on improving Inmail. Mailhandler as a module is set of Inmail plugins and configuration files and in discussion with mentors, we agreed that improving the user interface of Inmail is actually an improvement to Mailhandler too.br / IMAP (Internet Message Access Protocol) as a standard message protocol is supported by Inmail. It is the main Inmail deliverer and UI/UX improvements were really needed there. In order to use it, valid credentials are requested. One of the DX validation patterns is to validate those credentials via a separate a href=https://www.drupal.org/node/2405045“Test connection” button/a.br /  /p figure role=group class=align-centerimg alt=IMAP test connection button data-entity-type=file data-entity-uuid=4f22d58c-86cc-4448-8bd1-6b52b067bc37 src=/sites/default/files/inline-images/imap_connect_button.png /figcaptionIMAP test connection button/figcaption/figurepIn the previous blog posts, I mentioned a power of a href=http://drupal.org/project/monitoringMonitoring/a module. It provides an overall monitoring of a Drupal website via nice UI. Since it is highly extensible, making Inmail support it would be a nice feature. Among the most important things to monitor was a quota of an IMAP plugin. This allows an administrator to see the health state of this plugin and to react timely. The relevant a href=https://www.drupal.org/node/2409923issue/a needs a few corrections, but it is close to be finished too.br /br / Seeing that some of the issues mentioned above are still in “Needs review” or “Needs work” state, I will spend additional time this week in order to finish them. The plan for the following week is to finish the remaining issues we started and focus on the module documentation. The module documentation consist of improving plugin documentation (similary to a href=https://api.drupal.orgapi.drupal.org/a), a href=https://www.drupal.org/sandbox/mbovan/2731473Drupal.org project page/a, adding a a href=https://github.com/fantastic91/mailhandler_d8Github/a read me, installation manuals, code comments, demo article updates and most likely everything related to describing the features of the module./p p /p p /p p /p/div span rel=schema:authorspan lang= about=/user/4 typeof=schema:Person property=schema:name datatype=Milos/span/span span property=schema:dateCreated content=2016-08-03T15:54:39+00:00Wed, 08/03/2016 - 17:54/span div class=field field--name-field-tags field--type-entity-reference field--label-above div class=field--labelTags/div div class=field__items div class=field--itema href=/taxonomy/term/1 property=schema:about hreflang=enGoogle Summer of Code/a/div div class=field--itema href=/taxonomy/term/2 property=schema:about hreflang=enDrupal/a/div div class=field--itema href=/taxonomy/term/3 property=schema:about hreflang=enOpen source/a/div div class=field--itema href=/taxonomy/term/4 property=schema:about hreflang=enDrupal Planet/a/div /div /div section rel=schema:comment h2Add new comment/h2 drupal-render-placeholder callback=comment.lazy_builders:renderForm arguments=0=nodeamp;1=11amp;2=commentamp;3=comment token=04b3e5a0/drupal-render-placeholder /section

OSTraining: How to Validate Field Submissions in Drupal

Wed, 08/03/2016 - 16:25
div class=ost-intro-imageimg src=https://www.ostraining.com/images/drupal8/field-validation.jpg alt=How to Validate Field Submissions in Drupal width=200 height=134 //div pAs OSTraining member asked us how to validate fields in Drupal 8./p pIn this particular example, they wanted to make sure that every entry in a text field was unique.nbsp;/p pFor this tutorial, you will need to download, install and enable the following modules./p

Drop Guard: 1..2..3 - continuous security! A business guide for companies individuals

Wed, 08/03/2016 - 15:00
div class=view-mode-rss ds-1col clearfix div class=field field--name-display-rss-image field--type-ds field--label-hidden field__itemimg src=http://www.drop-guard.net/blog/sites/default/files/styles/medium/public/2016-07/The%20Drupal%20Update%20Guide%20b.png?itok=NHJi6S0t/div div class=clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__itempA lot of Drupal community members, who are interested in or already use Drop Guard, were waiting for this ultimate guide on continuous security in Drupal. Using Drop Guard in a daily routine improved update workflows and increased the efficiency of the website support for all of our users. But there were still a lot of blind spots and unexplored capabilities such as using Drop Guard as an SLA catalyser. So we've stuck our heads together and figured out how to share this information with you in a professional and condensed way./p /div div class=field field--name-field-blog-post-tags field--type-entity-reference field--label-hidden field__items div class=field__itema href=/blog/taxonomy/term/2 hreflang=enDrupal/a/div div class=field__itema href=/blog/taxonomy/term/3 hreflang=enDrupal Planet/a/div div class=field__itema href=/blog/taxonomy/term/37 hreflang=enDrupal Community/a/div div class=field__itema href=/blog/taxonomy/term/5 hreflang=enSecurity/a/div div class=field__itema href=/blog/taxonomy/term/53 hreflang=enDrupal shops/a/div div class=field__itema href=/blog/taxonomy/term/13 hreflang=enBusiness/a/div /div /div

GVSO Blog: [GSoC 2016: Social API] Week 10: A Social Post implementer

Wed, 08/03/2016 - 07:42
span property=schema:name[GSoC 2016: Social API] Week 10: A Social Post implementer/span div property=schema:text class=field field--name-body field--type-text-with-summary field--label-hidden field--itempWeek 10 is over, and we are only two weeks away from Google Summer of Code final evaluation. During these ten weeks, we have been rebuilding social networking ecosystem in Drupal. Thus, we created the a href=https://www.drupal.org/project/social_apiSocial API/a project and divided it into three components: a href=https://www.drupal.org/project/social_authSocial Auth/a, a href=https://www.drupal.org/project/social_postSocial Post/a and a href=https://www.drupal.org/project/social_widgetsSocial Widgets/a./p/div span rel=schema:authorspan lang= about=/user/1 typeof=schema:Person property=schema:name datatype=gvso/span/span span property=schema:dateCreated content=2016-08-03T05:42:37+00:00Wed, 08/03/2016 - 01:42/span div class=field field--name-field-tags field--type-entity-reference field--label-above div class=field--labelTags/div div class=field__items span class=field--itema href=/tag/drupal property=schema:about hreflang=enDrupal/a/span span class=field--itema href=/tag/drupal-planet property=schema:about hreflang=enDrupal Planet/a/span span class=field--itema href=/tag/gsoc2016 property=schema:about hreflang=enGSoC 2016/a/span /div /div ul class=links inline list-inlineli class=node-readmorea href=/article/2016-08-03/gsoc-2016-social-api-week-10-social-post-implementer rel=tag title=[GSoC 2016: Social API] Week 10: A Social Post implementer hreflang=enRead morespan class=visually-hidden about [GSoC 2016: Social API] Week 10: A Social Post implementer/span/a/lili class=comment-forbiddena href=/user/login?destination=/article/2016-08-03/gsoc-2016-social-api-week-10-social-post-implementer%23comment-formLog in/a to post comments/li/ul

Galaxy: GSoC’ 16: Port Search Configuration module; coding week #10

Wed, 08/03/2016 - 00:47
div class=field field-name-field-image field-type-image field-label-hiddendiv class=field-itemsdiv class=field-item even rel=og:image rdfs:seeAlso resource=http://galaxy-joyceg.rhcloud.com/sites/default/files/styles/large/public/field/image/labelsAndStringOverrides.png?itok=6HJR1Uanimg typeof=foaf:Image class=img-responsive src=http://galaxy-joyceg.rhcloud.com/sites/default/files/styles/large/public/field/image/labelsAndStringOverrides.png?itok=6HJR1Uan width=462 height=406 alt=Switching the labels. //div/div/divdiv class=field field-name-body field-type-text-with-summary field-label-hiddendiv class=field-itemsdiv class=field-item even property=content:encodedp a href=https://groups.drupal.org/google-summer-codeGoogle Summer of Code 2016 /ais into its final lap. I have been porting the a href=https://www.drupal.org/project/search_configsearch configuration/a module to a href=https://www.drupal.org/8Drupal 8/a as part of this program and I am into the last stage, fixing some of the issues reported and improving the module port I have been doing for the past two months.br / Finally, I have set up my Drupal blog. I should have done it much more earlier. A quick advice to to those who are interested in creating a blog powered by Drupal and run it online, I made use of the a href=https://openshift.redhat.com/openshift/a to host my blog. It gives the freedom to run maximum of three applications for free. Select your favorite a href=https://www.drupal.org/project/project_themeDrupal theme/a and start blogging.br / So, now lets come back to my project status. If you would like to have a glance at my past activities on this port , please refer these a href=https://geojoyce.wordpress.com/category/gsoc-16/posts/a.br / Last week I was mainly concentrating on fixing some of the a href=https://www.drupal.org/project/issues/search_configissues/a reported in the module port. It was really a wonderful learning experience, creating new issues, getting reviewed the patches, updating the patches if required and finally the happiness of getting the patches committed into the Drupal core is a different feeling. Moreover, I could also get suggestions from other developers who are not directly part of my project which I find as the real blessing of being part of this wonderful community. /p pThe module is now shaping up well and is moving ahead in the right pace. Last week, I had faced some issues with the twig and I was resolving it. The module is currently a href=https://www.drupal.org/project/search_config/releases/8.x-1.x-devavailable/a for testing. I could work on some key aspects of the module in the past week. I worked on the namespace issues. Some of the functions were not working as intended due to the wrong usage of the a href=https://www.drupal.org/node/1353118PSR namespace/a. I could fix some of these issues. Basically, PSR namespaces helps to reuse certain standard functions of the Drupal API framework. They are accessed using the 'use' keyword. We can name the class locations using the namespace property.br / For instance, if I want to use the Html escape function for converting special characters to HTML format,br / use Drupal\Component\Utility\Html;br / Now, $role_option s= array_map('Html::escape', a href=https://api.drupal.org/api/drupal/core!modules!user!user.module/function/user_role_names/8.2.xuser_role_names()/a)br / Hope you got the idea. Here I could have written the entire route/path of thee escape function. But through the usage of the namespace, I just need to define the route at the beginning and later on it can be used for further implementations n number of times.br / The user_role_names() retrieved the names of the roles involved. This is an illustration of the usage of namespace. This is really an area to explore more. Please do read more on this, for better implementation of the Drupal concepts. /p pIn the coming days, I would like to test the various units of the module ported, fix the issues if any and bring up a secure, user friendly search configuration module for Drupal.br / Hope all the students are enjoying the process and exploring the Drupal concepts. Stay tuned for the future updates on this port process./p /div/div/divdiv class=field field-name-field-tags field-type-taxonomy-term-reference field-label-abovediv class=field-labelTags:nbsp;/divdiv class=field-itemsdiv class=field-item even rel=dc:subjecta href=/taxonomy/term/1 typeof=skos:Concept property=rdfs:label skos:prefLabel datatype=drupal-planet/a/div/div/div