Drupal8Cards #01 - Configuration Management in D8
Objectives
At the end of this course, you will be able to
- export configuration from a local or Dev environment
- transfer the same by copying the files or through version control to another environment
Thereby, moving version-controlled configuration across various environments.
Exercise
- Setup 2 local D8 instances. Call one site Dev and the other Prod (Clone the dev site to prod, rather than setting them up individually. Research issues with mismatching UUIDs)
- Create a simple content type (say Book) with 2 fields (Title, ISBN) and create 2 nodes of content on Dev
- Build a simple view (of page type, accessible at the url /list) listing the book nodes
- Export the site configuration using Drush (which includes the content type and the view) using drush cex command or Drupal Console using drupal ce
- Copy the exported files to the same directory on the Prod site simulating a code pull from the upstream repo.
- Import the configuration using drush cim on prod site or drupal ci. Verify the content type and view are available on Prod.
Drupal8Cards #02 - Paragraphs Module
Objective
At the end of this course, you will be able to
- Create paragraph types
- Use paragraphs in content types to display grouped fields appropriately.
Exercise
- Create a Paragraph type “Social Media” with the following fields 1) Embed Code (Text field that accepts any long text and is rendered without any filters (Hint: Create a text format called “Raw”) and 2) Link
- On the Article Content type Add a new field referring to the above paragraph type created (Multiple values allowed).
- Configure the display of the paragraph type and the article content type such that the embed code and link are displayed as on the screengrab attached.
Fields on Paragraph Type
Bonus Exercise
Theme the paragraph type such that the 2 fields (Embed code and link, wherever they are shown on any content type, are rendered in 2 columns as below:
<table> <tr> <td>Embed Code</td> <td>Link</td> </tr> </table>
Drupal8Cards #03 - Building Configuration forms
Objective
At the end of this course, you will be able to
- Create a very basic configuration form on a custom page
- Provide Default values for the configuration on the form
- Save the configuration values on form submission.
Exercise
- Create a custom module that provides a configuration form available at the url “mymodule/config” to all users with the permission “administer content”
- The form shall have 3 fields. Labels and Types of fields are arbitrary. Ensure you have diverse fields Text, Select, Radio
- Get the form to work such that the form values are saved and persisted on the form on reload.
- The values submitted on the form should be accessible elsewhere on the same or a different module using the Config API.
Bonus Exercise
- Create your own permission and use that to restrict this page
Drupal8Cards #04 - Migration 101
Objective
At the end of this course, you will be able to
- Import content from MySQL/CSV dump to content types, taxonomies in Drupal.
Exercise
- Create a movie content type with fields Title (text), Plot(Formatted Text), Actors (Node Reference), Genre(Term Reference)
- Actors and Genres are simple content type and vocab respectively with no additional fields
- Import the CSV dumps from here to populate the movie nodes in Drupal using Migrate API.
Preview Content: Movies, Actors
Bonus Exercise
- Let’s try some preprocessing while migrating. In the plot field of the movie, remove the word “the” (wherever it occurs, irrespective of the letter case).
- Add an Image field to the Movie content type. Update the migration script to use the dump file with images. Rerun the migration such that the images are downloaded and attached to the movie nodes.
Drupal8Cards #05 - Block System
Objective
At the end of this course, you will be able to
- Create "Block Types" with fields
- Place Multiple Instances of the block type with different field values
- Programmatically update block instance values / content
Exercise
- Create a Block type called "Stock Exchange Rate Card"
- Company Name
- Symbol
- Last Price
- Change
- Create Instances of the block with different sets of values and place them at different spots on the site. Example values (Apple, AAPL), (Bank of America, BAC), (Transocean, RIG), (Freeport, FCX). (Ignore the Last Price and Change fields’ values, we will be dealing with them in the next step).
- Below API can be used to retrieve Last Price and Change values http://dev.markitondemand.com/MODApis/Api/v2/Quote/json?symbol=BAC&callback=myFunction
- Build a custom module, which on Cron run,
- Iterates through each instance of blocks of type "Stock Exchange Price Card"
- For each block, take the symbol value and call the API to retrieve the Last Price and Change values
- Update the block field values programmatically with the values of Last Price and Change retrieved from the API and save the block
Drupal8Cards #06 - Services and Dependency Injection
Objective
At the end of this course, you will be able to
- What is dependency injection?
- Building Services and why build services
- Core Services
Exercise
This is not a Drupal API to have an exercise for itself
Drupal8Cards #07 - Cron Queuing
Objective
At the end of this course, you will be able to
- Understand and utilize the Queue API to add tasks to the queue and process them on cron runs
Exercise
- Build a module that sends a welcome email to registered users
- Use the Cron Queue by adding to the queue the user id whenever a user registers
- Create a queue worker that picks these queue items (uids) during the cron and sends a welcome email (can be any simple text) to the registered email address.
Drupal8Cards #08 - Plugin System: Text Filters
Objective
At the end of this course, you will be able to
- Understand a bit of the plugin system
- Create a new Custom Text filter using the Plugin system
Exercise
- Create a custom text filter that could be added to any text format, which autocapitalizes preconfigured words anywhere they occur in the filtered text
- The filter has a configuration form that allows configuring the list of words that should be autocapitalized
Drupal8Cards #09 - Attaching assets (CSS/JS)
Objective
At the end of this course, you will be able to
- add JS/CSS to a module or a theme to be available on selection / all pages
Exercise
- Create a custom module and add a CSS and JS file in appropriate subdirectories in the module.
- Create a libraries.yml file and define 2 libraries one for each of the CSS and JS.
- Attach the CSS such that it is loaded for all Table elements shown anywhere on the site. Hint
- Take any custom block that you have built over the previous exercises. Modify the build() to attach the JS to be loaded whenever the block is displayed. Hint
Drupal8Cards #10 - Configuring your local site for Development
Objective
At the end of this course, you will be able to
- Setting up your settings.local.php
- Null Cache Service
- Disabling Twig Cache
- rebuild.php
Exercise
On your local D8 site, perform all the configuration changes mentioned in the video tutorial.
Video tutorial: https://www.youtube.com/watch?v=rRsOxSuJ4OU
Drupal8Cards #11 - Creating a Custom D8 Content Entity Type
Objective
At the end of this course, you will be able to
- create a content entity type with administration management pages
Exercise
- Create a custom content entity type called “Contact” with the following fields:
- Name
- Email Address
- Telephone
- Address
- Build / Provide a minimal CRUD management page to manage the custom contact entities
- Explore why would you even want to define a custom entity type vs using a Content-Type
Drupal8Cards #12 - Theming 101
Objective
At the end of this course, you will be able to
- build a very basic 3 column D8 theme using "stable" as the base theme
Exercise
- Generate a new theme with “stable” as the base theme using drupal console.
- Define 3 regions (sidebar1, content, sidebar2 while generatingthe theme).
- Turn on Twig Debugging to see the template names in use, as well as template name suggestions (This is covered in our Day10 course) in the view source.
- Override page.html.twig in your theme such that 3 columns are rendered in the page.
Drupal8Cards #13 - Logging in D8
Objective
At the end of this course, you will be able to
- use the replacement of watchdog() in D8
Exercise
- Build a small custom module, which adds to the “Recent Log Messages” a message of type “Node Updates” with the message “Node with title %NODE_TITLE% of type %NODE_TYPE% has been updated“ whenever a node is updated.
Drupal8Cards #14 - Creating a Custom Field Formatter
Objective
In this course today, we will be revising the plugin system by creating a custom field formatter.
Exercise
- On the Movie content type, create a Decimal field called Rating that accepts any decimal value between 0 and 5.
- Build a custom field formatter for decimal fields, which when selected for the display, will show the decimal value (between 0 and 5) as a collection of stars. (Of course quantized at 0.5 stars, as limited by the CSS we chose to implement.)
CSS: http://www.webcodingeasy.com/Webdesign/Display-simple-CSS-star-rating
Drupal8Cards #15 - Dependency Injection Example / Service Container
Objective
We will be trying out an example today, in an attempt to use Dependency Injection by modifying an existing code without changing any functionality.
Exercise
- Download the examples module from https://www.drupal.org/project/examples. It has a bunch of modules but we will be interested in the page_example module only, during the course of this exercise.
- The module has a PageExampleController defined in src/Controller/PageExampleController.php. The simple() method in this controller is responsible for rendering the url “examples/page_example/simple” when the module is enabled.
- Let’s modify this method by adding a line such that a log entry is made whenever this url is opened.
\Drupal::logger('page_example_module')->notice('Simple Page was displayed');
- Now, this is the code we will start with for our exercise.
- Modify the code to use dependency injection to give access to logger.factory service from our controller, which will be used to do the logging, instead of \Drupal::logger.
- The links in additional resources are a great read towards achieving this.
Drupal8Cards #16 - Composer in your module to load PHP libraries
Objective
In this session, we will see how we could leverage composer, and composer-merge-plugin to load PHP libraries / SDKs in our custom modules
Exercise
- Create a custom module.
- Update the module’s composer.json file to include this library https://packagist.org/packages/guhelski/forecastphp
- Install
wikimedia/composer-merge-plugin
. Runcomposer update
in root such that the mentioned library is fetched to the vendor folder and autoloaded and hence is available for use in your module. - Build a custom block with a configuration form that takes latitude and longitude in the configuration form.
- The block, when enabled should show the forecast for the configured location by a simple text as "Forecast is XXXXX with a temperature of XXX deg C". This forecast information is retrieved using the Forecast wrapper library that we included.
- API Key you could use =
7411b0e6d5e0c99fbd7405fd6de00cd5
(Alternatively, you could register on forecast.io for the key).
Drupal8Cards #17 - Events and Subscriber
Objective
In this session, we will take a look into the Events and Subscribers which is a mechanism very similar to Drupal’s hook system which allows one component of code to be triggered when something else is triggered.
Exercise
- Modify the page_example module such that whenever the “examples/page_example/simple” page is loaded, an event “simple_page_load” is dispatched.
- In your custom module, subscribe to the earlier event. Implement some custom code in your subscriber (Say make an entry to database logging under “Simple Page” type with the message “Simple Page Loaded”).
Drupal8Cards #18 - Twig Templating
Objective
In this session, we will take a look at the basics of Twig Templating, which has replaced the PHPTemplate engine in Drupal.
Exercise
- Download and install this module. This module provides a very basic block whose template is "day19/templates/day19‐twig‐test.html.twig". The build() of the block provides variables "var1, var2, classes, myclasscount" that are available in the template to be used.
- Place the block provided by the module ("My Block") onto a region on your site from the block admin interface, so you can view the block.
- If you see the block display "Your template goes here.." you are all set now. Go further.
- Now modify the template as below
- If "var1" is set, print the value of "var1".
- Move the output of "var1" to a "" whose class names are those provided by "classes" variable passed to the template (Hint: Ensure that the class names are cleaned enough so they deserve to be class names).
- Print the variable "$var2[3][‘g’]".
- Print the word "Hello", such that it can be translated using the admin translation interface.
- Move the "Hello" string into a "" such that the div has all classes in the pattern "minion0, minion1, minion2, minion3, minion4.....till minionX", where "X" is provided by the value of "myclasscount" variable.
- Try out "{{ dump() }}" and "{{ dump(var1) }}" on the template to see how the printed variables show up on the screen.
- With the above changes, the markup of the rendered block is expected to be something like this.
Bonus Exercise
- The provided solution has a bug wherein the classes added to the span enclosing "var1", are also added as classes to the div enclosing the translatable "Hello" String. Fix the template.
Drupal8Cards #20 - Replacing hook_init
Objective
Although doing stuff in hook_init is avoided as there is always a better way of doing the same thing elsewhere. We have taken a look at the event subscriber system on Day 18. We will be extending the same to hook into the page response to do something before every response is rendered, just as you did with hook_init().
Exercise
- Build a custom module such that the header
Access-Control-Allow-Origin: *
is added to the page response only for Anonymous users.
Comments
Post a Comment