Managing WordPress with Composer

With the introduction of Drupal 8 the Composer package manager became the goût du jour for me. And once you start using Composer to manage your PHP-projects you never want to do it any other way.  So how do you go about it if you  want to spin up a WordPress site using composer? There is plenty of useful information to be found on the internets, not least from the competent people at roots.io. This piece was written all the way back in August of 2013, but still seems to be the best summary out there: Using Composer with WordPress After reading this and following the instructions I still found it hard to get the plugins and themes in the right directory. So here is my current boilerplate composer.json for spinning up a WordPress site, hopefully it helps someone else looking for the same thing: { "require": { "johnpbloch/wordpress": "^4.9", "wpackagist-plugin/fakerpress": "^0.4.11" }, "extra": { "wordpress-install-dir": "wp", "installer-paths": { "wp/wp-content/plugins/{$name}/": ["type:wordpress-plugin"], "wp/wp-content/themes/{$name}/": ["type:wordpress-theme"] } }, "repositories": [ { "type":"composer", "url":"https://wpackagist.org" } ] } I'm sure this can be done even better and I look forward to any suggestions in the comment section below this article.  So once you've installed WordPress itself and you want to add a plugin, you do that by typing  composer require wpackagist-plugin/{name of plugin} In the boilerplate above I've included the Fakerpress plugin, which allows you to quickly add place holder content in your WP site. Not dissimilar to the devel generate functionality in the Drupal Devel module.   ...
Read more

Leander LindahlLeander Lindahl

This is how you install Drupal Console

Drupal Console is a command line tool derived from the Symfony Console and let's you debug, and interact with Drupal as well as create "boilerplate" code. Once you've installed Drupal Console you should be able use it to create modules and services among other things. A nice time saver. This is how you install it.  1. Use your Terminal to download the latest version of Drupal Console curl https://drupalconsole.com/installer -L -o drupal.phar 2. Verify that the drupal.phar file works php drupal.phar This should result in a list with the available commands Drupal Console Launcher 1.5.0 Usage: command [options] [arguments] Options: -h, --help Display this help message -q, --quiet Do not output any message -V, --version Display this application version --ansi Force ANSI output --no-ansi Disable ANSI output -n, --no-interaction Do not ask any interactive question -e, --env[=ENV] The Environment name [default: "prod"] --root[=ROOT] Define the Drupal root to be used in command execution --debug Switches on debug mode --learning Generate a verbose code output -c, --generate-chain Shows command options and arguments as yaml output to be used in chain command -i, --generate-inline Shows command options and arguments as inline command -d, --generate-doc Shows command options and arguments as markdown -t, --target[=TARGET] Site name you want to interact with (for local or remote sites) -l, --uri=URI URI of the Drupal site to use (for multi-site environments or when running on an alternate port) -y, --yes Skip confirmation and proceed -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug Available commands: about Displays basic information about Drupal Console project chain Chain command execution check System requirement checker exec Execute an external command. help Displays help for a command init Copy configuration files. list Lists all available commands debug debug:chain (dch) List available chain files. debug:settings (dse) List user Drupal Console settings. debug:site (dsi) List all known local and remote sites. develop develop:contribute Download Drupal + Drupal Console to contribute. quick quick:start Download, install and serve a new Drupal project settings settings:set Change a specific setting value in DrupalConsole config file site site:new Download a new Drupal project 3. Move the file to a place on your system where it can be globally executable, and change the permissions  mv drupal.phar /usr/local/bin/drupal chmod +x /usr/local/bin/drupal 4. Copy the configuration files to your user directory ($HOME or ~/) drupal init This will launch a series of y/n questions. I choose to say "yes" to all of them. Now you get this response: Bash: Bash support depends on the http://bash-completion.alioth.debian.org/ project which can be installed with your package manager of choice. Then add this line to your shell configuration file. source "$HOME/.console/console.rc" 2>/dev/null Bash or Zsh: Add this line to your shell configuration file: source "$HOME/.console/console.rc" 2>/dev/null Fish: Create a symbolic link ln -s ~/.console/drupal.fish ~/.config/fish/completions/drupal.fish Generated or updated files Generation path: phar:///usr/local/bin/drupal/bin/../ 1 - /Users/leanderl/.console/config.yml 2 - /Users/leanderl/.console/console.rc 3 - /Users/leanderl/.console/drupal.fish Generated lines of code: 42 5. Configure the autocomplete features  #Bash or Zsh: Add this line to your shell configuration file: source "$HOME/.console/console.rc" 2>/dev/null #Fish: Create a symbolic link ln -s ~/.console/drupal.fish ~/.config/fish/completions/drupal.fish 6. If you need to update the Drupal Console, just run this command: drupal self-update   Source: https://drupalconsole.com/articles/how-to-install-drupal-console ...
Read more

Leander LindahlLeander Lindahl on Drupal 8

