Software
Drupalize.Me: Drupalize.Me Free Icon Package
Are you finding yourself searching for some new icons to use on your latest project? Drupalize.Me loves helping out the Drupal community, and people in general, so for this post I thought it would be fitting to provide you with a carefully designed free icon set.
Acquia: The Last-Ditch Fix - Programmatically changing a Drupal 7 view
Originally posted on Yellow Pencil's blog. Follow @kimbeaudin on Twitter
precessionmedia: How To Create A Custom Rules Action
This post should give a quick example on how to write the code to create your own custom actions for Drupals' Rules module. Writing your own plugins for rules (events, conditions or actions) can give you enormous benefits later, when you start to reuse them throughout the site or even port them on other Drupal sites.
We will be creating an action, which will provide a hashed string. In order to create this string we need to pass some parameters to php's hash function like a source string, a list with possible algorithms to choose and an output length. These parameters will be configurable through Rules' backend. So let's dive in.
First you need to create a basic custom module in your Drupal installation. The one I have in my custom environment is called "my_module".
You don't need anything special in your "my_module.info" or "my_module.module" files, but there has to be a file called "my_module.rules.inc", which will hold the code for your rules' action. Create it and add following code to it:
<?php /** * Implement hook_rules_action_info(). */ function my_module_rules_action_info() { return array( 'my_module_rules_action_create_hashed_string' => array( 'label' => t('Create hashed string'), 'group' => t('Custom'), 'parameter' => array( 'string' => array( 'type' => 'text', 'label' => t('String to be hashed'), 'description' => t('Enter a value for a string that will be hashed using the md5 hash-algorithm.'), ), 'length' => array( 'type' => 'integer', 'label' => t('The length of the returned string'), 'description' => t('Enter a number for the length of the hashed string that will be created.'), ), 'algorithm' => array( 'type' => 'text', 'label' => t('Algorithm'), 'description' => t('Select a hash algorithm.'), 'options list' => 'my_module_algorithm_options', 'restriction' => 'input', ), ), 'provides' => array( 'hashed_string' => array( 'type' => 'text', 'label' => t('Hashed string'), ), ), ), ); } // A helper function to provide us with a list of algorithms function my_module_algorithm_options() { $bundles = array(); $bundles['md4'] = t('md4'); $bundles['md5'] = t('md5'); return $bundles; } // This callback creates the hashed string by using the parameters provided through rules' UI function my_module_rules_action_create_hashed_string($string, $length, $algorithm) { if ($length <= 0) { // For anything below or equal zero lets return the default value. $string = hash('md5', $string); } else { $string = substr(hash($algorithm, $string), 0, $length); } return array( 'hashed_string' => $string, ); }Here we implement initially "hook_rules_action_info" and add our own action to it. Our action is an associative array keyed with the name of the callback that will return our value (in this case a hashed string). Inside it we give our action a label and put it in a group ("Custom"). The next part of this array is an associative array itself, keyed with "parameter". Inside it we describe our 3 parameters, which will be passed to the action callback. Note that the "algorithm" parameter has an entry with the key "options list" which points to a helper function ("my_module_algorithm_options") to keep the code more lean.
The last part of the array is another associative array keyed with "provides". This key tells Rules what the machine name of the provided variable is, among with giving it some additional data like type or label. You can use this provided variable in latter actions of your rule now!
The last part of the code is the action callback. Only thing to note here is that we return the whole string returned by the hash-function, when the value of $length is below or equal to 0.
Clear your cache in order for Drupal to register the code you added and the new action should appear now:
In order to see it's working I've added a "Show a message on the site"-action which shows the provided hashed string when we're looking at a node page:
That's it with this simple example! Please leave a comment if there is anything more that comes to mind. Thanks!
By dimitar on 05.08.2014
Share this:Janez Urevc: Progress of Entity embed module in GSoC 2014
If you want to try the module and/or contribute please visit the project page. You are also invited to check original post on groups.drupal.org.
Cheppers blog: 7 +1 steps to plan a successful Drupal website
According to our experience the most usual approach for clients with web development needs is to contact multiple agencies with more or less vague ideas - asking for quotes, and then selecting a choice based on price. This approach is doomed to fail for two reasons:
- Without a precise specification of requirements, agencies will have to base their quotes entirely on guesses.
- The client is missing out on the value that the agency could have added if they were involved in the discovery and planning as well.
Károly Négyesi: Drupal 8 progress from my / MongoDB perspective: update #28
The standard mechanism for backend-aware service overrides is in and these services are already tagged. We have agreed on how to transfer data from one backend to another and my sandbox contains the first getTransferIterator implementation for config with more to follow. There's a small amendment in the works that makes the old backend available too.
More field renames are in the works. That's why I am not focusing on the MongoDB drivers just yet. Let's wait for beta. The drivers in a state where we can do some meaningful testing (which lead to making sure tests are modifiable before) and so we can make sure everything will work for us but writing the entity drivers themselves at this point is a waste of time -- let's wait for a (more) stable API. The transfer work started because MongoDB needed to solve taking over config storage and while we had it solved, there is really nothing MongoDB specific so I am pushing for core inclusion.
I didn't mention config devel in this series -- although I did previously on this blog -- I firmly believe this will be used widely and lead to a more joyous CMI experience. Reminder: everyone using CMI is what makes the Drupal on MongoDB only feasible in the first place.
Drupal core announcements: Drupal Core Updates for Aug 4, 2014
It's been an exciting two weeks as Twig Autoescaping was turned on by default, the menu links system was completely revamped, entity caching was finally added to core, and we switched Drupal 8 version numbers to Semantic Versioning!
The switch to semantic versioning means that if you have a clone of Drupal 8 core, you shouldn't patch the 8.x branch anymore: use 8.0.x instead. To switch branches, simply run git fetch origin && git checkout -t origin/8.0.x. See jhodgdon's announcement to the Core group for more information.
The valiant efforts of the 15-person team at the Drupal 8 Code Sprint at the Jersey Shore saw 30 issues move forward, 12 of which have already been committed. For more information, read this recap of the event by Kalpana Goel of Forum One.
Finally, thank you to all the contributors who helped us fix 378 Drupal 8 issues in July, 101 more than in June! The fast turnaround in the RTBC queue from our awesome core maintainers has been really motivating — as of right now the RTBC queue is totally empty, meaning that every RTBC issue has either received committer feedback or been committed. (Also noteworthy, Alex Pott of Chapter Three committed a remarkable 70% of July's many commits. Wow!)
Where's Drupal 8 at in terms of release?In the past week, we've fixed 9 critical issues and 22 major issues, and opened 4 criticals and 35 majors. That puts us overall at 104 release-blocking critical issues and 656 major issues.
Only 3 of 173 beta blockers remain before we can release a Drupal 8 beta. Drupal 8will soon be in beta, so now is the time to take a close look at the remaining critical issues and beta deadline issues. In each issue, help clarify:
- If it's critical or major, why?
- What would be the implications of not fixing the issue?
- What would be the implications of fixing the issue between betas? (Code changed for modules, upgrade path, etc.)
- What would be the implications of fixing the issue after the first release candidate?
- What is the next step to make progress? What are the remaining tasks?
Each week, we check with core maintainers and contributors for the "extra critical" criticals that are blocking other work. These issues are often tough problems with a long history. If you're familiar with the problem-space of one of these issues and have the time to dig in, help drive it forward by reviewing, improving, and testing its patch, and by making sure the issue's summary is up to date and any API changes are documented with a draft change record, we could use your help!
- Issue #1934152: Figure out if we want global config overrides to stick (settings.php overrides don't work on all pages) aims to determine if it would be more secure/sane to apply global configuration overrides hard-coded into settings.php even when they wouldn't normally (for example, when editing/previewing a the configuration of a view in the Views UI, where request/URL don't apply because they're intended for the edit page, not the view itself), or whether it would be better to provide a 2-tiered override system (one for global overrides and one for "soft" request/URL overrides).
- Issue #2313159: [meta] Make multilingual views work is a collection of problems related to making multi-lingual views in Drupal 8. A number of the sub-issues are "Major", meaning they have significant repercussions but do not render the whole system unusable.
- Issue #2189661: Replace $form_state['redirect_route'] with setRedirect() aims to make the Form API more consistent with the rest of core, but the patch is out-of-date and needs to be re-rolled.
- Pick a critical issue or beta deadline issue, take the time to thoroughly read the issue (including doing some background reading if necessary to understand the problem space), and then update the issue summary for the issue. Include a summary of the current status and remaining tasks for the issue, and identify any API changes the issue would introduce. Consider whether the change would require a change record or updates to existing change records. Consider what the implications of not resolving the issue would be, or of resolving it after the first beta or after release.
- We also need help writing help text for core modules like Entity, Contextual Links, Field UI, Image, Taxonomy and Toolbar. This is an easy way to learn the Drupal Core contribution process and start contributing to Drupal Core.
- Help brainstorm how to improve core's Contact module for Drupal 8.1 and beyond.
As always, if you're new to contributing to core, check out Core contribution mentoring hours. Twice per week, you can log into IRC and helpful Drupal core mentors will get you set up with answers to any of your questions, plus provide some useful issues to work on.
You can also help by sponsoring Drupal core development.
Notable CommitsThe best of git log --since "2014-07-16" --pretty=oneline (180 commits in total):
- Issue 1825952 by Fabianx, joelpittet, bdragon, heddn, chx, xjm, pwolanin, mikey_p, ti2m, bfr, dags, cilefen, scor, mgifford: Turn on twig autoescape by default
Now, every string printed from a twig template (i.e.: between {{ and }}) is automatically run through String::checkPlain(). This makes it hard for themers and module developers to accidentally introduce XSS attack vectors in their code, which is a big win for security.
If you notice a double-escaping issue, please update Issue #2297711: [meta] Fix double-escaping due to Twig autoescape.
A follow-up issue was also committed: Issue #2289999 by dawehner, Cottser | Fabianx: Add an easy way to create HTML on the fly without having to create a theme function / template.. This makes it easier to generate tiny chunks of HTML where full Twig files would not be useful. - Issue 2256521 by pwolanin, dawehner, Wim Leers, effulgentsia, joelpittet, larowlan, xjm, YesCT, kgoel, victoru, berdir, likin, plach, alexpott: [META] New plan, Phase 2: Implement menu links as plugins, including static admin links and views, and custom links with menu_link_content entity, all managed via menu_ui module.
This critical beta-blocker completely revamped the menu link system on the back-end (the UI for managing menus and menu links remains largely the same). It added a common interface for menu links, to hide implementation details and let different storage methods work together in the same menu tree, condensed the crufty, confusing code that loads and renders menu trees down to just three methods, decoupled breadcrumbs and menu links, and broke down the code into multiple services to allow different behavior to be customized with a minimal amount of code. - Issue 597236 by Berdir, catch, msonnabaum, Xano, Wim Leers, jhedstrom, amateescu, corvus_ch, swentel, moshe weitzman, Gábor Hojtsy, riccardoR, killes@www.drop.org, et al: Add entity caching to core.
This issue, which has been around in various forms for about 10 years, increases overall peformance by caching entities so they don't have to be rebuilt every page request. Initial performance testing showed a performance increase of about 15%, although this varies based on the number of loaded entities. - Issue 1986418 by tompagabor, LewisNyman, idflood, jamesquinton, lauriii, emma.maria, danmuzyka, rteijeiro, scronide, frankbaele, Coornail, ekl1773, oresh, philipz | Bojhan: Update textfield & textarea style.
- Issue 733054 by jhodgdon, mkalkbrenner, amitgoyal, ndewhurst: Fixed Watchdog logging of all searches is performance hit; need ability to turn it off.
- Issue 1288442 by jhodgdon | Wolfflow: Added search index status to the Status Report page.
- Issue 2062043 by eelkeblok, longwave, rhm50, InternetDevels, alvar0hurtad0, Xano: Replace user_access() calls with $account->hasPermission() in core files.
- Issue 2293773 by Gábor Hojtsy, alexpott, effulgentsia, penyaskito, hussainweb: Fixed Field allowed values use dots in key names - not allowed in config.
- Issue 2247049 by sqndr, herom, LewisNyman: Redesign password strength indicator so it's less fragile.
- Issue 2225353 by tim.plunkett: Convert $form_state to an object and provide methods like setError().
You can also always check the Change records for Drupal core for the full list of Drupal 8 API changes from Drupal 7.
Drupal 8 Around the InterwebsIf you want to keep up with the changes in Drupal 8, but you'd rather absorb yourself in articles than dig through diffs, here are some notable blog posts to read:
- Lizzie Hodgson explains user personas, why they're important, and how Deeson Online's content strategists came up with and contributed personas to the Drupal 8 landing page on Drupal.org based on Dries' keynote in Prague.
- Virginia Durikova of Mogdesign discusses the importance of the #d8rules Drupalfund project and analyzes why it was so successful.
- Kim Pepper of PreviousNext wrote a tutorial on how to use Drupal 8 Condition Plugins API.
- Thomas Seidl wrote a tutorial on how to create your own Drupal 8 service.
- Keenan Holloway of Forum One shares a presentation on how to get set up for Drupal 8 development.
- Pedro Rocha of SingleView blogged about his experience using the popular Bootstrap framework to theme a Drupal 8 site.
- Kyle Hofmeyer of Drupalize.Me lists some Drupal 7 modules that provide Drupal 8 features.
- Alex Pott of Chapter Three writes about reviewing Drupal 8 patches with PHPStorm.
August will have many events for you to meet other Drupal contributors and collaborate on the issues you're passionate about! Some notable ones are:
- Aug 7-10: Twin Cities DrupalCamp in Minnesota, USA will have a sprint room for all four days and has a sprint sign-up. @TCDrupal
- Aug 7-10: Drupalaton at Lake Balaton, Hungary has Drupal 8 sessions and sprints. @drupalaton
- Aug 9: Vacation Code Sprint in Wrocław, Poland will be meeting to work together on Drupal 8 at the RatioWeb offices.
- Aug 16-17: Drupal Sprint Weekend in London, England will have new-contributor, core and contrib sprints.
- Aug 22: DrupalGov in Canberra, Australia features everything relating to Drupal and the Australian Government, including Drupal 8 sessions.
- Aug 23: Drupal 8 core sprint in Helsinki, Finland will focus on Drupal.fi and Drupal 8 Core.
Do you follow Drupal Planet with devotion, or keep a close eye on the Drupal event calendar, or git pull origin 8.0.x every morning without fail before your coffee? We're looking for more contributors to help compile these posts. You could either take a few hours once every six weeks or so to put together a whole post, or help with one section more regularly. Contact xjm if you'd like to help communicate all the interesting happenings in Drupal 8!
Friendly Machine: Headless Drupal? It Just Might Be a Bigger Deal than Twig
If you're a frontend developer or designer that has grumbled about the challenges of Drupal theming, you no doubt applauded the announcement that the Twig template framework was being added to Drupal 8.
It's a big upgrade, no question. If you're like me, however, you may prefer a completely custom frontend crafted out of HTML, CSS and JavaScript. You may have looked at the cool stuff AngularJS or Backbone is capable of and wondered how you could bridge the gap with Drupal to enjoy that sort of freedom.
Fortunately, there are some folks that are already doing exactly that and sharing the results of their work. It's something called "headless Drupal" and it's an approach that uses Drupal as a backend content repository and REST server.
A REST server makes it possible for other applications to read and update data. The typical case is that Drupal is used to store and manage content and it then provides that data to your app built with Angular, Backbone, Ember, or whatever. If that's not entirely clear, don't worry. The links below will help sort it out.
Headless Drupal ResourcesHeadless Drupal Manifesto - This is great place to start. It succinctly answers the question of why anyone would want to do this sort of thing.
Headless Drupal Group - A group on Drupal.org devoted to sharing ideas, discussion and experiments around the topic of headless Drupal.
Build a Drupal-free theme with 8's REST API and JavaScript - A presentation from DrupalCon Austin on building an AngularJS site that uses Drupal for the backend.
Headless Drupal, One form at a time - This is a great post from Amitai Burstein that demonstrates some of what this approach has to offer for the creation of frontend user interfaces.
Headless Drupal - Inline edit - Another good one from Amitai.
Here’s Drupal - Tonight on the Tonight Show with Jimmy Fallon - A case study of headless Drupal in action on a very high profile site.
If you know of some other resources, please share them in the comments below. I'd love to check them out.
Nikro: Moldcamp 2014 - a late review
I know, it's been a while since the event took place (17th-18th of May), I was pretty busy and had a lot of stuff to do meanwhile, so I finally found a couple of hours to make a small review.
Tags:Microserve: Coding in the Cloud
An old timer like myself couldn't help but be filled with trepidation when it was revealed I'd be acting as the company guinea pig to give cloud based development a viability road test on my latest project.
No matter how cool I played it, the momentary panic at the thought of working without the tried and tested 'REAL' software apps installed on my macbook, must have been visible on my face.
You'll have to pry my favourite text editor out of my cold dead hands!I've been used to the same comfy workflow for the last few years.
A local environment comprising of the same trusty text editor/IDE, a LAMP stack running on MAMP and code versioning using GIT. There was just something about 'cloud based coding' that didn't seem to ring true.
Pause For ThoughtThen when i really thought about it, I began to examine just how much of my professional and personal life had already drifted into the cloud and in most cases for the better.
Thanks to Google, Dropbox and Apple amongst others, my email, calendars, notepads, files, photos, videos and documents have for the most part been in the cloud for ages. Do I miss opening up MS Word to write a letter? No.
Then I thought about how much easier life as a Drupal developer had become since adopting tools like Drush, Git and more recently, the Pantheon platform. (in essence 'cloud' based tools themselves.) So, thinking about it, cutting the last few remaining ties to local, machine specific workflow seemed less of an imposition and more like the next natural step in the evolution of web development.
Where to start?After a bit of googling 'cloud based IDE', you'll see there's already quite a few choices. Most seem to follow a similar basic subscription paradigm (one or a number of free public projects and a paid for plan for private/production projects.)
In most cases they provide a fully functioning text/code editor with text highlighting support, basic options for uploading, renaming and deleting files, a cloud based LAMP stack, some kind of terminal or command line and a selection of optional 'plugin' tools.
RoadtestI've been testing Codio: https://codio.com/
The site I've been working on is a Drupal 7 site that arrived with us, half built.
Codio handled the import of the existing database and files without much hassle and pulled in the code base via Git.
I was able to install drush as a Codio ‘part' (plugin) and was installing essential modules via Codio's command line terminal in no time.
There's a nice file tree in the left pane and the editor itself is a real pleasure to use.
I was impressed to find text highlighting support for SASS/LESS out of the box and it had decent poke at autocomplete of attributes.
There's a handy tab in the main menu which opens your project 'box' in a new tab or window and on a decent sized screen, it's pretty easy to get a nice comfortable layout with your code in one window and the running site in another.
One of the best things about Codio is that all changes to code are instant, with no saving or incremental Git commits needed. You only need to refresh your site to see it update.
Once you've done a tranche of work you're happy with, you can commit as you normally would, either using the in-built terminal or the GUI menus.
ConclusionBy the end of day one I had been totally sold. The feeling of freedom was, well.. liberating. The next day I had to set up a new mac to use at work, and usually this process eats up half a day of downloading latest versions of software, configuring, chasing licences etc. In this case I literally just turned on the new laptop, installed my browser of choice, logged into Codio and I was away!
Of course, with everything, there are some niggles. The most obvious downside to cloud based development is, that when your connection is spotty or you suffer an outage, you're immediately incapacitated. A few days in and the Codio servers themselves had a few hours of intermediate drop outs. You can imagine how frustrating this might be if you were riding up close to a deadline.
But on the whole the good far outweighed the bad and I'm sure that service and reliability is only going to improve as web based coding becomes the norm... Which i'm now convinced it will before too long.
Pros and Cons of Web Based Development Pros- Code anywhere that has a connection
- Collaborate more easily with other developers
- No local apps needed other than a browser
- Platform agnostic (Makes things like Chromebooks slightly more viable as a stripped down development machine)
- Less chance of incompatible files being shared between collaborators
- Fewer problems for code team Sysadmins.
- Reliant on reliable internet connection and host server
- Basic file, folder housekeeping can be a bit laborious.
*I should point out that my experiences are with Codio IDE, but there are many other alternatives available. Cloud 9 seems to be proving very popular for instance.
You can find a rundown of some of the most popular here:
http://www.hongkiat.com/blog/cloud-ide-developers/
Drupal core announcements: Fixing double-escape bugs
Since Twig autoescape is on, there are double escape bugs. If you can fix them by refactoring code into Twig templates, that's great. If not then wait for an easy way to create HTML on the fly without having to create a theme function / template. It's already RTBC, it's a matter of days to find its way in. Regarding SafeMarkup::set calls, there is an issue to refactor and remove the ones we needed to add to get tests pass and so adding more is not acceptable (the reason for writing this announcement are the quick fix issues I need to whack trying to fix double escape by adding more of these).
Károly Négyesi: OOP developer experience: snap to grid
After writing my first Drupal 8 contrib module I have a new appreciation. Let me try to explain. It is certainly possible to write a letter on an empty sheet of paper but achieving tidy results is quite a lot easier if it's a lined sheet. In Drupal 7, the code flow in general is calling a function, getting an array, manipulating the array and passing it to another function. Pretty much anything goes. In Drupal 8, you are handed an object and the object has methods. Instead of trying to figure out which possible function are you continuing with, it is one of the methods. When passing on data, the receiving method (hopefully) has a helpful type hint which tells you what to pass in. Often even the argument name will be helpful too.
It's exactly like having a lined paper: you still need to know how to produce legible handwriting but at least you have a guide. Another apt metaphor is lining up shapes in a drawing program. Yes, it's possible by hand and there's more freedom doing it but for most it's easier to just use the snap to grid feature.
This blog post was inspired by ConfigDevelAutoImportSubscriber having a $this->configManager object. That I need a config manager I have copied from a core file doing similar things. So, I wanted to create an entity -- I already know doing that requires calling the create method of the relevant storage controller. But how do you get one? Well, ConfigManagerInterface only has 10 methods and only 1 looks even remotely relevant: getEntityManager. So now I have a EntityManagerInterface object. Look, a getStorage method.
<?php
$entity_type_id = $this->configManager->getEntityTypeIdByName($config_name);
$entity_storage = $this->configManager->getEntityManager()->getStorage($entity_type_id);
$entity = $entity_storage->create($data);
?>
We could call this "autocomplete driven development" cos the autocomplete in your IDE pretty much drives you forward. Oh yeah: trying to develope D8 without an IDE is not something I'd recommend.
cs_shadow: Entity Embed module demo
Midterm evaluations for GSoC are over and I've released a short demo for the entity embed module: Introducing Entity Embed module for Drupal 8. This screencast explains the basic idea behind the module and its usage.
It's also time for the status update of what I've been doing for past couple of weeks. Apart from making the demo, a significant amount of work has been done since my last blog post. Some important issues that were solved over past couple of weeks include a much better test coverage, adding a preview of entity in CKEditor, adding support for alignment of embeds, and some code cleanup. Also, travis-ci is now enabled for the github repo so it has become far much easier to run tests on new pull requests and commits.
Check out the video and if you have any issues, feel free to open a ticket on the entity embed issue queue on d.o or contact me directly.
Cruiskeen Consulting: The Joys of Configuration!
At the moment we're working on a fairly BIG Drupal 6-Drupal 7 migration for the Twin Cities Daily Planet.
As part of that I am attempting to get the rather unwieldy site completely under code and configuration management. The code part is well understood (well, at least by others) and semi working for us, so I'm not going to talk about the issues of getting sites under control of git - lots of others have written about that. I am going to talk about the configuration management part.
I have always been more than a little disheartened by the use of Features to control all those icky parts of the site that are held in the database rather than code. For one thing, that's not really what Features was intended to do - it was intended to pile up a single hunk of site functionality and turn it into a feature. This I can dig, but from a general site administration viewpoint it is a pretty awkward tool. So I was really excited to realize that this whole configuration issue is being seriously worked on in Drupal 8, and that all of those messy things in the database will now get written out into flat config files that can actually be code managed. I was even MORE excited to see a few months back that there is now a configuration module for Drupal 7. This looked to me like it was exactly what the Doctor. ordered. But as often happens, the drug seems to have some side effects.
Drupal core announcements: Drupal core security release window on Wednesday, August 6 (NOTE: Change from normal schedule)
The monthly security release window for Drupal 6 and Drupal 7 core will take place on Wednesday, August 6.
Take note of the change in schedule! The security release window is normally the third Wednesday of the month, but we are moving it up for this month only to better coordinate various schedules. Apologies for any inconvenience this change might cause.
This does not mean that a Drupal core security release will necessarily take place on that date for either the Drupal 6 or Drupal 7 branches, only that you should prepare to look out for one (and be ready to update your Drupal sites in the event that the Drupal security team decides to make a release).
Due to the change in schedule and the fact that the Drupal 7.30 bug fix release was just a week ago, there will be no bug fix release in August; the next window for a Drupal core bug fix release is Wednesday, September 3.
For more information on Drupal core release windows, see the documentation on release timing and security releases, and the discussion that led to this policy being implemented.
Greater Los Angeles Drupal (GLAD): Pantheon Development and Drupal upgrades
I have been developing migrations for a new site on Pantheon. The work flow is pretty easy. You clone the environment, make your changes on your local machine then push to the dev site. This allows you to install modules, change the configurations and then push this to Pantheon just using Git.
There are a few gotchas like installing and enabling modules. When you install a module it does this in code so just adding the folder into the git repository will install the module on Pantheon, but enabling the module is in the database. Unless you do something like have a feature for installing modules you can end up with something different on Pantheon. No big issue it is easy to enable a module and all is right with the world again. This also means you learn quickly the value of the features module, if there is something in the database you want to synchronize you need to create a feature. Things like content types, views etc.
Another big gotcha hit me last week. Pantheon warns you all over their the place not to upgrade Drupal with Drush. I did not update the Pantheon site with Drush but I headed the warnings on my local environment and updated my local environment with Drush. Then later when Pantheon was on the same version I merged and pushed this back to Pantheon. Admittedly I took some steps to merge that I did not understand, but after I did this push I pushed it to the test environment as well. Trouble is when I went to the dev or test site all I saw was a screen waiting to install Drupal, and there was a warning stating that I had upgraded incorrectly and had to fix this. Unfortunately the steps they gave did not resolve the situation (probably due to my ignorance). Now I have a broken Pantheon site, and my backup was 30 days old.
Turns out the fix was pretty easy, but sounded complex. I restored the dev environment from backup. Now it worked but was out of date. I pulled to my local environment, this worked, and status stated that I was 70 commits ahead of head. I looked through the log and found the last commit before I broke things. I committed this and pushed. My dev environment was working on Pantheon with my latest code. Pushed this to the test environment and it was now working.
After a great deal of worrying and hand wringing the solution was easy. GIT is great!
Lessons learned:
- When working in a Pantheon environment do not use drush to update Drupal, even on your local environment.
- Make backups often, you never know when you can use it.
tsvenson: I am a Follower & Thinker
Lets start with a question - How often do you ask yourself:
- How on earth did they think there/then?
...then set off spending quite a bit of time trying to reverse engineer it somehow!
I still do it all the time, more than once a day usually. Particularly when stumbling on new things, such as when hearing news about how bad state our world is in, or when watching a lecture or talk about an interesting topic.
To simplify, the big question for me ended something like this:
- Do I want to feel needed just because I can follow someone else's instructions, no matter how stupid they sounded - Or because I can process information, think and use the new knowledge to make something better with?
For me it was, in the end, a simple choice!
Followers & LeadersIn society we are often told there are either followers or leaders. To a large degree that have worked really well. Just look at the technology progress made since electricity was invented. However, leaders are often also rulers. While there are good leaders, there is sadly also too many who are not so good. Those who demand us to follow their instructions without asking questions.
A leader also need a dominion to rule over. Traditionally that has been an area, most often in the form of a guarder piece of our planet with borders we have to pass through.
Today things are different, we have a global network called the Internet which we use to communicate with each others in various ways. This has, in my book, turned everything upside down. No longer do we need to wait for filtered information (the state and media) to select and tailor-make the information we are allowed to see.
- Never before in history have we as citizens been able to check things for ourselves. Contact nearly anybody almost anywhere in the world and just ask!
It doesn't stop there. Today we have gone bye by just asking questions and hoping for an answer. Today we collaborate freely over the internet, we do things together no traditional borders can ever stop us from again.
Still, the old leaders don't want to give up their power. They have tried to regain their powers through the backdoor with schemes such as SOPA, PIPA and ACTA. Then, thanks to the courage of Edward Snowden we have learned how the NSA is trespassing on our human rights to privacy and trust. They claim they do it to fight terrorism, but has thus far failed badly proving even the slighted success! Instead we have learned that the government, the US government, who has given them the means, in reality have little clue to the extent they have taken it.
Or does it know?
The Open Source movement shows a new way forwardFor the last six years I have had the pleasure of being part of the Drupal community. I know now that I have not been the nicest player there, but during the last half year it has really sinked in for me.
In open source there are few traditional leaders. Instead it is filled with passionate individuals who come together to solve problems together. Sure, debates are often heated and sometimes unsolvable. But hey, that's just life and Open Source has actually a fine working solution for that to.
- If you are not happy with the direction, then just fork the project and go on in your own direction!
No one can stop you and few will. Sure, there will be discussions but they are usually done in the open and everyone has the opportunity to give their own arguments about it. This is, actually, also an effective way to keep traditional leaders at bay as the open source leaders gets their powers from the way they lead, the way they inspire others to want to be part of something good!
In my experience, few open source leaders have needs that match traditional ones. They just want to get on with it, build something better that everyone have access to use.
In fact, most of the internet is built on Open Source. Especially 20+ years ago when few saw it's potential. That is something we should be very grateful for today. Just imagine how bad it would have been if they back then had been as eager to protect their ideas as the smartphone manufactures are today. Ideas that they themselves in many cases got the inspiration to from others.
On thing is sure, it would have looked nothing like the internet we have today - An internet worth fighting for!
Only way is up!I'm currently living on welfare in Sweden. It is the only thing that separates me from being homeless. My path down has been quite an slippery slope. There where times I thought I had cracked it and life was better. At least for a while until it began to go, even further, south again. It was always the same thing:
- I never managed to fit in with society, or even smaller groups, and in the end it got me running somewhere else!
Basically after a while I gradually felt more trapped, that life began to go in repeated circles and there where less and less things around to get inspired and/or motivated about.
That has finally changed and for the first time ever I am actually looking forward with a feeling I have something to share. The growing feeling of being needed is making me jump out of bed, ready to take on whatever will happens with excitement.
Somehow the majority of everything I have been through survived - At least it seems it got locked down somewhere in the back of my mind. But it isn't until now, at the age of 46, I have found a way to process it all, understand its meaning and finally feel I am really starting contributing back to the world in a meaningful way.
Followers & ThinkersMy proposal:
- Follow what, including people, inspires your curiosity.
- Listen to what they have to say, how they say it and the passion you can feel from how they express it.
- Then also think about how that fits with your own reality, how it help explain things.
That's pretty much what I do now, plus trying to figure out how to do it better together with others!
Here are a one inspiring person in my life: Elon Musk
I watched this recording of a conversation Elon had with Khan Academy. I had admired him for quite some time for what he has acomplished especially with Tesla Motors and the pure *madness* with SpaceX. I had no idea what I was about to experience, but I am glad I did.
For me, this became a guided tour of Elon's brain and the way he thinks - His thought process. Never before had I come to understand the world, the universe like that before. For the first time I begun to understand the concept of time and space!
I was hooked!
Since that day, February 4th, the world around me has at an accelerating pace started to change. The roller-coaster between *heaven* and *hell* I once was having has changed! Today the world is a beautiful thing, something presious we all share.
But the best thing I have learned is this:
- We are slowly beginning to understand!
#PowertoCreate made it all come together for me. Therefore I can't think of anything better than let Matthew Taylor, Chief executive of the RSA tell you in his own words.
drunken monkey: Updating the Search API to D8 – Part 4: Creating plugin types
The new plugin system is another large and important change in Drupal 8. While you were pretty much on your own if you wanted to provide some kind of plugin system in Drupal 7 (which a lot of modules do – think Views, Rules, etc.) there is now a very sophisticated framework to easily implement plugins and to define your own plugin types in a clean, extensible and very flexible way. And the good news for everyone familiar (code-wise) with the Search API in Drupal 7: the system is very much in line with how Search API implemented plugins itself, so the switch is pretty easy for us.
What is a plugin?There have already been a lot of great blog posts about the plugin system in Drupal 8, so I won't go into much detail here. Generally speaking, a plugin is a self-contained unit providing a certain, well-defined functionality. A plugin type is defined by a single, central system (which is usually also the only place where the plugins are used), but other modules can then provide their own plugins with an individual implementation of that functionality.
Probably not a very helpful explanation, it's not that easy to explain – but, to use an example, blocks are now plugins in Drupal 8. The Block module provides the "Block" plugin type, which defines how blocks can be displayed on a page and how they can be configured. The Block module also provides all the code utilizing those plugins, letting the user place blocks on the site, ensuring they are displayed when and where appropriate, etc. Other modules then provide implementations of that "Block" plugin type – i.e., individual plugins – that implement different kinds of blocks: the User module provides a block with the login form, the Language module the "Language switcher" block, the Book module a block displaying the current book's navigation, etc.
But there are literally dozens of other types of plugins already included in Drupal core, and contrib is bound to add countless more – four (currently) by the Search API, for example. Entity types, the various Views handlers (fields, filters, sorts, …) and plugins (display, row, …), field types, WYSIWYG editors – all of those are now just different types of plugins, all using one new, large, unified framework to provide their functionality.
So, what do we need to add our own plugin type to that growing list? Well, basically just a plugin manager, which (as explained last time) is a special type of service – that's it. Your new plugin type becomes available by just implementing a single method. Of course, to make your plugin type more useful and easier to use for others, you should add a few more things: an interface describing what plugins of that type should be able to do, an abstract base class for implementing that interface (unless it doesn't make sense in your case) and (optionally) a dedicated annotation for your plugin type.
Let's go through those with the example of Search API processors.
The plugin managerAs mentioned earlier, the plugin manager is simply a special kind of service. There is a base class (DefaultPluginManager) which already takes care of 95% of what's needed, you literally only need to override the constructor. So, we save the following in search_api/src/Processor/ProcessorPluginManager.php:
<?phpclass ProcessorPluginManager extends DefaultPluginManager {
public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler) {
parent::__construct('Plugin/search_api/processor', $namespaces, $module_handler, 'Drupal\search_api\Annotation\SearchApiProcessor');
$this->setCacheBackend($cache_backend, 'search_api_processors');
$this->alterInfo('search_api_processor_info');
}
}
?>
(To save space, I skip the namespace, imports and comments for all examples.)
This can be used as kind of a template, the base class will then take care of everything that's necessary to make the plugin system work. Here's what each of the lines do:
- The __construct() method signature contains the service's dependencies, which will be injected when the plugin manager is constructed. $namespaces basically contains all root folders for sub-namespaces – i.e., every module's src/ and/or lib/ directory, plus a few more. The others are the services that handle caching and module interaction (e.g., invoking hooks).
- The parent constructor sets the plugin manager up for this specific plugin type. The two variables are of course just passed on as-is, the other two parameters represent the following:
- Plugin/search_api/processor is the sub-dir (and therefore sub-namespace) in which plugins of this type have to be located for automatic detection. That means, e.g., if the Views module would want to provide a Search API processor, it would have to be in namespace \Drupal\views\Plugin\search_api\processor, otherwise it wouldn't be found.
The general standard for this parameter is either Plugin/[module]/[component] (like here) or Plugin/[ModuleComponent] (so, Plugin/SearchApiProcessor in this case). I think the former is generally preferred if your module defines more than one plugin type, while the latter can be cleaner/more practical if your module only defines a single one – I'm not completely sure myself, though. They probably shouldn't be mixed in a single module, in any case.
(As a side note, I cheated here a bit, we currently use the sub-dir Plugin/SearchApi/Processor for processors. As I'm pretty sure that's wrong, though, we'll change that shortly.) - \Drupal\search_api\Annotation\SearchApiProcessor is the fully qualified class name of the annotation that will be used for defining plugins of your type. (See here if you have no idea what I'm talking about.) You can just skip this parameter, in which case it will default to \Drupal\Component\Annotation\Plugin – i.e., the generic @Plugin annotation. Core's validation constraints, e.g., use this instead of an individual annotation. Don't ask me what the decision process is here, but I'm pretty sure it's generally encouraged to use a dedicated annotation for your plugin types.
- Plugin/search_api/processor is the sub-dir (and therefore sub-namespace) in which plugins of this type have to be located for automatic detection. That means, e.g., if the Views module would want to provide a Search API processor, it would have to be in namespace \Drupal\views\Plugin\search_api\processor, otherwise it wouldn't be found.
- The second line just sets up caching for the plugin type, to avoid having to re-discover the available plugins each time they are required. search_api_processors here is the cache key that will be used to store the cached entries. You can also pass an array of cache tags as an optional third parameter to setCacheBackend(), which can be useful in special scenarios (i.e., when the cached plugin data should always be cleared alongside other cached data) but usually shouldn't be done.
- The last line just determines that modules can alter the available processor definitions using hook_search_api_processor_info_alter(array &$definitions). Make sure to also document that hook in your module's MODULE.api.php file!
And that's already it for the class, all very straight-forward. Now, the only thing that's missing for the service is its entry in the search_api.services.yml file:
services:plugin.manager.search_api.processor:
class: Drupal\search_api\Processor\ProcessorPluginManager
parent: default_plugin_manager
The service ID here is generally plugin.manager.[module].[component]. Then we simply specify the class we just created and use the handy parent shortcut to copy over the same constructor dependencies that (usually) all plugin managers have. This is no higher magic but just references (and partly copies over) the following definition from core.services.yml:
services:default_plugin_manager:
abstract: true
arguments: ['@container.namespaces', '@cache.discovery', '@module_handler']
You'll recognize the arguments as exactly those we used in our plugin manager's constructor.
The @SearchApiProcessor annotationSince we wanted a dedicated annotation instead of the generic @Plugin, we still have to create the SearchApiProcessor annotation class to get the plugin type basically working. This is also very easy, we just put the following into search_api/src/Annotation/SearchApiProcessor.php:
<?phpclass SearchApiProcessor extends Plugin {
public $id;
public $label;
public $description;
}
?>
That's all – you just define your plugin annotation's properties and inherit from Plugin, that base class will take care of everything else. The properties aren't even necessary, they are just there to document for other developers what properties the plugin type expects in plugin definitions. (And, though not used in this case, to set defaults for optional properties.) The base class doesn't care about that, it will just save all the properties it encounters in the definition, regardless of whether they are defined or not. (Note, though, that the id property is "magic" – if you want to use that for anything other than the plugin ID (and have the plugin ID in a different property), then you'll have to override getId() in your annotation class.)
The only thing you do have to take care of is that annotation autloading will only work if you put the annotation into the \Drupal\[module]\Annotation namespace.
With the above done, you already have a fully functional new plugin type: other modules can define their own Search API processors and we can easily get all defined processors with the following bit of code:
<?php$processor_plugin_manager = \Drupal::service('plugin.manager.search_api.processor');
$processor_definitions = $processor_plugin_manager->getDefinitions();
foreach ($processor_definitions as $processor_id => $processor_definition) {
$processors[$processor_id] = $processor_plugin_manager->createInstance($processor_id, $processor_settings[$processor_id]);
}
?>
However, while this is a complete working example as far as Drupal's plugin framework is concerned, it is of course not really practical since we don't specify anywhere what we expect from processor plugins, so modules that want to provide their own processors don't know which methods to provide and how they should behave (without combing the whole module code of the Search API for any calls to processor plugins). So, it is more or less required to also define an interface for plugins of your new type that implementing modules would have to use.
The specific methods in the interface of course differ from case to case, but there are a lot of interfaces (and corrsponding base classes or traits) provided in Drupal Core for functionality that is often required for plugins. E.g., PluginInspectionInterface lets you retrieve a plugin's ID and definition, DerivativeInspectionInterface helps dealing with plugin derivatives (look out for an upcoming blog post about those) and PluginBase is a great base class for plugins which implements both of these interfaces and additionally provides a few other handy methods for child classes (first and foremost, a t() method for doing dependency-injected translation). PluginFormInterface provides methods for plugins that should have a configuration form, usually used in conjunction with ConfigurablePluginInterface, which represents plugins with configuration. And ContainerFactoryPluginInterface, as the last one used in the Search API, provides a static create() method for easily implementing proper dependency injection. There are more, though, so take a look through the \Drupal\Component\Plugin and \Drupal\Core\Plugin namespaces before adding custom methods to your plugin interface.
The whole interface then looks like this (conceptually):
<?phpinterface ProcessorInterface extends PluginInspectionInterface, DerivativeInspectionInterface, DrupalConfigurablePluginInterface, PluginFormInterface, ContainerFactoryPluginInterface {
// Put plugin type-specific methods here.
}
?>
This interface is usually put into the same directory (and, therefore, namespace) as the plugin manager (since there is nothing else that really links the plugin manager to the interface), as is a default base class for the plugin type that implements the interface and helps modules avoid boilerplate code when providing their own plugins:
<?phpabstract class ProcessorPluginBase extends PluginBase implements ProcessorInterface {
// Here, provide default implementations for all methods of the interface (for which it makes sense).
}
?>
And that's all, now you've completely defined a new plugin type for your module. Modules can now provide plugins of that type like this:
<?php/**
* @SearchApiProcessor(
* id = "example_some_processor",
* label = @Translation("Some processor"),
* description = @Translation("Description of the processor.")
* )
*/
class SomeProcessor extends ProcessorPluginBase {
// Plugin code.
}
?>
Image credit: findicons.com
ThinkShout: Online Fundraising with RedHen Donation
I’ve spent many a late night in the office shouting at my computer screen - all in the name of philanthropy. Technology woes just go with the small nonprofit territory, and the organization I worked for before joining ThinkShout was no exception. Some of those woes, however, I just couldn’t tolerate. Not when they were getting in the way of our mission, and preventing us from raising funds to support our work.
My first foray into online fundraising happened while I was working in the development department of this small nonprofit. We focused primarily on assisting low-income families with safety net services and emergency housing. Over the last few years, we’d seen a huge increase in the percentage of online donations. Times were changing and we’d begun to rely heavily on that online donation page as we saw more and more donors taking the digital route - many of whom were donating to us for the first time. But as our needs evolved, we needed the donation form to evolve with us. We needed more options, more fields, new content as the campaigns changed. Unfortunately, we didn’t realize what a monumental task that would be, given the online donation solution we were using. The problems didn’t end there.
This set-in-stone donation solution probably wasn’t a big concern back when the development team was first evaluating CRMs. Perhaps they didn’t know what they were getting into. Perhaps they didn’t realize they’d be charged almost $200 every time they needed to edit an online donation form. Perhaps they didn’t think we’d use the form that much. The form itself wasn’t very nice to look at. It didn’t match our website’s theme. It got close, but something was always off. There was absolutely nothing convenient about dealing with it.
Those days are a ways behind me, but they’re still on my mind. Since my transition to ThinkShout, I’ve had the opportunity to view these issues from a different perspective and I tend to hear the same complaints from the nonprofits we serve:
- Multi-step checkout
- Clunky check-out systems
- No control over form content
- No support for multiple campaigns
- Forms are expensive to edit
- Can’t fix issues without ticketing your CRM’s support team
- Form theme doesn’t match your website
- Payment methods are limited
Wow. Look at this awesomely long list of annoying things that plague such an integral part of nonprofit fundraising. My blood still boils when I think about how difficult a decision it was to simply submit a ticket to change a single line of text in our donation form - how much effort went into making a case for the cost. This had to change. There had to be something better.
We began working on the RedHenDonation module with intent to create a better online donation solution. We wanted to create a donation tool that allowed nonprofits to keep everything under one roof. The end result accomplishes this. What we came up with is unique in the sense that it offers nonprofits several features that aren’t quite so commonplace. RedHen Donation is inside their website, connected to their CRM. It allows for both one-time and recurring donations, multiple donation pages, and easy-to-edit donation forms.
I chatted with Brandon Lee, the architect behind RedHen Donation, to get a better understanding of RedHen Donation’s capabilities.
Stephanie: So what’s the big deal with RedHen Donation?
Brandon: It’s an integration between RedHen CRM contacts and Drupal Commerce that allows for single page donations with both one time and recurring donations options. The recurring donations feature is a pretty big part of it, since that’s not an option you frequently see offered in other donation form tools.
Stephanie: How does it work with RedHen CRM?
Brandon: RedHen Donation allows you to create a single page donation form that can create or update RedHen contacts. It’s tightly-integrated with RedHen, so if you’re already using RedHen CRM, it will be very simple to get up and running.
Stephanie: How does it compare to other donation form modules out there?
Brandon: It’s a standalone module that’s used with the RedHen suite. CRM Core has a similar donation module, but it doesn’t allow for recurring donations. RedHen Donation does. The ability to give donors the option of setting up a recurring donation within the same form is something we’re thrilled to offer nonprofits.
The donation space, in a lot of ways, is what sets it apart from similar modules. If you’re dealing with Commerce specifically, it wants to lock you into the Commerce workflow. With RedHen Donation, you don’t have to go through three different steps to make one donation to an organization. You fill out one page and you’re done. It’s quick and user-friendly. No more filling out a form, then passing through a portal, then onto a confirmation page, then back to your site.
Stephanie: What if I want create a new form?
Brandon: With the assumption that you already have RedHen set up, it’s relatively simple. You enable the module, then create a donation type, which is a Drupal entity, and during the configuration, you select what kind of product you’re working with - at least with one-time donations. This is a fieldable methodology that we’ve used with MailChimp and other projects in the past. If you understand Drupal concepts of entities, fields, and commerce, then it’s simple. You do need a working knowledge of those three things to build a form. But once it’s complete, it’s incredibly simple for donors to use. That’s the whole point of the single page donation form. You can offer multiple recurring options. Every month for forever, every month for a year, all of those options on the same page.
Stephanie: It sounds like you’ve got a lot of payment options to choose from as an end-user - and the recurring donation option is huge win for fundraisers - but how customizable is this form? And how difficult is it to make changes?
Brandon: It allows for different payment gateways, like iATS - basically, anything supported by Drupal Commerce. Create a contact, indicate which fields you want created, pick a payment gateway, and you’re set. It can be as simple as name, credit card number, and donation amount. It can be as complex as name, credit card, honoree, honoree address, honoree’s favorite color, etc. Payment options allow for text fields, a drop-down menu, or other. Recurring payments open up another myriad of options.
Stephanie: So long as I know Drupal, I can make this form into whatever I need?
Brandon: Exactly.
Stephanie: Say I have multiple campaigns I’m running and I need a different form for each campaign. Can I do that?
Brandon: Absolutely. Let’s say you have multiple different contact types in RedHen because of the campaign. And say I want to send out this particular form because I’m currently soliciting for one particular campaign. You can have as many donation forms as you have entities that are fieldable. You can create a different form on the same content type.
Stephanie: Anything else we should know about it?
Brandon: The availability of RedHen Donation within RedHen CRM is a big deal. You don’t have to worry about third-party integration. You don’t have to send people off to another site to collect the donation. You don’t have to wait on a third-party to send that much-needed information back. With RedHen Donation, it just works. It’s all self-contained. If I’m a nonprofit site admin, this is a great option, and a great reason to consider using RedHen CRM because everything needed to collect donations is all in one place.
Our Conclusion:
RedHen Donation is a fantastic asset for nonprofits looking for a flexible, customizable, and affordable online donation tool. Its single-page functionality and recurring donation options make it a must-have for organizations that need these features to work seamlessly with their Drupal website. For organizations currently shopping around for a CRM, RedHen Donation is a huge plus for RedHen CRM and a compelling reason to select it as your constituent database.
We’re incredibly excited about RedHen Donation and what it offers nonprofits. We do understand that seeing is often believing, so we highly recommend that you install the latest release of RedHen CRM, RedHen Donation, and see what we’re talking about. Not sure how to get started? Do you have more questions than what we covered? Leave us a comment - we’d love to talk RedHen with you.