Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Blocks Advanced: Difference between revisions

From MoodleDocs
No edit summary
No edit summary
Line 298: Line 298:
</code>
</code>
This code checks to see if we are updating or inserting into the database. We have not created the database yet, so this code won't work. Continue on to the next section and create the database before testing this code.
This code checks to see if we are updating or inserting into the database. We have not created the database yet, so this code won't work. Continue on to the next section and create the database before testing this code.
=Creating a Database=
We will be using the XMLDB Editor to design and create the database table that will hold the data from the form that we have just created. We have eight pieces of information to store from the simplehtml form.
First create a folder named '''db''' under you main block directory. Next login to Moodle and navigate to the XMLDB editor, located in the 'Site administration->Development->XMLDB editor'. The XMLDB editor is a graphical interface to help generate the xml files that Moodle uses to create and maintain database tables. When you get to the XMLDB editor you will see all the blocks, modules and other areas that have db directories. Those that show a link already have tables defined that can be loaded and modified. Find the '''blocks/simplehtml/db''' and click on Create.
The db directory has an install.xml file with some basic information about your block and one table called simplehtml. In Moodle you will now see the block/simplehtml/db highlighted in green and the Load and Delete commands will be linked. Click on Load. Now you will see the Edit and Unload text linked. Click on Edit.
The simplehtml table must be modified to include the information entered from the form: click on the Edit link next to the simplehtml table to display the definition that is created by default for the table. Id field will be there and a primary key that links to the id field. Rename the table to block_simplehtml. Alter the comments for this table here as well. Any changes to the comments field requires a click on the Change button for the changes to be recorded.
Now add the following fields:
#blockid
#pagetitle
#displaytext
#format
#filename
#picture
#description
#displaypicture
#displaydate
==blockid==
The blockid is a foreign key that references the block table. This will be used to join our data rows to the block table. The block table houses generic block information for installed block instances. To add the blockid field:
#Click the "New Field" link
#Change the Name to blockid
#Enter a Comment about the field
#Set the Type to int
#Enter a Length of 10
#Set Not Null to not null
#Set Sequence to No
#Enter 0 for the Default
#Click the Change button.
==pagetitle==
The pagetitle is simply text that will be used for links to this simplehtml page. '''Using default Moodle Themes, Moodle blocks cannot handle more than 25 characters without wrapping'''. To add the pagetitle field:
#Click the "New Field" link
#Change the Name to pagetitle
#Enter a Comment about the field
#Set the Type to char
#Enter a Length of 25
#Set Not Null to not null
#Click the Change button.
==display text==
The displaytext field will be displayed as text on the simplehtml page, potentially as HTML. To add the dispaytext field:
#Click the "New Field" link
#Change the Name to displaytext
#Enter a Comment about the field
#Set the Type to text
#Set Not Null to not null
#Click the Change button.
==format==
The format field will contain the integer value that represents the format the text was entered in. To add the format field:
#Click the "New Field" link
#Change the Name to format
#Enter a Comment about the field
#Set the Type to int
#Enter a Length of 3
#Set Not Null to not null
#Set Sequence to No
#Enter 0 for the Default
#Click the Change button.
==filename==
The filename field stores the name of a file the instructor posts on the simplehtml page, which students can then download or view. To add the filename field:
#Click the "New Field" link
#Change the Name to filename
#Enter a Comment about the field
#Set the Type to char
#Enter a Length of 255
#Set Not Null to not null
#Click the Change button.
==picture==
The URL for the user's chosen picture is in a predefined static variable that associates a number to a picture. This will allow the addition of more pictures later if necessary, or for changing the current pictures' URLs without updating the database. Because only the number is stored the database field should be created as an int rather than a char. To add the picture field:
#Click the "New Field" link
#Change the Name to picture
#Enter a Comment about the field
#Set the Type to int
#Enter a Length of 2
#Set Not Null to not null
#Set Sequence to No
#Enter 0 for the Default
#Click the Change button.
==description==
Add the description field that will be displayed on the page. To add the description field:
#Click the "New Field" link
#Change the Name to description
#Enter a Comment about the field
#Set the Type to text
#Set Not Null to not null
#Click the Change button.
==displaypicture==
The displaypicture field will be the "yes" or "no" question on the form. This is best represented as an 'int'. To add the displaypicture field:
#Click the "New Field" link
#Change the Name to displaypicture
#Enter a Comment about the field
#Set the Type to int
#Enter a Length of 1
#Set Not Null to not null
#Set Sequence to No
#Enter 0 for the Default
#Click the Change button.
==displaydate==
The final field to add to the table is the displaydate. It is a UNIX timestamp which is an integer value. To add the displaydate field:
#Click the "New Field" link
#Change the Name to displaydate
#Enter a Comment about the field
#Set the Type to int
#Enter a Length of 10
#Set Not Null to not null
#Set Sequence to No
#Enter 0 for the Default
#Click the Change button.
Now that the fields have been added to the table the install.xml needs to be saved. Click the "Back" link and the "Back to Main". Once on the main page click the "Save" link to save the changes to the install.xml. Remember update code wasn't added to install the database table after the block has already been installed. When developing within a localized environment load the database by uninstalling the module and then reinstalling it. In normal circumstances where the block or module has been in production use you would need to do this with proper update code.
Now you should be able to test your code. You can view the data was stored in the proper table by viewing the table block_simplehtml via phpadmin.