Acquia Dev Desktop, Drush and Drupal 8.4

If you are using Acquia Dev Desktop for spinning up Drupal 8 sites quickly – like I suggested in this article you may run into trouble when trying to use Drush on Drupal version 8.4 and newer. Update 2018-02-02: You won't need to follow the instructions below to "fix" your Dev Desktop, you simply have to download the latest version of the Acquia Dev Desktop. The "Check for update" function in Acquia Dev Desktop isn't working properly and always tell you that you have the latest version, even when there's a new version available. If you're using Acquia Dev Desktop with Drupal 8.4 and Drush (which is version 8 in the current version of Acquia Dev Desktop) you'll probably get this error: PHP Fatal error: Declaration of Drush\Command \DrushInputAdapter::hasParameterOption() must be compatible with Symfony\Component\Console\Input\InputInterface::hasParameterOption($values, $onlyParams = false) in /Applications/DevDesktop/tools/vendor/drush/drush/lib/Drush /Command/DrushInputAdapter.php on line 27 This is because Symfony in Drupal (8.4.4) has been updated to ~3.2 (it used to be 2.8.x). Long story short: this breaks Drush 8 lesser than 8.1.12 and you'll be needing Drush version 8.1.12 or above to execute Drush commands on your Drupal site. To patch/upgrade Acquia Dev Desktop you need to update composer.json in the tools folder. To do this on a Mac, which is the OS environment I'm familiar with you open Terminal and go to cd /Applications/DevDesktop/tools In this folder you'll find the composer.json file that governs which version of Drush that Acquia Dev Desktop is using. If you wish to, you can inspect this file and change it like so: nano composer.json --- { "require": { "drush/drush": "8.1.12" } } --- After this, you can update composer by typing composer update And you should be able to use Drush again. (Drush 9 is compatible with Drupal 7 and Drupal 8.) ...
Read more

Drupal 8 Learning Series: 2. Disable Cache in a Devel Environment

If you've developed in Drupal before you're familiar with the classic question "have you cleared the cache?". If you haven't developed in Drupal before, let me ask you this: – Have you cleared the cache? To do any kind of decent development you need a non-cached environment, so that changes you make to the code are reflected upon reloading in the browser. In this second article of the Drupal 8 Learning Series we'll look into how to configure your cool new D8 project for development. Out of the box Drupal 8 comes with the maximum possible amount of caching enabled. The reasoning behind this is that a site should be as performant as possible with the default settings. This is all good and well. But usually you start by doing some development and then it's not so great if the changes you make in code are not reflected when you refresh.  It can be quite tricky to disentangle the web of cache settings if you're new to Drupal 8. So let's have a look at how to set up a local development environment with no cache. 1. Edit settings.php The first step to "uncache" your D8 site is to uncomment a few lines in settings.php if( file_exists(__DIR__.’settings.local.php’) ) { include __DIR__ . ’settings.local.php’; } In more recent versions of Drupal 8 this will be: if (file_exists($app_root . '/' . $site_path . '/settings.local.php')) { include $app_root . '/' . $site_path . '/settings.local.php'; } What these line of codes do is to include a file called settings.local.php. In a standard installation this file will be located in sites/default/settings.local.php.  Copy sites/example.settings.local.php to sites/default/settings.local.php This new file will provide overrides to the regular settings.php file and in a local development environment caching will be disabled in these settings. To make Drupal register (read) this new settings.local.php file you need to clear the cache with Configuration -> Performance -> Clear all caches or drush cr. 2. Use development.services.yml Using the sites/default/settings.local.php file will also include and use sites/development.services.yml. This file should already exist in you Drupal 8 project out of the box. It will override the configuration in sites/default/services.yml. Personally I find it confusing that the sites/development.services.yml override lives one directory level above sites/default/services.yml. But it does.  The important part of the sites/development.services.yml is the declaration of  $settings['cache']['bins']['render'] = 'cache.backend.null'; which will return a "null" cache. Which means no cache.   # Local development services. # # To activate this feature, follow the instructions at the top of the # 'example.settings.local.php' file, which sits next to this file. services: cache.backend.null: class: Drupal\Core\Cache\NullBackendFactory 3. Debugging Twig So now we have a Drupal 8 site that doesn't cache everything by carving it into rock. But we still need to debug twig and stop caching template files. You also need to do this in order to get theme hook suggestions. No problem: just add the "parameters" below to your sites/development.services.yml # Local development services. # # To activate this feature, follow the instructions at the top of the # 'example.settings.local.php' file, which sits next to this file. services: cache.backend.null: class: Drupal\Core\Cache\NullBackendFactory # Enable Twig debugging. parameters: twig.config: debug: true auto_reload: true cache: false (We'll be discussing the theme hook suggestions in a future article of Drupal 8 Learning Series. Stay tuned.) 4. Don't trip up on browser cache Sometimes when you configure your local development environment like I've described above you still have to empty cache "manually" between every page load. Why? What is wrong? Most likely it's the browser cache settings. Make sure you've disabled browser caching. In Chrome this is how: Read more on this topic here: https://www.drupal.org/node/2598914 https://knpuniversity.com/screencast/drupal8-under-the-hood/debugging#play   ...
Read more

