Drupal 7 for Developers
Drupal 7 for Developers
Drupal 7 for Developers Training Materials
Copyright Notice
Copyright © 2004-2023 by NobleProg Limited All rights reserved.
This publication is protected by copyright, and permission must be obtained from the publisher prior to any prohibited reproduction, storage in a retrieval system, or transmission in any form or by any means, electronic, mechanical, photocopying, recording, or likewise.
Introduction ⌘
Why You Should not Develop with Drupal
Developing ⌘
When you start developing with Drupal for the first time, you can get quite irritated.
Especially when you are used to dealing with well documented platforms and environments like Oracle or Visual Studio .NET.
When you don't know something, you simply try to find it in the documentation.
If you can't find something in the documentation, you don't bother and you try to find a way around the problem.
(Not)Developing with Drupal ⌘
This is not the case with Drupal. Documentation is scarce, if it exists at all, and mostly inaccurate.
The easiest way to know how to use Drupal to its full potential is simply to read the code. This is painful and time consuming.
A lot of people simply hack a module or write their own.
Finding solution ⌘
But before you start tinkering with the code, maybe you should think twice.
It isn't a problem to write thousands of lines of code.
The problem is to find a solution to a problem, not to write code.
As developers we tend to think that we are paid for writing code.
But in my experience in business and as a project manager it has taught me something quite different.
Programmers should be paid for solving problems in general, not writing code.
Manager vs Programmer ⌘
We can always argue that the job of the project manager is to be split into various tasks so that programmers don't have to think about the big picture.
But how is possible for project managers to split the tasks if they don't know programming well?
So ironically, there is a huge gap between the project manager and the developers.
We can argue about who is responsible for what, or maybe we can even hire a system architect.
Existing solutions ⌘
Years spent working on software projects has taught me one thing: try to find and learn existing solutions before you write a single line of code.
In one of the companies I used to work for as a project manager we hung sheets of paper all over the office showing the order we should follow when starting to solve a problem.
Solving problem ⌘
It looked like this:
- Check http://drupal.org for existing solutions
- Check the company's repository
- Ask your colleagues!!
- Check the Drupal GIT repository
- Check Google
- If you don't want to do this task, ask if anyone else wants to do it
- Create a sub-module to extend the functionality of an existing module
- Create a patch to modify an existing module
- Write a module from scratch
Code as a last resort ⌘
Of course a developer should only write any code as a last resort!
So, should we hire developers or rather people with good presentation skills who are willing to learn?
Of course the latter seems to be more reasonable, but not necessarily.
Broad thinkers ⌘
Even if a person only
- has to assess the quality of the code,
- export it from the repository,
- apply a patch or write a very small piece of code,
they still
- have to be able to understand the code,
- have to read the code,
- find the problem or assess whether it is worth spending a few seconds more on this problem.
To deal with successful Drupal projects we definitely need broad thinkers who are also able to understand and sometimes write a couple of lines of code.
OOP in Drupal ⌘
Another thing which can irritate you in Drupal 7 is its procedural oriented architecture with a bit of OOP..
I used to spend hours with objects and simply can't think in any different ways now.
Writing a good procedural code is a much harder job than writing good object oriented code.
Some people argue whether Drupal complies to some object oriented standards.
You can find a must-read article about it at https://www.drupal.org/node/547518.
But to be honest, I love object oriented programming and have a real dilemma when I have to give away my object oriented thinking and deal with Drupal 7.
It was painful, I even wanted to give up the project and move to some more "serious" job with Java or C#.
Configuring vs Coding ⌘
One thing which made me decide to play with Drupal for some more time is: I don't have to write any code.
Everything that I want is there! All I have to do is to learn it! Drupal is written in quite a general way.
You have nodes but you can create your own content types like invoices, order forms, etc.
So instead of writing code, you actually spend time on configuring Drupal. Is it worth it?
Coding, testing, bugs ⌘
Of course, writing any code requires testing and bug fixing.
Even if you can write required code quite quickly, you DO NOT know how much time you are going to spend testing and bug fixing.
From my experience, you always spend much more time on analyzing, design, testing and bug fixing than writing code itself.
So, to summarize, Drupal sucks, Drupal is poorly written, not object oriented, but it is there, tried and tested and waiting for you to use it.
Stop developing with Drupal, start to use it.
Analysis, Design and Documentation ⌘
Do not try to create any documentation! It is a waste of time.
Documentation post mortems, especially, are highly dangerous and unhealthy.
Analyzing ⌘
But do analysis.
When you have a problem try to describe it, write use cases, scenarios,UML, pictures, schemas, charts, tables, crayons, paints or whatever may make the problem more understandable to the rest of the team, yourself, and of course the person who - by definition - knows little about requirements: the client.
Client's needs ⌘
When you have information about what the client actually wants, you can think about design and implementation.
This means you can choose some modules or write your own, etc.
The use cases and other documents, like activity diagrams (work flows), class diagrams, state diagrams, etc. should constitute documentation.
Don't try to synchronize it with real applications which, of course, will be totally different. It is a waste of time.
(Not)Creating documentation ⌘
If you really want to create documentation for your modules, here is the proper place with some info http://drupal.org/node/632262
Environment and Deployment ⌘
PHP is a dynamic language. It means it requires a hell of a lot less hustling with compilers, variable declarations, types, etc.
You simply write what you want and it may work or not. The downside of that is of course much worse performance and a lot more errors.
Good IDE (Integrated Development Environment) allows you to avoid most of the errors. Personally, when I see people developing under vim, I feel like during the last 20 years the software industry hasn't moved a bit.
Before you start even installing Drupal, you should think of the whole environment and deploying process.
Repository ⌘
First of all is to choose a repository. The most popular solutions available are: SVN or GIT.
Even if you develop a Drupal application yourself, you should create a repository. Why? Because if you patch something, change any code or even modify configuration files, it is crucial to know what and when it has been changed.
From my experience, putting tests, configuration files and some example database schema into a repository sooner or later pays off.
IDE ⌘
The second issue is good IDE. There are different solutions. I personally use Eclipse with PHPeclipse and I connect through SVN repository by Subclipse plug-in along with svn+ssh protocol.
There are of course different solutions like http://www.eclipse.org/pdt/, but it is just a matter of taste rather than a strategic decision. It is quite easy to switch from one environment to another unless the new one is much worse.
If you are up and running, import your project and try to deploy it. A good environment and deploying procedure saves you a lot of time and frustration.
If you are not familiar with Subversion or git, you may be interested in this courses:
http://www.nobleprog.co.uk/training/subversion+users http://www.nobleprog.co.uk/git/training
Project Managing and Drupal Projects ⌘
Most Drupal companies have never heard about project management.
When I talk about critical paths, tasks, concurrency, Gant charts, etc. They simply have no idea what I am talking about.
Of course it is obvious that in most cases project management is not really necessary.
But if you have more than one developer, or if you have some nasty thing called a deadline, then, you should definitely consider doing some project management work.
Project managing ⌘
The simplest way is to use a spreadsheet like Ex**l or Open Office Calc.
You simply (it is not simple, believe me) split your job into stories and try to estimate the time needed to do it.
After that you may multiply this by 4 or 8, and you end up with an underestimated time which you can submit to your client.
Your client will tell you that it is too long, then you may say it may be done earlier, and you know it is never going to be done on time.
But don't worry, you tried.
Drupal projects ⌘
At the other extreme, I have seen Drupal projects where heavy methodologies like Prince 2 or RUP were in place. Of course they suffocated everything.
In my experience a modified Scrum framework or XP methodology worked perfectly well. We worked with XPlanner and our overall estimations were almost 100% accurate, though single stories or tasks were over- or underestimated significantly.
Drupal project and project_issue modules are not bad solution as well.
Writing Your Own Module ⌘
Unless you want to hack Drupal modules, you have to put your code somewhere. Actually, you don't have much choice. You can only put it in these places:
- Configuration file (yes it works, but don't do it)
- Themes (don't put any logic there)
- Database (some modules allow you to put a code in the setting pages in the admin area - don't do it)
- Your own module
Your own module ⌘
Of course you know that only the last option is - in most cases - the most reasonable solution.
If you are unsure whether the problem is caused by your code, you can uninstall your module, and then you can be 100% sure that the problem lies elsewhere.
Even if you need to tweak your application a tiny bit, you have to write your own module.
How to do it?
"Sloth is a virtue!" Copy any other module and change what you need.
Exercise: Create Own Module ⌘
Copy modules/blog module to sites/all/modules folder and modify it to your needs.
- Name the directory to mymodule.
- Rename blog.module to mymodule.module
- Remove all content from mymodule.module (leave only first line with <?php )
- Rename blog.info to mymodule.info
- Remove rest of the files
- Change entries in mymodule.info as shown below
name = My Module description = My first module package = My Package version = 7.x-dev core = 7.x
- Install the module
Drupal and Onion ⌘
You have probably heard of layer or tiered architecture.
Sometimes you even come across buzz words or acronyms like MVC.
Drupal tends to pretend to comply with some of these standards.
Drupal is mostly written by incredibly ambitious junior programmers, we can see selects in theme layer, some logic in queries or in phptemplate files, as well as logic functions splitting out HTML straight to the theme function or even on the screen.
Levels of Layer ⌘
The main reason we want to split a program into layers is to make code more universal and easier to read.
Lower Layer ⌘
The lower layer should not assume what kind of layer there is above. In other words, we are able to change higher layers without changing anything in the lower one.
For example, we are able to change the theme without modifying a Drupal module. In more advanced models, we use the same code for desktop applications as well as for web applications.
If a logic layer assumed that this application is a web application and printed some HTML code (which, for example Drupal does), we would not be able to create a proper desktop application.
The same with the database. A database layer does not assume that the programming language you are going to use is PHP, Java or any other.
Higher layer ⌘
We cannot say the opposite. The higher level must know something about the lower level.
For example Drupal assumes that a database is MySQL or Postgres.
Or, every theme function assumes a certain type of data is "injected" into a template file.
Good practice shows, that the less dependence between layers, the easier the application is to maintain.
Layers ⌘
- Presentation
- tpl files
- phptemplate_ and theme_ functions
- Logic
- Forms, Views
- Acctual Business Logic
- Data Objects (nodes, users, comments)
- Data Abstraction Layer
- node_load, node_save, user_load, etc...
- db_ functions
- Database
- MySQL, MongoDB, Postgre, etc...
Exercise ⌘
Where would you make changes or write a code in order to achieve the goals below?
- A button should be hidden when a user is logged in
- Swap the right pane column with the left one
- Change an HTML list to an HTML table
- Add an additional field to a form
- Add additional information to a form only if a user is anonymous
- Remove unnecessary descriptions
- Display additional information from a different node on the node view page
- Hide field labels
- Change font size
- Add additional validation to a field
- Add an additional HTML table with some information
What Would You Call a Person Who.. ⌘
..Implements Hooks?
Modifying Nodes (hook_nodeapi_$op)
This hook allows you to modify a node when you view, load, insert or update it. Use Cases
- Adding your own extension to a node (like additional functionality, so you can add it when the node is inserted and remove it when the node is deleted)
- Notifying when an operation happens (like sending email when a node has been modified)
- Counting node views
- Validation, when you want to add additional constraints
Injecting Extra Stuff to a Node Example ⌘
/**
* Implementation of hook_node_view().
*/
function mymodule_node_view($node, $view_mode, $lang) {
if ($node->type == 'page') {
$node->content['extra_stuff']['#markup'] = 'Extra Stuff';
}
}
It will not work with panelized node page!
Changing Form (hook_form_alter) ⌘
This hook allows you to modify any form generated by the Drupal core or a module.
Use Cases
- Hide a field in a form
- Change the label of a field
- Change the size, type or shape of a field
How to find a form id? ⌘
- Find the form on the web page
- Implement a hook_form_alter and display the form_id
function mymodule_form_alter(&$form, &$form_state, $form_id) {
drupal_set_message($form_id);
}
How to display the form structure? ⌘
- Find the form on the web page
- Implement a hook_form_alter and display the $form
function mymodule_form_alter(&$form, $form_state, $form_id) {
if ($form_id == 'user_login_block') {
print_r($form);
}
}
Use Cases
- Creating a page (often containing forms)
- Creating a menu item
- Controlling permission to a page and menu item
The simplest example: ⌘
function mymodule_menu() {
$items['my_first_page1'] = array(
'title' => t('My First Page 1'),
'description' => "My First Page 1 Description.",
'page callback' => 'mymodule_my_first_page',
'access callback' => true,
);
return $items;
}
function mymodule_my_first_page() {
return 'First page';
}
Permissions ⌘
Permissions are implemented via hook_permissions.
/**
* Implementation of hook_menu().
*/
function mymodule_menu() {
$items['my_second_page2'] = array(
'title' => t('My Second Page 2'),
'description' => "My Second Page 2 Description.",
'page callback' => 'mymodule_my_second_page',
'access arguments' => array('view my second page'),
);
return $items;
}
function mymodule_my_second_page() {
return 'Second page';
}
/**
* Implementation of hook_permission().
*/
function mymodule_permission() {
return array(
'view my second page' => array(
'title' => t('View My Second Page'),
'description' => t('Just a sample permission.'),
),
);
}
Exercises ⌘
Exercise 1
- On the user login block
- change the label "Username" to "Login name" (use hook_form_alter)
Exercise 2 Add a shortcut key (e.g. "S") to a submit button to every node.
Exercise 3 Create a page with the text "Hello not so cruel Drupal" and place it under the path "/cruel_drupal" (use hook_menu)
Exercise 4 Add a menu item in the admin menu called "Don't click me" which points to the page created above.
Exercise 5
- Create a permission called "view hello drupal".
- Allow only users with this permission to view a page and menu item created above.
Node that Down ⌘
A node is an abstract concept of data. If you know the object oriented concept, you can think of a node as a top level class.
Almost every other content type inherits from the node. It means that whatever functionality works with nodes will also work with any content type you are going to create.
So, if you are lazy you should definitely take advantage of the benefits of nodes.
For example, if you use nodes instead of your own data type, you don't have to worry about a search mechanism, comments, access controls, workflow, classification or any of the many other things which are already implemented in Drupal.
Not only nodes ⌘
Because of the history of Drupal, not all things in Drupal are nodes. For example, a user is not a node.
Of course you can install a module which creates one node per user (like usernode module) and then you can comment on the user profile, manage profile visibility, etc.
But if a user were a node, everything would be simpler.
From many different reasons, comments which have been implemented in the Drupal core are not nodes.
If you think that your application may become complicated in the future, it might be a good idea to stop using core comment content type and install nodecomment module instead.
Loading and Saving Nodes ⌘
In terms of programming, you can very easily manipulate nodes, no matter how many fields or other things a node contains.
For example, you can load node which id is 123 like this.
$node = node_load(123);
Example with print_r() ⌘
If you print the result (e.g. print_r($node)) it looks like this:
stdClass Object ( [vid] => 1 [uid] => 1 [title] => test [log] => [status] => 1 [comment] => 1 [promote] => 0 [sticky] => 0 [nid] => 1 [type] => page [language] => und [created] => 1298922087 [changed] => 1298922087 [tnid] => 0 [translate] => 0 [revision_timestamp] => 1298922087 [revision_uid] => 1 [body] => Array...
The first thing you may notice is the type of object: stdClass. It is a generic PHP class without any specific type. It is NOT an array!
Saving node ⌘
You can easily modify the node and save it with the node_save statement like this:
$node = node_load(1);
$node->title = "My New Title";
node_save($node);
Finding Nodes ⌘
In this case it doesn't really matter whether we pass the node or the node id.
All of those parameters are interpreted by the node_load function in exactly the same way:
entity_load('node',false,array('nid'=>1));
node_load(1);
Function entity_load() will return ARRAY of objects! Even if we load only one entity.
Searching criteria ⌘
But you can search a node which has a specific title, creation date, type, etc.
$node = entity_load('node',false,array('title'=>'asdf'));
Of course if there is more than one node with the title "asdf" this statement will return only one node.
Drupal does not specify which of the nodes with the same criteria will be returned.
This argument has been removed in Drupal 8 (it's deprecated).
Searching with many criteria ⌘
We can specify as many criteria as we want:
$node = entity_load('node',false,array('title'=>'asdf', 'type' => 'page'));
We should read it like this: find a node with a title "asdf" and of type "page".
More advanced searches ⌘
Please visit:
- https://www.drupal.org/node/1343708
- http://api.drupal.org/api/drupal/includes%21entity.inc/class/EntityFieldQuery/7
Exercise ⌘
Create new items in hook_menu and put code from II.1. and II.2. into separate page call-back functions.
I. SOME MANUAL PREPARATIONS 1. Add fields to the Basic Page content type: - "Do you like it?" (check-box with options: Yes, No) - "Weight of food" (integer) 2. Create 2 pages: banana, radish. 3. Create taxonomy container Foods with terms: Fruit, Vegetable 4. Add field to the article content type: - Kind of food (term reference with kind of food) 5. Create 2 articles about: apple, onion. II. START CODING HERE 1. Load contents of a simple page and article nodes. Use node_load and entity_load with title and type parameters. Apply those changes below: - change the value of check-box to the opposite; - change the values of foods weights; - replace the values of title in a page with article's title and vice versa (in the same time). 2. Load taxonomy term with tid=1 and change it's name to "Obst". Create a menu item with wild-carded tid. Use those functions: - taxonomy_term_load(); - taxonomy_term_save();
Forming Forms ⌘
In Drupal we can distinguish between different type of forms:
- Node submission forms
- Other forms which submit content (user registration, comment submission, etc).
- Forms which manipulate system variables (most forms in admin section)
Form Creation and Submission
All of them, though, are created and rendered in an almost identical way.
Form example in php ⌘
A simple example of a form could look like this:
function mymodule_myform_form() {
//Create a text field
$form['name'] = array(
'#type' => 'textfield',
'#title' => t('Your name'),
'#size' => 20,
'#maxlength' => 20,
'#required' => TRUE,
'#default_value' => 'John Smith',
);
//Create a submit button
$form[] = array(
'#type' => 'submit',
'#value' => t('Submit'),
);
return $form;
}
The mymodule_myform_form() function generates an array with structures described in this document: https://api.drupal.org/api/drupal/developer%21topics%21forms_api_reference.html/7.x
Form example ⌘
Menu hook item for form example ⌘
The first function implements the hook_menu. Let's focus on these two lines:
$items['test_form'] = array (
'title' => 'Test Form',
'page callback' => 'drupal_get_form',
// Name of the function which generates the form
'page arguments' => array('mymodule_myform_form'),
'access callback' => true,
);
When users visit ?q=test_form Drupal invokes the 'drupal_get_form' function.
The argument passed to this function is simply a function name which generates a form.
Form submit for form example ⌘
The last function: mymodule_myform_form_submit processes the form after submission.
function mymodule_myform_form_submit($form, &$form_state){
$welcome_message = "Hello " . $form['name']['#value'] . '!';
drupal_set_message($welcome_message);
// Where sites will be redirected after submission, null = the same page
//$form_state['redirect'] = 'node/1';
}
It is a kind of hook, since Drupal will search for this function automatically.
The proper name for a submission function is a form function name with the "_submit" suffix.
Drupal core form functionality will search for this function automatically.
The first parameter contains form structure and, in the #post element, submitted form values.
The second parameter contains information about form state.
Optionally, you can set redirect field, which contains the path where Drupal will redirect a user after form submission.
Form Validation ⌘
For example if we add age field to our form in function mymodule_myform_form():
//The added field
$form['age'] = array(
'#type' => 'textfield',
'#title' => t('Your age'),
'#required' => false,
);
Function _validate ⌘
Then, we add validation function.
In order to validate a form, we have to create a function with the same name as the function which creates a form and add _validate suffix.
function mymodule_myform_form_validate($form_id, $form_values) {
if($form_values['values']['age'] < 18){
form_set_error(
'error',
t('You are too young and you would cause some minority complex to our staff!')
);
}
}
Validation in different module ⌘
Validation forms generated by different modules example:
function mymodule_form_user_register_form_alter(&$form, &$form_state, $form_id) {
$form['#validate'][] = 'mymodule_validation';
}
function mymodule_validation(&$form, &$form_state) {
if (strlen($form['account']['name']['#value']) < 5) {
form_set_error('name', 'Name must be longer than 5 charaters');
}
}
Related Drupal Documentation ⌘
- http://api.drupal.org/api/file/developer/topics/forms_api_reference.html/7
- https://drupal.org/node/37775
Exercise ⌘
Modify the form above so it should take default value from a paramter in the URL. Example: www.mypage.com/test_form/John%20Mill should use "John Mill" as a default value in the form. Hint, use arg() function.
Presentation layer ⌘
Drupal separates presentation layer from the logic layer.
The content prepared by a module is usually rendered as HTML or XML via theme functions.
Abstracting Themeing From Code ⌘
For example, we can inject data into the theme_table theme function using theme() function.
function mymodule_my_first_themed_page(){
$rows = array(
// Simple row
array(
'Cell 1', 'Cell 2', 'Cell 3'
),
// Row with attributes on the row and some of its cells.
array(
'data' => array('Cell 1',
array('data' => 'Cell 2', 'colspan' => 2)),
'class' => array('funky')
)
);
$header = array('column1','column2','column3');
return theme('table',array('header' => $header,'rows' => $rows));
}
$items['my_first_themed_page1'] = array(
'title' => t('My First Themed Page'),
'description' => "My Fist Themed Page Description.",
'page callback' => 'mymodule_my_first_themed_page',
'access callback' => true,
'type' => MENU_SUGGESTED_ITEM
);
Theme functions ⌘
Theme functions are functions which start with theme_ and can be overridden by the template engine or theme.
For example function theme_table() can be overridden by:
- phptemplate_table
- themename_table.
Please find theme_table function, copy it to template.php, rename it as themename_table and modify it.
See how all tables look like after the modifications.
Exercises ⌘
Try to override other theme functions from includes/theme.inc file.
Registering new themes ⌘
Due to optimization, Drupal requires a developer to register a new theme in a hook_theme().
function mymodule_themed_registered_page() {
$body = "no Body No Crime";
return theme('mymodule_fancy', array('body' => $body));
}
function mymodule_theme($existing, $type, $theme, $path) {
return array(
'mymodule_fancy' => array(
'variables' => array('body' => NULL),
),
);
} // When you copy this code, replace < with '<' etc
function theme_mymodule_fancy($variables){
$o = '<div style="color:red">';
$o .= $variables['body'];
$o .= '</div>';
return $o;
}
$items['themed_registered_page'] = array(
'title' => t('My First Themed Registered Page'),
'description' => "My Fist Themed Registered Page Description.",
'page callback' => 'mymodule_themed_registered_page',
'access callback' => true,
'type' => MENU_SUGGESTED_ITEM
);
Exercise ⌘
Create a theme called theme_divtable which takes raws and header parameters and renders them using div tags (with a table layout but without table tag).
See the details below:
http://training-course-material.com/training/Drupal_7_for_Developers#More_Exercises_.E2.8C.98
Variables ⌘
You can always store certain values within a variable
variable_set('mymodule_vat_rate',0.2);
variable_get('mymodule_vat_rate',0.175);
The second parameter within variable_get function is a default value in case the variable has not been set yet.
Complex data ⌘
You can store complex data in a variable as well.
$rates = array(
'standard_rate' => 0.2,
'reduced_rate' => 0.5
);
variable_set('mymodule_vat_rate', $rates);
variable_get('mymodule_vat_rate', array());
Exercises ⌘
To the test_form example add a code which would save the name in a variable called mymodule_name and once you enter the form again sets it as a default value.
Important additional links ⌘
Some fresh discussion about OOP in drupal:
http://groups.drupal.org/node/230283
Good IDEs:
http://netbeans.org/ http://www.geany.org/ http://www.aptana.com/ http://www.eclipse.org/ https://www.sublimetext.com/ https://www.jetbrains.com/phpstorm/
Miscellaneous:
https://simplytest.me/
More Exercises ⌘
1. In basic page content type create drop down field(select list) with values provided (create one field per one option below):
- manually
- via php code in field configuration
- via function in mymodule
(before you start, make sure you have installed cck module)
2. Prepopulate your mymodule_form with prepopulate module. Do it in:
- browser explorer (in path)
- in mymodule and hook_form_alter
3. Create default view in your module
- create the view manually
- export it
- create new file 'mymodule.views_default.inc'
- in this file insert the code:
function mymodule_views_default_views(){ $export = array(); // ... (here should go exported view code) $export['here_should_go_the_machine_name_of_your_view'] = $view; return $export; }
- add code to mymodule.module:
function mymodule_views_api() { return array( 'api' => 3, ); }
- test it in structure/views
4. Themeing exercise.
Create a theme called 'my_th' and themeing function 'theme_divtable'.
4.1. Copy stark theme (entire catalog) from [your_domain]/themes to [your_domain]/sites/all/themes
4.2. Rename the catalog 'stark' to 'my_th'
4.3. Rename the 'stark.info' file to 'my_th.info' and replace all content in it to:
name = My Th description = My theme package = My Th version = VERSION core = 7.x stylesheets[all][] = layout.css
4.4. Add css code:
/* Theme function with divs. This css code below should be added to layout.css file in the 'my_th' folder: */ .celly { display: table-cell; padding: 5px; }
4.5. In the web browser go to admin/appearance and 'Enable and set default' theme called 'My Th 7.0'.
4.6. Create 'theme_divtable' function which will render the output this way:
- takes 'raws' and 'header' parameters and renders them using div tags (with a table layout but without table tag)
- use the css class from point 4.4.
- use hook_page callback to test it
5. Include translatable string in 'add article' form:
- in php snippet,
- in js(jq) snippet.
6. Webservice exercise 1
Let's say some site keeps web-service with info about food:
- categories of food (taxonomy),
- articles about food (nodes),
- and it's not powered by drupal.
We want to add foods to our site via this web-service.
To simplify and show only how to search content through entity options/attributes:
- suppose that we've already synchronized taxonomy and it keeps info about relation in field 'kind_of_food_ws'
- we will search the exact drupal term id as an argument during creation of new node
- we will use article content type and mock the synchronization of article content from the external site
Find proper taxonomy 'tid' and assign it to the new node(article).
Advanced exercises
(*) 7. Webservice exercise 2
Create webservice which will take all oracle venues and recreate them in drupal structure:
- as taxonomy terms,
- add to term city name and location code as fields.
Use this xml feed: 'education.oracle.co.uk/html/oracle/28US/location.xml'
You can use also those php functions below:
file_get_contents() simplexml_load_string() unset clone
(**) 8. Webservice exercise 3
Create webservice which will take all polish Inland Revenues(IR) and recreate them in drupal structure(as drop-down field in 'Basic Page' content type)
Use this xsd feed: www.finanse.mf.gov.pl/documents/766655/1198699/KodyUrzedowSkarbowych_v3-0.xsd
You can use also those php functions below:
file_get_contents() xml_parser_create() xml_parse_into_struct() transliteration_get() array_combine() xml_parser_free()
(*) 9. Own hook exercise
Create your 2 own hooks (HINT: module_invoke, module_invoke_all, drupal_alter).
- "Create" new hook in your first module.
- Create 2 new modules: mm1, mm2. In both of them implement your new hook.
- Examples
-- hook, which will alter your own form (Alter hook)
-- hook to perform actions during the execution (Intercepting hook)
Even more exercises ⌘
// Exercise1 (no longer public feed, doesn't work..) // ws with oracle locations // get city name and location code from here 'http://education.oracle.co.uk/html/oracle/28US/location.xml' // Exercise2 // Take all polish Inland Revenues (names and codes) from here: // 'http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2018/08/24/eD/DefinicjeTypy/KodyUrzedowSkarbowych_v5-0E.xsd' // try to use function 'simplexml_load_file()' and 'xpath' method // Exercise3 // Get the collection of items from 'https://jsonplaceholder.typicode.com/posts' // try to use function 'drupal_http_request()' // Exercise4 // Post new message here https://jsonplaceholder.typicode.com/posts // Exercise5 // Check if message with user id 2 and message id 12 exists, // if yes, show this text "Msg exists and will be removed" and try to DELETE it. // // Update message 22 from user 3 with PUT // try to use: json_decode(), foreach, echo, if // Exercise6 // try to simplify this code above, use built-in function instead of 'foreach' and create function to reuse it later // Exercise 7 (Catherine) /* ex2 Create array with values provided by your function. Loop through array values with "foreach" and display them each in its own line. Create 3D array in drupal (devel module): -- first level should have title of one basic page in it */
Drupal best practices
Tool, tricks and tips
https://www.drupal.org/node/188989
Coding standards
(https://www.drupal.org/coding-standards)
Best practices
(https://www.drupal.org/developing/best-practices)