Revision as of 00:37, 10 April 2012

Moodle 2.0


Introduction

This is a continuation of the simpleHTML block example.

Adding forms

The next thing that we want to do is add a form to create a simpleHTML page.

We are going to create two pages - view.php and simplehtml_form.php All of our logic will be contained in view.php and simplehtml_form.php will just display the form elements.

Create a new file in the blocks/simplehtml directory called simplehtml_form.php. Add the following code: require_once("$CFG->libdir/formslib.php");

class simplehtml_form extends moodleform {

   function definition() {
       
       $mform =& $this->_form;
       $mform->addElement('header','displayinfo', get_string('textfields', 'block_simplehtml'));
   }

} Now let's create view.php.

Create a new file in the blocks/simplehtml directory called view.php. In this file add the following code:

<?php

require_once('../../config.php'); require_once('simplehtml_form.php');

global $DB;

// Check for all required variables. $courseid = required_param('courseid', PARAM_INT);


if (!$course = $DB->get_record('course', array('id' => $courseid))) {

   print_error('invalidcourse', 'block_simplehtml', $courseid);

}

require_login($course);

$simplehtml = new simplehtml_form();

$simplehtml->display(); ?> Next we will add a link from our block to this page so that we can see what we have created.

In the get_content() method of our block_simplehtml class replace $this->content->footer = 'Footer here...'; with global $COURSE

// The other code.

$url = new moodle_url('/blocks/simplehtml/view.php', array('blockid' => $this->instance->id, 'courseid' => $COURSE->id)); $this->content->footer = html_writer::link($url, get_string('addpage', 'block_simplehtml'));

Add a Header

If you visit the page now you will see a very basic non-themed form without any of the necessary navigational structure. Note that this happens because the form processing page, in this case view.php, is being accessed directly via the URL and not by being included in another page. This means that the necessary infrastructure must be added directly to the script. Add this by using the print_header function, but a few pieces of data are needed to build appropriate navigation. Make the following adjustments to view.php:


In the global declaration: global $DB, $OUTPUT, $PAGE; After require_login($course); $PAGE->set_url('/blocks/simplehtml/view.php', array('id' => $courseid)); $PAGE->set_pagelayout('standard'); $PAGE->set_heading(get_string('edithtml', 'block_simplehtml')); One last lot of code to add. The following lines should be added after $simplehtml = new simplehtml_form(); echo $OUTPUT->header(); $simplehtml->display(); echo $OUTPUT->footer();