Drupal 8 Learning Series: 1. Create a child theme

Where should an aspiring web developer who wants to try out Drupal 8 begin? In a series of posts I’ll walk you through a few basic exercises to help you get acquainted with Drupal 8. If you’re already a real pro scooting around D8 in your coding skills equivalent of a jetski – this content is clearly not for you. But if you feel a bit lost where to start and want to try out some basic Drupal development you’re welcome to read along. This first post will simply show you how create a child theme. Having a custom child theme will allow you to have a set of ”your own files” where you can start coding without hacking core. I guess it may seem self evident to most people, but it’s still worth mentioning, that you never, under any circumstances, want to hack core. Why? Because doing so will make you ”enter a world of pain, Smokey” (ten points to whoever pins that quote). Here are three reasons why: Hacking core means that you will not be able to safely update Drupal Core or contrib modules further down the line. Drupal provides plenty of hooks and opportunities for you to alter and add things without touching the code in core or in contributed modules and themes. Hacking core exposes you as someone who doesn’t know Drupal and is too lazy and arrogant to do basic research and read the API on drupal.org A kitten dies every time you hack core (https://drupal.stackexchange.com/questions/59054/why-dont-we-hack-core) Creating a child theme to Bartik Install Drupal 8 by your preferred method. As of lately I recommend using Acquia Dev Desktop for learning and testing purposes – read about that in my previous blog post here (http://leanderlindahl.se/article/acquia-dev-desktop-fastlane-drupal-8-development).  Find your document root and open it in an editor such as PHPStorm or Sublime.     For the purpose of this tutorial we’re going to create a custom child theme named Katniss in the themes-folder. The theme will be based on the Bartik that is the default theme in Drupal 8. Open the themes folder in your site root (e.g ~/username/Sites/devdesktop/drupal-8.3.2/themes). This is the location where you store themes – both downloaded contributed themes from drupal.org and custom themes that you create yourself. (In Drupal 7 this used to be sites/all/themes.) To keep everything orderly and pretty we are going to create a folder inside themes named “custom”. If you download contributed themes from drupal.org or elsewhere, you should place them in a folder named “contrib". This subfolder structure (themes/custom and themes/contib) is a convention and not a technical requirement. But if you are going to become a honourable Drupal citizen you should go for the “orderly and pretty” option and follow this Drupal convention. Now in the themes/custom folder you create the actual folder containing your theme. In this example where we’re creating a theme named “Katniss” the folder should be named “katniss” (lowercase is the convention of all folder and file names).   Inside “katniss” create a new file named katniss.info.yml. And insert the following code (this is what actually creates the theme in the eyes of Drupal): name: Katniss type: theme description: Custom theme for District 12 core: 8.x base theme: bartik libraries: - katniss/global-styling The name value is the "human readable" name of your theme. This could be something other than the machine name "katniss", such as "Everdeen" or "My super AweSome fancy Theme". But it's usually a good idea to keep this name more or less the same as the machine name to avoid confusion, in this case we're going with "Katniss". The type value declares to Drupal that this is a theme. The description value allows you to specify a description for your theme. The base theme value is used if you want your theme to be based on another theme. Basing your theme on another means that your theme will inherit all the settings and templates from another theme unless you actively override those settings and templates with your own settings and templates. The core value declares with what version of Drupal your theme is compatible. In our case this is Drupal 8.x, which means all versions of Drupal 8. Now libraries is slightly more tricky. This declaration allows you to attach CSS and JavaScript files to your theme. In this case we're declaring "katniss/global-styling". This means that Drupal will look in "katniss" for a file named "katniss.libraries.yml". In this file it will look up the declaration of "global-styling". We could have named this anything. But we didn't. So let's create "katniss.libraries.yml" and declare "global-styling".  global-styling: version: 1.0 css: theme: css/style.css: {} To keep this exercise simple we'll only add a style.css file where we can add css to our theme. You could also add javascript and other resources, such as font-awesome in the libraries declaration. So now we've added a stylesheet to our theme and it will live in the theme's folder (katniss) in a subfolder named css. The file itself will be name "style.css". This is what the source file tree should look like now:   There's actually one more thing we have do to to avoid having errors thrown. If we're using Bartik as base theme the template files we're inheriting are expecting the same regions as in Bartik to be available. Thus we need to copy the regions declaration from core/themes/bartik/bartik.info.yml into our own katniss.info.yml:   name: Katniss type: theme description: Custom theme for District 12 core: 8.x base theme: bartik libraries: - katniss/global-styling regions: header: Header primary_menu: 'Primary menu' secondary_menu: 'Secondary menu' page_top: 'Page top' page_bottom: 'Page bottom' highlighted: Highlighted featured_top: 'Featured top' breadcrumb: Breadcrumb content: Content sidebar_first: 'Sidebar first' sidebar_second: 'Sidebar second' featured_bottom_first: 'Featured bottom first' featured_bottom_second: 'Featured bottom second' featured_bottom_third: 'Featured bottom third' footer_first: 'Footer first' footer_second: 'Footer second' footer_third: 'Footer third' footer_fourth: 'Footer fourth' footer_fifth: 'Footer fifth' Now your theme should be available in the "Appearance menu" of your Drupal Site and you should be able to install it and set it as default:     If you have trouble finding your theme try to empty the cache in "admin/config/development/performance" and click the button "clear all caches".  As the crowning of your work, and to verify that your theme is now the "boss" of your Drupal site's appearance create the file themes/custom/katniss/css/style.css and enter the following: * { color: red !important; } Empty the cache with admin/config/development/performance in a different browser tab and view the result. It should look something like this:   This CSS is kind of awkward and is only meant as a test for you to establish that your actual CSS impacts the site. So now you have a child theme for Drupal 8, where you can start coding to your hearts content. In the next article of this series we'll have a look at setting up your development environment without the very strict and "heavy" default caching that Drupal 8 has "out of the box".  Happy coding! ...
Read more

Acquia Dev Desktop - a fastlane to Drupal 8 development

Ever been curious about Drupal? Ever wanted to try it out? Are you introducing someone else to Drupal development?  Or perhaps you're neither curious nor wanting to try it out because you're already seasoned and experienced in Drupal, but you want to be able spin up a dev environment quickly to try out a new idea or create a proof of concept? Enter Acquia Dev Desktop. I must admit I’ve always been skeptical of pre packaged solutions as opposed to installing the stack (Apache/Ngnix, MySQL, PHP) myself. It feels purer and more under my control if I do the installation and configuration of each component in the stack myself. Call me old fashioned and square headed – because I am. But the last few weeks I’ve tried out Acquia Dev Desktop when training developers and designers new to Drupal and I’ve reluctantly come to the realization that it’s pretty awesome. I guess the key moment was when I could get my 9 year old daughter without previous experience in development to host her own local development environment and Drupal project within the space of 5 minutes.  We could immediately get to the ”fun stuff” and create her own custom theme and do some CSS. When I work with Drupal development I usually try out concepts and ideas in a ”vanilla” Drupal before trying them out in a more complex existing project. That way you can separate the specific and often complicating factors of your existing project from the ”clean” bare bones principles of ”would this concept work” in Drupal if I combined these customizations, contributed modules and Drupal core to build something in this way?  It’s a lot easier to ”see clearly” when working with a site that is not weighed down by all the often times strange configuration and code that an existing project has accumulated. And if you do this – once you establish that your concept and principles are sound and viable  – you can tackle the more daunting task of implementing them in an existing project with the knowledge that your concept in itself is sound. "Yada yada yada – so Leander likes Acquia Dev Desktop" I hear you say? Correct – so let’s get to it.  How to install and run Acquia Dev Desktop Visit https://dev.acquia.com/downloads and click ”Download” Run the installer Once the installer has finished you’re prompted to choose a distribution. At the time of writing this the second and third alternative gives you the lates versions of ”vanilla” and ”standard” Drupal (v8.3.2 and v7.54). These are the versions I would recommend if trying out Drupal so that you build your knowledge from a standardized and neutral base. There are of course many more options such as ”Lightning, Acquia Drupal and Drupal Commerce”. I must admit that except for Drupal Commerce I know next to nothing of these distributions, but I ’m sure they’re excellent in their own right. However I feel you learn the most and get the most value out of installing a ”regular” Drupal and then adding functionality (i.e. modules) to that, rather than using a distribution. However that is just my personal opinion Once you choose a distribution – the installer installs your actual Drupal site.  Now you have Drupal in a local development environment to play with! Typically this should take no more than five minutes and all you’ve been required to do is click ”ok” and ”continue” a few times.   What do I do now? The beauty of it all is that you only have to click to browse you new Drupal development environment.   Click on (1) "local site" to browse your local development installation. Click on (2) "local code" to open the local directory containing the site root and start coding. Click on (3) the terminal icon to open a terminal where you can run drush commands such as "drush dl module_name" or "drush cr" (drupal 8) or "drush cc all" (drupal 7). Update 2018-01-18: If you're using Drupal 8.4 adn Drush, you may have to manually update Drush in Acquia Dev Desktop.   ...
Read more

Radera en mapp via terminal

Terminal-kommandon som jag alltid behöver Googla: rm -r -f katalognamn rm //remove / delete -r //recursively deletes the directory and all files in it, including subdirectories -f //will not ask for confirmation before deleting Tips för geeks: Man kan spara två tangentryckningar genom att skriva “-rf” istället för “-r -f” Källa:  http://dustyreagan.com/how-to-delete-an-entire-directory-via-ssh/ ...
Read more

Leander LindahlLeander Lindahl on Terminal

Filter content in a Drupal View with AJAX

When displaying Drupal content through Views you’d sometimes like the user to be able to dynamically filter the content from a list of links. Ajax is already part of Drupal 8 Views. This is how you change the default <select> list into themable links. Update 2018-01-05: Some of my readers have had trouble getting this to work properly. So I've added a demo module that you can download from GitHub to get working code including a preconfigured view. Remember to clear Drupals' cache after installing it. Have fun! In a previous post I've written about how you can do this same thing in Drupal 7. This time around we are going to explore how it can be done in Drupal 8, which is currently in beta (8.0.0-beta15). The nice thing about Drupal 8 is that the Views module which we are going to use is now part of Drupal core, which means you can get a lot more done "out of the box" without installing any contrib-modules.   This is the default select list from Views for exposed filters.[/caption]   To turn the default Views Exposed Filter <select> into a list of links we'll create a custom module and make use of the powerful Drupal form_alter hook. We are also going to add some javascript and a tiny pinch of css. If this sounds intimidating, don't worry, I'll walk you through it step by step. I'm sure there are other methods to achieve the same result, but in my experience, a leaner solution, with a relatively simple override is usually the quickest and most reliable way to go. The alternative of adding one or more contrib-modules to a site for a small thing such as this means that those modules have to work (in themselves and with each other) and be without bugs, patches, dead-end issue queues and so on. That's not always the case. You could wind up spending hours trying to solve a tiny problem only to find in the end that it can't be done with the current state of the modules.   The View We're assuming that you've already created articles and tagged them. In this clean install of Drupal 8 beta I created three articles and tagged them alfa, beta and gamma. Next we need to create a View. In the Drupal 8 admin section you choose Structure -> Views and then click the blue button that says + Add new view. Choose Show Content of type Article. Check Create a page for this example. Display format should be Unformatted list of fields. Remove (empty) the default number of items to display and uncheck Use a pager. When you’re done click Save and edit.     Next we need to create the exposed filter which will let the user click and sort the content. The Exposed Filter Add a filter criteria to your view by clicking the add button in Filter Criteria section of the views interface. [caption id="attachment_347" align="alignnone" width="838"]       The AJAX At this point we have our View and our Exposed Filter, but we still need to activate AJAX to make the view filter the content dynamically. In the Advanced section of your View configuration screen you will find what you need. Per default these settings are collapsed. Open it by clicking the Advanced section label.    Now change the setting for Use AJAX. This should simply be switched from No to Yes.     To make the effect of the filtering more visually clear while developing I've added the fields image and tags to the fields section (and removed title). I also changed the Sort Criteria to Tags (desc) to have the tags display in alphabetical order. Simply because it looks more orderly to me.  So up to this point we've created our content, our view, added the filter criteria and activated AJAX in the view. So we have the basic "stuff" we need: we can display the content of our choice, with the presentation of our choice (teaser, fields or something else) we can filter the content by the terms the editor has tagged it with the content gets refreshed with AJAX without reloading the entire document Now all we need is to tweak the presentation to suit our taste – or the taste of the designer who handed us their fancy design. The Custom Module To be able to use hook_form_alter and do our magic we need to create a custom module. Start by creating a new folder called custom in the modules folder. The purpose of this is to set custom made modules apart from contributed modules (downloaded from Drupal.org). Now in the custom folder create your new custom module folder. In this example we are naming the module popolo_custom. You can name it anything you want. But remember to replace all occurrences of popolo_custom in the following code examples with the name you've chosen. Now begin by declaring your module with a yml-file: popolo_custom.info.yml name: Popolo Custom type: module description: 'Example module for Drupal 8.' package: Custom version: 8.x core: 8.x Next we need to find out the form id of the exposed filter we're trying to manipulate. To to this inspect the form in your browser. Inspect the views exposed form in your browser to find the form id. Make a note of the id, so that you can copy and paste it into the code. If you've followed the steps of this tutorial exactly the id should be views-exposed-form-filter-articles-page-1. If you're implementing this on a different view, obviously the id will be something different.[/caption]   Now let's create the popolo_custom.module file. And paste the following code into it. Make sure the id on row 8 matches the id we just inspected: <?php /** * @file * Module file for Popolo Custom. */ /** * Implements hook_form_alter(). */ function popolo_custom_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id){ // Apply the form_alter to a specific form #id // the form #id can be found through inspecting the markup. if($form['#id'] == 'views-exposed-form-filter-articles-page-1') { // Include js and css, which was defined in libraries.yml. $form['#attached']['library'][] = 'popolo_custom/popolo_custom.enable'; $form['#attached']['library'][] = 'popolo_custom/popolo_custom.forms'; // Extract the options from the Views Exposed Filter <select>-list. $links = $form['field_tags_target_id']['#options']; // Iterate over the options ($links) to build an array ($pop_array) of links. $i = 0; // Initiate counter/index $pop_array = array(); foreach ($links as $tid => $term_name) { if ($tid == 'All') { $pop_array[$i]['#markup'] = '<span class="filter-tab"><a href="" class="active" id="' . $tid . '">' . $term_name . '</a></span>'; } else { $pop_array[$i]['#markup'] = '<span class="filter-tab"><a href="" id="' . $tid . '">' . $term_name . '</a></span>'; } $i++; // Increase counter/index } // Create the item-list the form should render. $form['links'] = [ '#theme' => 'item_list', '#items' => $pop_array, '#attributes' => ['class' => ['pop-list']], ]; } } The code identifies the form we want to alter with a simple "if the id equals [our id] then do the following" (row 8). Next on rows 13 and 14 we add some javascript and css. After that we pull out the options from the select list and construct our own list items with some markup and css-classes that we want. This particular example uses some classes that I usually like to have, such as pop-list and filter-tab. Needless to say, you could choose to create different markup and different classes. Now we need to add some javascript (and css) which we did on rows 13 and 14. New in Drupal 8 is that you need to define your external javascript and css files with a libraries.yml-file. So lets do that by creating a file called popolo_custom.libraries.yml. popolo_custom.forms: version: VERSION css: theme: css/popolo_custom.theme.css: {} popolo_custom.enable: version: VERSION js: js/popolo_custom.js: {} dependencies: - core/jquery - core/drupalSettings Thanks to Earl Fong for explaining how this works in this post. Now we create the file popolo_custom.js in a new subfolder named js: (function ($) { /** * Set active class on Views AJAX filter * on selected category */ Drupal.behaviors.exposedfilter_buttons = { attach: function(context, settings) { $('.filter-tab a').on('click', function(e) { e.preventDefault(); // Get ID of clicked item var id = $(e.target).attr('id'); // Set the new value in the SELECT element var filter = $('#views-exposed-form-filter-articles-page-1 select[name="field_tags_target_id"]'); filter.val(id); // Unset and then set the active class $('.filter-tab a').removeClass('active'); $(e.target).addClass('active'); // Do it! Trigger the select box //filter.trigger('change'); $('#views-exposed-form-filter-articles-page-1 select[name="field_tags_target_id"]').trigger('change'); $('#views-exposed-form-filter-articles-page-1 input.form-submit').trigger('click'); }); } }; jQuery(document).ajaxComplete(function(event, xhr, settings) { switch(settings.extraData.view_name){ case "filter_articles": var filter_id = $('#views-exposed-form-filter-articles-page-1 select[name="field_tags_target_id"]').find(":selected").val(); $('.filter-tab a').removeClass('active'); $('.filter-tab').find('#' + filter_id).addClass('active'); break; default: break; }; }); })(jQuery); Notice the id of our view being used in the above code. Finally to polish the look of the view we create popolo_custom.css in a new subfolder named css. This css hides the select list and apply button. The additional styling would normally go into your sites theme. /** * Hide <select> and submit-button */ #views-exposed-form-filter-articles-page-1 .form-type-select { display: none; } #views-exposed-form-filter-articles-page-1 .form-submit { display: none; } /** * Pure styling, should probably be put in your theme stylesheet * instead of in this module */ .pop-list { display: block; text-align: left; margin: 0 auto; padding: 0; } .pop-list li { margin: 25px 5px 25px 0; float: none; display: inline-block; margin: 25px 5px 25px 0; font-size: 16px; text-transform: uppercase; } .pop-list li a { background-color: #CCC; height: 40px; border-radius: 40px; padding: 10px 16px 9px; color: #FFF; line-height: 23px; text-decoration: none; border-bottom: none; } .pop-list li a.active { background-color: #0071b3; } .view-filter-articles .views-row{ float: left; padding: 15px; } Next activate the module in Extend (admin/modules), empty the sites cache and then load the page. If everything works your page should now look something like this: That's it – you're done! ...
Read more

Dynamically filter content in a Drupal View

When presenting Drupal content with a View you'd sometimes like to filter the content from a list of links. Ajax filtering is already part of the Views module. Our job is to change the default select list into links. This is how it is done. This article focuses on Drupal 7, if you'd like to see how this is done in Drupal 8, you should read this post. Some may argue that there are other ways, such as the Better Exposed Filters module for instance. My personal experience of trying that is one of being shipwrecked on the harsh rocks of uncompleted and incompatible code on a sea of patches. In theory it works, but not in practice. With this method you should (fingers crossed) be up an running in a few minutes, instead of spending endless hours trying various contrib modules and their patches. This method entails creating a custom module with form alter and some javascript. If that sounds intimidating don't worry – I'll walk you through it.  The View Before we can begin, we need to create a view. In this example we're using Drupal Core 7.38 and Views 7.x-3.11. Create a View for a content type with taxonomy tags that you would like the user to be able to filter by. Typically this could be content type Article and taxonomy vocabulary Tags. In this example, based on an actual web site in Swedish language, the content type is inspirationsseminarier (english: inspirational workshops) and the taxonomy is called målgrupp (english: target audience). [   Create a basic view listing a content type. Choose Show Content of type *content type of your choosing*. Uncheck Create a page for this example and check Create a block. Remove the default number of items per page. (You could create a page, but for this example we're doing it as a block). When you're done click Continue & edit. This now is your basic view: This is what the basic view looks like before we add exposed filters and ajax.[/caption] The next step is to add an exposed fiter that filters by the tags in the taxonomy you want the user to filter by. The Exposed Filter Now we're going to add a Filter Criteria. Click the add button next to the Filter Criteria section title in the Views interface. [caption id="attachment_243" align="alignnone" width="760"] Step 1/3. Start typing the name of your content types taxonomy term field in the search field to narrow the list of possible fields and then check the checkbox for the field. In this example the field is a taxonomy term field named Målgrupp. Obviously it will be named something else in your case. When you're done – click Apply (all displays).[/caption]   [caption id="attachment_244" align="alignnone" width="760"] Step 2/3. Select Dropdown. Click Apply and continue.[/caption]   [caption id="attachment_245" align="alignnone" width="760"] Step 3/3. Check Expose this filter to visitors, to allow them to change it. Filter type shold be Single filter. Operator should be is one of. If you'd like to limit the choice you can multiselect certain terms (like in the screenshot) or you can include all terms. If you limit the choices, remember to also tick the box Limit list to selected items. Click Apply (all displays) when you're done.[/caption]   The AJAX Now we have our view and our filter. But we still have to enable ajax and configure Exposed forms style. These settings are found in the Advanced section of your View configuration screen. Per default this is collapsed. Open it by clicking the Advanced section label. [caption id="attachment_261" align="alignnone" width="1077"] These are the two settings in the advanced section that you should configure.[/caption] The first setting we are manipulating is Use AJAX. This should simply be switched from No to Yes. The other setting is the Exposed form Settings where we should check Autosubmit and Hide submit button. [caption id="attachment_260" align="alignnone" width="702"] Check the checkboxes for Autosubmit and Hide submit button and then click Apply (all displays).[/caption] [caption id="attachment_267" align="alignnone" width="867"] In your Views preview you should now be able to see the select list and try out filtering your content by term.[/caption] Up to this point what we have done is a standard Views exposed form with AJAX. This is not bad at all, because it means we have all the "machinery" in place that we want and need: we can display the content of our choice, with the presentation of our choice (teaser, fields or something else) we can filter the content by the terms the editor has tagged it with the content gets refreshed with AJAX without reloading the entire document Now we just need that extra little thing. To not have a select list as filter, but rather text links that we can style in whichever way we'd like. To see your new view you need to place the block on a page. Create a new Basic page and once it is saved take note of it's node id (in this example it is 287). Head over to the blocks admin section admin/structure/block and place the new block View: Exposed filter example in a region on the new page. [caption id="attachment_289" align="alignnone" width="1024"] In our example the block from our view is placed in the content region of node 287.[/caption] The custom module To change the markup of the exposed filter we need to use form_alter – a coding hook that let's Drupal intercept a form and change it. We want the markup of the form containing the exposed filter to be a unordered list of links instead of a select list. To create your custom module begin by creating a new folder in your modules catalogue. Typically this would be /sites/all/modules. Good practice would also have you differentiate between contrib modules from drupal.org (such as Views) and your own modules by having subfolders in your modules catalogue. Like this sites/all/modules/contrib <-- modules downloaded from Drupal.org sites/all/modules/custom <-- your own custom modules Whatever you do please don't add any modules to the modules folder of the site root. That folder is only meant for Drupal core modules and your site becomes a mess to maintain if you stick other modules into that catalogue. In this example we create a folder named exposedfilter_buttons in sites/all/modules/custom. In this folder we create a new file named exposedfilter_buttons.info with the following code: name = Exposed Filter Buttons description = Create Buttons instead of Select box in Views Exposed Filter package = Views core = 7.x dependencies[] = views Next we create a new file named exposedfilter_button.module. Before we continue we need to find out the form-id of our exposed filter. This is not completely straight forward, but the way you do it is by inspecting the form element. [caption id="attachment_290" align="alignnone" width="1001"] Inspect the exposed filter form to find its' ID. In this example the ID is views-exposed-form-exposed-filter-example-block.[/caption] In the exposedfilter_buttons.module file we place the following code and make sure that the id on row 7 matches the form id that we just inspected: <?php function exposedfilter_buttons_form_alter(&$form, &$form_state, $form_id) { /** * Manipulate output of Views Ajax Exposed filter */ if ($form['#id'] == 'views-exposed-form-exposed-filter-example-block') { $form['#attached']['js'] = array( drupal_get_path('module', 'exposedfilter_buttons') . '/js/exposedfilter_buttons.js', ); $links = $form['field_kategori_tid']['#options']; $newlinks = array(); foreach ($links as $tid => $term_name) { if ($tid == 'All') { $newlinks[] = array('data' => '<span class="filter-tab"><a href="" id="' .$tid . '" class="active">' . $term_name . '</a></span>', 'class' => array('pop-filter-label')); } if (_get_term_depth($tid) == 1) { $newlinks[] = array('data' => '<span class="filter-tab"><a href="" id="' .$tid . '">' . $term_name . '</a></span>', 'class' => array('pop-filter-label')); } } $prefix = theme( 'item_list', array( 'items' => $newlinks, 'type' => 'ul', 'attributes' => array('id' => 'pop-filter-list'), 'container_id' => 'scope-list-wrapper', )); $form['links'] = array( '#type' => 'markup', '#value' => $prefix, '#markup' => $prefix, ); } // extra submit form handle $form['#submit'][] = 'exposedfilter_buttons_form_submit'; } // handle form submition function exposedfilter_buttons_form_submit($form, &$form_state){ $values = $form_state['values']; } What this code does is using a form_alter hook to override all forms in Drupal However we only want to override the form with the specific id of our exposed filter, hence the if-condition on row 7. When we've established that we're altering the right form we add a custom javascript on row 8-10. The rest of the code iterates through the taxonomy terms and outputs them as an unordered list in HTML. You may notice that code has some css-classes in it which are specific to the site I was building when writing this code: pop-filter-list, filter-tab and scope-list-wrapper. You can name them differently as suits your theming-needs. Next it's time to add the custom javascript file mentioned on row 8 of the above code. Create a new folder in your custom module: sites/all/modules/custom/exposedfilter_buttons/js/ and in it create a javascript file named exposedfilter_buttons.js containing the following code: (function ($) { /** * Set active class on Views AJAX filter * on selected category */ Drupal.behaviors.exposedfilter_buttons = { attach: function(context, settings) { $('.filter-tab a').on('click', function(e) { e.preventDefault(); // Get ID of clicked item var id = $(e.target).attr('id'); // Set the new value in the SELECT element var filter = $('#views-exposed-form-exposed-filter-example-block select[name="field_kategori_tid"]'); filter.val(id); // Unset and then set the active class $('.filter-tab a').removeClass('active'); $(e.target).addClass('active'); // Do it! Trigger the select box //filter.trigger('change'); $('#views-exposed-form-exposed-filter-example-block select[name="field_kategori_tid"]').trigger('change'); $('#views-exposed-form-exposed-filter-example-block button.form-submit').trigger('click'); }); } }; /** * Manipulate HTML for Views AJAX filter * on selected category */ jQuery(document).ajaxComplete(function(event, xhr, settings) { switch(settings.extraData.view_name){ case "exposed_filter_example": var filter_id = $('#views-exposed-form-exposed-filter-example-block select[name="field_kategori_tid"]').find(":selected").val(); $('.filter-tab a').removeClass('active'); $('.filter-tab').find('#' + filter_id).addClass('active'); break; default: break; }; }); })(jQuery); (It is not uncommon to encounter som jQuery version discrepancies when dealing with jQuery in Drupal and that is why the contrib module jQuery Update exists. The settings that worked for me are jQuery 1.8 on both front end and back end.) [caption id="attachment_301" align="alignnone" width="937"] jQuery update settings.[/caption] Next activate the module in admin/modules, empty the sites cache and then load the page where you placed the block. If everything works your page should now look something like this: [caption id="attachment_300" align="alignnone" width="637"] This is approximately what your page should look like. You should be able to click the text links and dynamically filter and AJAX-reload the content.[/caption] To wrap things up add your own custom theming and css-hide the default select list #edit-field-kategori-tid-wrapper { display:none; } You're done! ...
Read more

Sanitize names of uploaded files in WordPress

Nothing worse than user contributed image files with strange (non-english) characters in the file name right? Here's what you can do about it in WordPress. If you are working with WordPress Sites in non-english languages, like for instance Swedish, like I am, sometimes there can be a world if pain when moving sites between hosts if the file names include non-standard charachters such as åÅ, äÄ, öÖ. The images appear as broken, becuase something with the file name encoding happens along the way. Here is a function to put in your themes functions.php that will help sanitize file names of uploaded files. add_filter('sanitize_file_name', 'sa_sanitize_chars', 10); function sa_sanitize_chars ($filename) { return remove_accents( $filename ); } Source: http://clubmate.fi/remove-weird-characters-like-o-and-a-from-file-names-in-wordpress-aka-sanitise-file-upload-image-names/ ...
Read more