Backend (Level 3)

Drupal Onboarding project tasks used for learning

Entity API - Create custom content entity type Reviews

We want to create reviews, but we want to have different fields depending of the type of content we are reviewing (event, location or company). Therefore, we will create a custom entity for reviews. We would like to have all reviews (no matter of which type) to have entity reference (to location, company .. which we are reviewing), user that created it and an overall 1-5 rating. But beside this, we also want to have some additional fields, that the user can add on each review type. For example: companies can have quality of webpage, locations can have parking, facilities etc.

You can create two review types for beginning: Locations review and Company review. Make some fields for each and add a link to each location/company, from where users can add their review (eg. link in sidebar on node display that would say 'Add review').

After that create a block view, that is shown on each location/company and will show review for that node. Also create a list view of all reviews, and the review type as exposed filter, so users can filter out only certain review types.

There is also a nice Entity cheat sheet available, that you can use later on the projects as well:

https://wizzlern.nl/sites/wizzlern.nl/files/artikel/drupal-content-entity-8.0.pdf

Using "#lazy_builder" on custom block

Create a custom block and list all Reviews from current user (Reviews are connected to ticket: 'Entity API - Create custom content entity type Reviews' so if you haven't made this task yet, go on it now).

Now that you created a block, let's configure it in a way that it will be "lazy loaded". First, it would be good if you go through this tutorial:

https://drupalize.me/tutorial/use-lazy-builders-and-placeholders?p=2766

After you're done, place this block to the page sidebar and show it sitewide. If you don't see any visual difference (because there is not much data), add some loop or timeout in the code, so you'll be sure it works and is loaded after the other parts of page was loaded.

Add 'Review summary' field to Review entity and change rating scale

Related to 'Entity API - Create custom content entity type Reviews' task, so make sure you finish that first.

We want to create couple of changes/upgrades to Review entity. First we want to add another field on each review called 'Review summary'. This should be a plain text textarea field. Add this field to field definitions in entity and write an update hook to update this on existing page.

Additionally we want to change the overall rate scale from 1-5 to 1-10. Update the field definition, write an update hook, and also write a post update hook, to update the values. To simplify the task and because we want to keep the integer values we will just multiply the current value with 2: 1->2, 2->4, 3->6, 4->8 and 5->10. Also, write an update in batch, to avoid timeouts on a page with thousands of reviews. Additional information is in a links below. You can also check batch_example sub-module inside of examples module.

More info:

Additional info for batch updates:

Weather forecast on Event page

Create a custom block that will be displayed on event page and will be showing a weather forecast for location that is set on event (city level is enough). To get the weather use https://openweathermap.org/api. We want to show this block only 5 days before the actual event, so we get more precise data.

Since we may wait for a response from API, make sure this block is "lazy loaded".

https://drupalize.me/tutorial/use-lazy-builders-and-placeholders?p=2766

If you don't see any visual difference (because the API is working extremely fast :)), add some loop or timeout in the code, so you'll be sure it works and is loaded after the other parts of page was loaded.

Custom Block visibility plugin

In the task 'Module: Message' you created a block with the recent notifications for a user. When a user disables the notifications we also want to immediately remove this block from user's profile page.

To do that we will create a custom Block visibility plugin. It should be called 'Display only when user has notifications enabled'. Edit the block after you create the plugin, so this block will only visible to users who have notifications enabled on user profile.

https://www.jaypan.com/tutorial/custom-drupal-block-visibility-plugins-and-condition-plugin-api

Create a node with JSON POST request

With this task you'll get familiar with JSON:API module. Module was originally contributed module so you will be able to find it here https://www.drupal.org/project/jsonapi, but as the page says it was added to core so you now have it when you install Drupal already.

The final goal is to create a new company node through JSON POST request using authentication. But before you do that, first get familiar with JSON:API module. Start with retrieving the node data through GET requests, check out how relationships work for entity reference, how you can authenticate and then you'll be ready to create a node. You can use Postman or similar tool to create requests.

There is a great series on Drupalize.me which will guide you through the steps with which you will get familiar with the way things work:

https://drupalize.me/series/web-services-drupal

There is also a whole series on drupal.org:

https://www.drupal.org/docs/core-modules-and-themes/core-modules/jsonapi-module/jsonapi

Suggest Location form

We want to give registered users an option to suggest Location to be added to our platform.

Create a custom form (path /suggest-location), that only registered users will be able to see and submit and which will gather some basic information about the Location. Looking at the Location content type, we will need: Name, Description, Address, Contact email and optionally Website, Phone number and Equipment. Equipment should have options available in Equipment taxonomy. In addition to that, we also want to add: Your name, Your email (should be prefilled from user account, but user can change) and Your connection to the Location. This should be radio buttons with values: I own this Location, I'm working at this location, I only know this place because I visited it before, Other. Last option should give you an additional input field, where user can type custom text. Check a link below for details:

https://www.drupal.org/docs/drupal-apis/form-api/conditional-form-fields

When the form is submitted, a Location node should be generated from the values in the form, but it should be unpublished by default. Additionally an email should be sent to a user or a group of users, that have a role "Suggestions Admin" (if it's not there yet, create it) which will include all the information from the form and the link to the unpublished node, which they can review, edit and publish. Make sure that only users with this role are able to see this node while unpublished.

Unit tests

This task is connected to "Custom block on event pages" task. If you haven't finished that one, do that first.

Using Phpunit, create a unit test to check that the service for getting the number of days until event starts works as expected.

https://www.axelerant.com/resources/team-blog/drupal-8-writing-your-first-unit-test-with-phpunit https://drupalize.me/tutorial/implement-unit-test-drupal?p=3056 https://drupalize.me/tutorial/run-drupal-tests-phpunit?p=3056

After you're done, deliberately make a temporary change in code, that will break the functionality in a way that your test will fail. After it fails, revert the change you've made and run again. The test should now pass.

Additional tests

Create tests for "Configuration form (Site status message module)" task. Write Functional and Behat test, that will test if the configuration form is working correctly.

Create tests that will mock requests to NewsAPI in "Queue API & Cron" task. Also write tests that confirm that news are getting saved and can be retrieved from database.

Create tests for custom entity type 'Review' you have created in task "Entity API - Create custom content entity type Reviews". Write tests that confirm that CRUD operations on this entity are working.

Create tests for service you have created for task "Event adjustment on save". Test for different edge cases (example: event title that only contains words that shouldn't be converted to title case, event title that has numbers...).

Create tests for functionalities that you have implemented for task "Equipment scoring". Write tests that confirm, that the equipment is evaluated correctly.