Navigation breadcrumbs

To really make this look like it's a part of moodle we will add the navigation breadcrumbs to the header of our page.

Add the following after $courseid = required_param('courseid', PARAM_INT); $blockid = required_param('blockid', PARAM_INT);

// Next look for optional variables. $id = optional_param('id', 0, PARAM_INT); Then add the following after the header code $settingsnode = $PAGE->settingsnav->add(get_string('simplehtmlsettings', 'block_simplehtml')); $editurl = new moodle_url('/blocks/simplehtml/view.php', array('id' => $id, 'courseid' => $courseid, 'blockid' => $blockid)); $editnode = $settingsnode->add(get_string('editpage', 'block_simplehtml'), $editurl); $editnode->make_active(); Don't forget to include definitions for the new strings that you are creating, into block_simplehtml.php

Form State Control

Now to add some basic form state control: The first step is to setup the appropriate actions based on the form state, accounting for three scenarios:

  1. to display a form for the first time
  2. to process submitted form data
  3. the user has canceled the form submission

To implement these three scenarios adjust the code a bit. The existing form display and header code will be used as the first time display code, and an if statement added after instantiating the simplehtml_form object will handle the logic behind the application flow: if($simplehtml->is_cancelled()) {

   // Cancelled forms redirect to the course main page.
   $courseurl = new moodle_url('/course/view.php', array('id' => $id));
   redirect($courseurl);

} else if ($simplehtml->get_data()) {

   // We need to add code to appropriately act on and store the submitted data
   // but for now we will just redirect back to the course main page.
   $courseurl = new moodle_url('/course/view.php', array('id' => $courseid));
   redirect($courseurl);

} else {

   // form didn't validate or this is the first display
   $site = get_site();
   echo $OUTPUT->header();
   $simplehtml->display();
   echo $OUTPUT->footer();

} Notice that the existing header and form display code have been moved into the third branch of the conditional. Also, there isn't any code to handle form processing. That code will be added shortly.

Final Steps

Reviewing the progress so far:

  1. simplehtml_form.php is created which defines the class used later to display our form.
  2. view.php is created which:
    • loads base moodle API and any necessary third party modules or non-base API files.
    • loads the necessary course object and globals.
    • performs necessary access control.
    • loads our form and branches execution appropriately based on our form state.

So the form class is defined and the form is displayed in a separate file. Adding elements to the form and finishing the processing of our form will wrap it up!

Add Form Elements

Currently there are no form elements which can submit data. Editing the form class definition in simplehtml_form.php will change that by adding a wide set of form elements to the form for demonstrative purposes only. This will give an example of how to add and process various form elements.

To add the link title text field and the displaytext HTML area to the form, paste the following text after the creation of the form object in the simplehtml_form.php file: // add group for text areas $mform->addElement('header','displayinfo', get_string('textfields', 'block_simplehtml'));

// add page titel element. $mform->addElement('text', 'pagetitle', get_string('pagetitle', 'block_simplehtml')); $mform->addRule('pagetitle', null, 'required', null, 'client');

// add display text field $mform->addElement('htmleditor', 'displaytext', get_string('displayedhtml', 'block_simplehtml')); $mform->setType('displaytexttext', PARAM_RAW); $mform->addRule('displaytext', null, 'required', null, 'client'); For full details on addElement() review the moodle documentation on addElement. Also review addRule() in moodle's documentation and the PEAR web site. PEAR is an included form processing library that moodle uses for form processing.

Now add additional form elements to simplehtml_form.php:

File Upload

Add the file field to the form after the existing elements: // add filename selection. $mform->addElement('filepicker', 'filename', get_string('file'), null, array('accpeted_types' => '*')); his field allows the user to choose a file in the course file directory. Notice that the name of the element in the form is the same name as the field in the database. This will make it easy to insert and update the database records later.

Fieldset Header

// add picture fields grouping $mform->addElement('header', 'picfield', get_string('picturefields', 'block_simplehtml'), null, false);

Yes/No Select

// add display picture yes / no option $mform->addElement('selectyesno', 'displaypicture', get_string('displaypicture', 'block_simplehtml')); $mform->setDefault('displaypicture', 1);

Radio Select

To control the available options, create a function that will return the list of available options as an array keyed by an integer. This is preferred for several reasons:

  • It keeps the database free from enum field types by providing data key by integers. This is database engine independent.
  • It makes it easy to add additional options at a later date by changing our function
  • It avoids the use of global variables.

Create a file lib.php and place the following code into it which will define the image options via radio select. function block_simplehtml_images() {

   return array(html_writer::tag('img', , array('alt' => get_string('red', 'block_simplehtml'), 'src' => "pix/picture0.gif")),
               html_writer::tag('img', , array('alt' => get_string('blue', 'block_simplehtml'), 'src' => "pix/picture1.gif")),
               html_writer::tag('img', , array('alt' => get_string('green', 'block_simplehtml'), 'src' => "pix/picture2.gif")));

} Now include the above file in any files that need to use the function, for now this is just simplehtml_form.php. Add the following after require_once("$CFG->libdir/formslib.php"); in simplehtml_form.php require_once($CFG->dirroot.'/blocks/simplehtml/lib.php'); You now need to add some pictures to the pix directory. In this example I have three gif images each a different colour, but you could use any image (small is better). Create a directory called pix in your simplehtml block directory. Now add the radio select to the form definition (simplethml_form.php) // add image selector radio buttons $images = block_simplehtml_images(); $radioarray = array(); for ($i = 0; $i < count($images); $i++) {

   $radioarray[] =& $mform->createElement('radio', 'picture', , $images[$i], $i);

} $mform->addGroup($radioarray, 'radioar', get_string('pictureselect', 'block_simplehtml'), array(' '), FALSE); A group is also added to capture multiple form elements on one line. Another approach would be to just display each radio element on its own line.

Alt Text Input

Finally, to wrap-up the image display selection, allow the user to choose the alternate text that will be displayed with the selected image. // add description field $attributes = array('size' => '50', 'maxlength' => '100'); $mform->addElement('text', 'description', get_string('picturedesc', 'block_simplehtml'), $attributes); $mform->setType('description', PARAM_TEXT); Note that there is an attributes variable added to the text field to limit its size and length. The setAdvanced() function adds advanced options to a form. To use this function pass in the name of the form element, group of elements, or header. The "Advanced Options" button appears in the upper right corner of the fieldset. In this example, there is a single element, but later you'll see an element within a header. Learn more about setAdvanced. The"Show/Hide Advanced" button won't be displayed until adding action buttons to the form during the next step of this tutorial.

Date Time Selector

Now add the date field as an optional element:

// add optional grouping

$mform->addElement('header', 'optional', get_string('optional', 'form'), null, false);

// add date_time selector in optional area

$mform->addElement('date_time_selector', 'displaydate', get_string('displaydate', 'block_simplehtml'), array('optional' => true)); $mform->setAdvanced('optional'); The above code adds a form header and sets it to hide the date/time selector within the optional (advanced) form controls.

Add State Variables and Finalize the Form

Adding Form Buttons

Most moodle forms have a basic set of buttons. "Submit" and "Cancel" are added by calling the moodleform member function add_action_buttons(). Add the following at the end of simplehtml_form.php $this->add_action_buttons(); Notice when calling add_action_buttons(), $this is used rather than $mform because add_action_buttons() is defined in the base class moodleform and would be outside scope for $mform.

Add State Variables

Sometimes forms need to keep track of additional data that is not intended to be visible to users. These fields should be placed in hidden elements. For this form blockid and the courseid are needed. Before the call to add_action_buttons() add: // hidden elements $mform->addElement('hidden', 'blockid'); $mform->addElement('hidden', 'courseid'); These elements will need to be populated by displaying code because these will be passed in via the URL initially. after $simplehtml = new simplehtml_form(); in view.php add: $toform['blockid'] = $blockid; $toform['courseid'] = $courseid; $simplehtml->set_data($toform);

Process Form Data

After creating the form, appropriate code must be added to process the submitted form data. Accomplish this by adding code to view.php. Typically when processing form data it is helpful to remove some of the final processing steps so that your script essentially terminates execution and does not redirect you to the course page or wherever makes sense. This is tremendously helpful while debugging. The processing code will be added to this block of code in view.php : } else if ($fromform = $simplehtml->get_data()) {

   // We need to add code to appropriately act on and store the submitted data
   // but for now we will just redirect back to the course main page.
   $courseurl = new moodle_url('/course/view.php', array('id' => $courseid));
   redirect($courseurl);

Notice that the else if statement has been modified to create the variable $fromform.

For now comment out the redirect and add the following above it. print_object($fromform); print_object() is a useful moodle function which prints out data from mixed data types showing the keys and data for arrays and objects. Now visit the "Add Page" link for the block and submit some form data. You should see something similar to: stdClass Object (

   [pagetitle] => fish

[displaytext] =>

fish

   [filename] => 687195712
   [displaypicture] => 1
   [picture] => 1
   [description] => ocean blue
   [displaydate] => 1333609200
   [mform_showadvanced_last] => 1
   [blockid] => 114
   [courseid] => 1
   [submitbutton] => Save changes

) The values in brackets are the keys and the portion after => is the data for that particular key. Since the form submission is verified as working as expected, save the submitted form data. The most direct way to save is with a call to insert_record(). This function takes the name of the table, 'block_simplehtml' in our case, and the object to be inserted. The object must have keys that map one-to-one with table column names. Choosing form element names that map directly to the database columns saves a bit of code. Save the submitted form data with the following code pasted above the commented out redirect: // We need to add code to appropriately act on and store the submitted data

   if ($fromform->id != 0) {
       if (!$DB->update_record('block_simplehtml', $fromform)) {
           print_error('updateerror', 'block_simplehtml');
       }
   } else {
       if (!$DB->insert_record('block_simplehtml', $fromform)) {
           print_error('inserterror', 'block_simplehtml');
       }
   }

This code checks to see if we are updating or inserting into the database. We have not created the database yet, so this code won't work. Continue on to the next section and create the database before testing this code.

Creating a Database

We will be using the XMLDB Editor to design and create the database table that will hold the data from the form that we have just created. We have eight pieces of information to store from the simplehtml form. First create a folder named db under you main block directory. Next login to Moodle and navigate to the XMLDB editor, located in the 'Site administration->Development->XMLDB editor'. The XMLDB editor is a graphical interface to help generate the xml files that Moodle uses to create and maintain database tables. When you get to the XMLDB editor you will see all the blocks, modules and other areas that have db directories. Those that show a link already have tables defined that can be loaded and modified. Find the blocks/simplehtml/db and click on Create.


The db directory has an install.xml file with some basic information about your block and one table called simplehtml. In Moodle you will now see the block/simplehtml/db highlighted in green and the Load and Delete commands will be linked. Click on Load. Now you will see the Edit and Unload text linked. Click on Edit.


The simplehtml table must be modified to include the information entered from the form: click on the Edit link next to the simplehtml table to display the definition that is created by default for the table. Id field will be there and a primary key that links to the id field. Rename the table to block_simplehtml. Alter the comments for this table here as well. Any changes to the comments field requires a click on the Change button for the changes to be recorded.


Now add the following fields:

  1. blockid
  2. pagetitle
  3. displaytext
  4. format
  5. filename
  6. picture
  7. description
  8. displaypicture
  9. displaydate

blockid

The blockid is a foreign key that references the block table. This will be used to join our data rows to the block table. The block table houses generic block information for installed block instances. To add the blockid field:

  1. Click the "New Field" link
  2. Change the Name to blockid
  3. Enter a Comment about the field
  4. Set the Type to int
  5. Enter a Length of 10
  6. Set Not Null to not null
  7. Set Sequence to No
  8. Enter 0 for the Default
  9. Click the Change button.

pagetitle

The pagetitle is simply text that will be used for links to this simplehtml page. Using default Moodle Themes, Moodle blocks cannot handle more than 25 characters without wrapping. To add the pagetitle field:

  1. Click the "New Field" link
  2. Change the Name to pagetitle
  3. Enter a Comment about the field
  4. Set the Type to char
  5. Enter a Length of 25
  6. Set Not Null to not null
  7. Click the Change button.

display text

The displaytext field will be displayed as text on the simplehtml page, potentially as HTML. To add the dispaytext field:

  1. Click the "New Field" link
  2. Change the Name to displaytext
  3. Enter a Comment about the field
  4. Set the Type to text
  5. Set Not Null to not null
  6. Click the Change button.

format

The format field will contain the integer value that represents the format the text was entered in. To add the format field:

  1. Click the "New Field" link
  2. Change the Name to format
  3. Enter a Comment about the field
  4. Set the Type to int
  5. Enter a Length of 3
  6. Set Not Null to not null
  7. Set Sequence to No
  8. Enter 0 for the Default
  9. Click the Change button.

filename

The filename field stores the name of a file the instructor posts on the simplehtml page, which students can then download or view. To add the filename field:

  1. Click the "New Field" link
  2. Change the Name to filename
  3. Enter a Comment about the field
  4. Set the Type to char
  5. Enter a Length of 255
  6. Set Not Null to not null
  7. Click the Change button.

picture

The URL for the user's chosen picture is in a predefined static variable that associates a number to a picture. This will allow the addition of more pictures later if necessary, or for changing the current pictures' URLs without updating the database. Because only the number is stored the database field should be created as an int rather than a char. To add the picture field:

  1. Click the "New Field" link
  2. Change the Name to picture
  3. Enter a Comment about the field
  4. Set the Type to int
  5. Enter a Length of 2
  6. Set Not Null to not null
  7. Set Sequence to No
  8. Enter 0 for the Default
  9. Click the Change button.

description

Add the description field that will be displayed on the page. To add the description field:

  1. Click the "New Field" link
  2. Change the Name to description
  3. Enter a Comment about the field
  4. Set the Type to text
  5. Set Not Null to not null
  6. Click the Change button.

displaypicture

The displaypicture field will be the "yes" or "no" question on the form. This is best represented as an 'int'. To add the displaypicture field:

  1. Click the "New Field" link
  2. Change the Name to displaypicture
  3. Enter a Comment about the field
  4. Set the Type to int
  5. Enter a Length of 1
  6. Set Not Null to not null
  7. Set Sequence to No
  8. Enter 0 for the Default
  9. Click the Change button.

displaydate

The final field to add to the table is the displaydate. It is a UNIX timestamp which is an integer value. To add the displaydate field:

  1. Click the "New Field" link
  2. Change the Name to displaydate
  3. Enter a Comment about the field
  4. Set the Type to int
  5. Enter a Length of 10
  6. Set Not Null to not null
  7. Set Sequence to No
  8. Enter 0 for the Default
  9. Click the Change button.

Now that the fields have been added to the table the install.xml needs to be saved. Click the "Back" link and the "Back to Main". Once on the main page click the "Save" link to save the changes to the install.xml. Remember update code wasn't added to install the database table after the block has already been installed. When developing within a localized environment load the database by uninstalling the module and then reinstalling it. In normal circumstances where the block or module has been in production use you would need to do this with proper update code. Now you should be able to test your code. You can view the data was stored in the proper table by viewing the table block_simplehtml via phpadmin.