<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ivki</id>
	<title>MoodleDocs - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ivki"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Ivki"/>
	<updated>2026-04-26T15:41:59Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Blocks_Advanced&amp;diff=42130</id>
		<title>Blocks Advanced</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Blocks_Advanced&amp;diff=42130"/>
		<updated>2013-08-19T20:47:46Z</updated>

		<summary type="html">&lt;p&gt;Ivki: /* Adding forms */ Added missing semi-colon&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.0}}&lt;br /&gt;
=Introduction=&lt;br /&gt;
This is a continuation of the [[Blocks| simpleHTML block example]].&lt;br /&gt;
&lt;br /&gt;
=Adding forms=&lt;br /&gt;
The next thing that we want to do is add a form to create a simpleHTML page.&lt;br /&gt;
&lt;br /&gt;
We are going to create two pages - view.php and simplehtml_form.php &lt;br /&gt;
All of our logic will be contained in view.php and simplehtml_form.php will just display the form elements.&lt;br /&gt;
&lt;br /&gt;
Create a new file in the blocks/simplehtml directory called simplehtml_form.php. Add the following code:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&amp;quot;{$CFG-&amp;gt;libdir}/formslib.php&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
class simplehtml_form extends moodleform {&lt;br /&gt;
    &lt;br /&gt;
    function definition() {&lt;br /&gt;
        &lt;br /&gt;
        $mform =&amp;amp; $this-&amp;gt;_form;&lt;br /&gt;
        $mform-&amp;gt;addElement(&#039;header&#039;,&#039;displayinfo&#039;, get_string(&#039;textfields&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Now let&#039;s create view.php.&lt;br /&gt;
&lt;br /&gt;
Create a new file in the blocks/simplehtml directory called view.php. In this file add the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
require_once(&#039;simplehtml_form.php&#039;);&lt;br /&gt;
&lt;br /&gt;
global $DB;&lt;br /&gt;
&lt;br /&gt;
// Check for all required variables.&lt;br /&gt;
$courseid = required_param(&#039;courseid&#039;, PARAM_INT);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039; =&amp;gt; $courseid))) {&lt;br /&gt;
    print_error(&#039;invalidcourse&#039;, &#039;block_simplehtml&#039;, $courseid);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
require_login($course);&lt;br /&gt;
&lt;br /&gt;
$simplehtml = new simplehtml_form();&lt;br /&gt;
&lt;br /&gt;
$simplehtml-&amp;gt;display();&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Next we will add a link from our block to this page so that we can see what we have created.&lt;br /&gt;
&lt;br /&gt;
In the get_content() method of our block_simplehtml class replace&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;content-&amp;gt;footer = &#039;Footer here...&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
with&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
global $COURSE;&lt;br /&gt;
&lt;br /&gt;
// The other code.&lt;br /&gt;
&lt;br /&gt;
$url = new moodle_url(&#039;/blocks/simplehtml/view.php&#039;, array(&#039;blockid&#039; =&amp;gt; $this-&amp;gt;instance-&amp;gt;id, &#039;courseid&#039; =&amp;gt; $COURSE-&amp;gt;id));&lt;br /&gt;
$this-&amp;gt;content-&amp;gt;footer = html_writer::link($url, get_string(&#039;addpage&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Add a Header==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the global declaration:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
global $DB, $OUTPUT, $PAGE;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
After require_login($course);&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$PAGE-&amp;gt;set_url(&#039;/blocks/simplehtml/view.php&#039;, array(&#039;id&#039; =&amp;gt; $courseid));&lt;br /&gt;
$PAGE-&amp;gt;set_pagelayout(&#039;standard&#039;);&lt;br /&gt;
$PAGE-&amp;gt;set_heading(get_string(&#039;edithtml&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
One last lot of code to add. The following lines should be added after $simplehtml = new simplehtml_form();&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
echo $OUTPUT-&amp;gt;header();&lt;br /&gt;
$simplehtml-&amp;gt;display();&lt;br /&gt;
echo $OUTPUT-&amp;gt;footer();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Navigation breadcrumbs===&lt;br /&gt;
To really make this look like it&#039;s a part of moodle we will add the navigation breadcrumbs to the header of our page.&lt;br /&gt;
&lt;br /&gt;
Add the following after $courseid = required_param(&#039;courseid&#039;, PARAM_INT);&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$blockid = required_param(&#039;blockid&#039;, PARAM_INT);&lt;br /&gt;
&lt;br /&gt;
// Next look for optional variables.&lt;br /&gt;
$id = optional_param(&#039;id&#039;, 0, PARAM_INT);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Then add the following after the header code&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$settingsnode = $PAGE-&amp;gt;settingsnav-&amp;gt;add(get_string(&#039;simplehtmlsettings&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
$editurl = new moodle_url(&#039;/blocks/simplehtml/view.php&#039;, array(&#039;id&#039; =&amp;gt; $id, &#039;courseid&#039; =&amp;gt; $courseid, &#039;blockid&#039; =&amp;gt; $blockid));&lt;br /&gt;
$editnode = $settingsnode-&amp;gt;add(get_string(&#039;editpage&#039;, &#039;block_simplehtml&#039;), $editurl);&lt;br /&gt;
$editnode-&amp;gt;make_active();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Don&#039;t forget to include definitions for the new strings that you are creating, into block_simplehtml.php&lt;br /&gt;
&lt;br /&gt;
==Form State Control==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
#to display a form for the first time&lt;br /&gt;
#to process submitted form data&lt;br /&gt;
#the user has canceled the form submission&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if($simplehtml-&amp;gt;is_cancelled()) {&lt;br /&gt;
    // Cancelled forms redirect to the course main page.&lt;br /&gt;
    $courseurl = new moodle_url(&#039;/course/view.php&#039;, array(&#039;id&#039; =&amp;gt; $id));&lt;br /&gt;
    redirect($courseurl);&lt;br /&gt;
} else if ($simplehtml-&amp;gt;get_data()) {&lt;br /&gt;
    // We need to add code to appropriately act on and store the submitted data&lt;br /&gt;
    // but for now we will just redirect back to the course main page.&lt;br /&gt;
    $courseurl = new moodle_url(&#039;/course/view.php&#039;, array(&#039;id&#039; =&amp;gt; $courseid));&lt;br /&gt;
    redirect($courseurl);&lt;br /&gt;
} else {&lt;br /&gt;
    // form didn&#039;t validate or this is the first display&lt;br /&gt;
    $site = get_site();&lt;br /&gt;
    echo $OUTPUT-&amp;gt;header();&lt;br /&gt;
    $simplehtml-&amp;gt;display();&lt;br /&gt;
    echo $OUTPUT-&amp;gt;footer();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Notice that the existing header and form display code have been moved into the third branch of the conditional. Also, there isn&#039;t any code to handle form processing. That code will be added shortly.&lt;br /&gt;
==Final Steps==&lt;br /&gt;
Reviewing the progress so far:&lt;br /&gt;
&lt;br /&gt;
#simplehtml_form.php is created which defines the class used later to display our form.&lt;br /&gt;
#view.php is created which:&lt;br /&gt;
#*loads base moodle API and any necessary third party modules or non-base API files.&lt;br /&gt;
#*loads the necessary course object and globals.&lt;br /&gt;
#*performs necessary access control.&lt;br /&gt;
#*loads our form and branches execution appropriately based on our form state.&lt;br /&gt;
&lt;br /&gt;
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!&lt;br /&gt;
===Add Form Elements===&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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: &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// add group for text areas&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;header&#039;,&#039;displayinfo&#039;, get_string(&#039;textfields&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
        &lt;br /&gt;
// add page titel element.&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;text&#039;, &#039;pagetitle&#039;, get_string(&#039;pagetitle&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
$mform-&amp;gt;addRule(&#039;pagetitle&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
        &lt;br /&gt;
// add display text field&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;htmleditor&#039;, &#039;displaytext&#039;, get_string(&#039;displayedhtml&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
$mform-&amp;gt;setType(&#039;displaytexttext&#039;, PARAM_RAW);&lt;br /&gt;
$mform-&amp;gt;addRule(&#039;displaytext&#039;, null, &#039;required&#039;, null, &#039;client&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
For full details on addElement() review the moodle documentation on addElement. Also review addRule() in moodle&#039;s documentation and the PEAR web site. PEAR is an included form processing library that moodle uses for form processing.&lt;br /&gt;
&lt;br /&gt;
Now add additional form elements to simplehtml_form.php: &lt;br /&gt;
====File Upload====&lt;br /&gt;
Add the file field to the form after the existing elements: &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// add filename selection.&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;filepicker&#039;, &#039;filename&#039;, get_string(&#039;file&#039;), null, array(&#039;accepted_types&#039; =&amp;gt; &#039;*&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
====Fieldset Header====&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// add picture fields grouping&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;header&#039;, &#039;picfield&#039;, get_string(&#039;picturefields&#039;, &#039;block_simplehtml&#039;), null, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
====Yes/No Select====&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// add display picture yes / no option&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;selectyesno&#039;, &#039;displaypicture&#039;, get_string(&#039;displaypicture&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
$mform-&amp;gt;setDefault(&#039;displaypicture&#039;, 1);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
====Radio Select====&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
*It keeps the database free from enum field types by providing data key by integers. This is database engine independent.&lt;br /&gt;
*It makes it easy to add additional options at a later date by changing our function&lt;br /&gt;
*It avoids the use of global variables.&lt;br /&gt;
&lt;br /&gt;
Create a file lib.php and place the following code into it which will define the image options via radio select.&lt;br /&gt;
&amp;lt;code php&amp;gt; &lt;br /&gt;
function block_simplehtml_images() {&lt;br /&gt;
    return array(html_writer::tag(&#039;img&#039;, &#039;&#039;, array(&#039;alt&#039; =&amp;gt; get_string(&#039;red&#039;, &#039;block_simplehtml&#039;), &#039;src&#039; =&amp;gt; &amp;quot;pix/picture0.gif&amp;quot;)),&lt;br /&gt;
                html_writer::tag(&#039;img&#039;, &#039;&#039;, array(&#039;alt&#039; =&amp;gt; get_string(&#039;blue&#039;, &#039;block_simplehtml&#039;), &#039;src&#039; =&amp;gt; &amp;quot;pix/picture1.gif&amp;quot;)),&lt;br /&gt;
                html_writer::tag(&#039;img&#039;, &#039;&#039;, array(&#039;alt&#039; =&amp;gt; get_string(&#039;green&#039;, &#039;block_simplehtml&#039;), &#039;src&#039; =&amp;gt; &amp;quot;pix/picture2.gif&amp;quot;)));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
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(&amp;quot;$CFG-&amp;gt;libdir/formslib.php&amp;quot;); in simplehtml_form.php &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/blocks/simplehtml/lib.php&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
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)&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// add image selector radio buttons&lt;br /&gt;
$images = block_simplehtml_images();&lt;br /&gt;
$radioarray = array();&lt;br /&gt;
for ($i = 0; $i &amp;lt; count($images); $i++) {&lt;br /&gt;
    $radioarray[] =&amp;amp; $mform-&amp;gt;createElement(&#039;radio&#039;, &#039;picture&#039;, &#039;&#039;, $images[$i], $i);&lt;br /&gt;
}&lt;br /&gt;
$mform-&amp;gt;addGroup($radioarray, &#039;radioar&#039;, get_string(&#039;pictureselect&#039;, &#039;block_simplehtml&#039;), array(&#039; &#039;), FALSE);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
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. &lt;br /&gt;
====Alt Text Input====&lt;br /&gt;
Finally, to wrap-up the image display selection, allow the user to choose the alternate text that will be displayed with the selected image. &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// add description field&lt;br /&gt;
$attributes = array(&#039;size&#039; =&amp;gt; &#039;50&#039;, &#039;maxlength&#039; =&amp;gt; &#039;100&#039;);&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;text&#039;, &#039;description&#039;, get_string(&#039;picturedesc&#039;, &#039;block_simplehtml&#039;), $attributes);&lt;br /&gt;
$mform-&amp;gt;setType(&#039;description&#039;, PARAM_TEXT);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
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 &amp;quot;Advanced Options&amp;quot; button appears in the upper right corner of the fieldset. In this example, there is a single element, but later you&#039;ll see an element within a header. Learn more about setAdvanced. The&amp;quot;Show/Hide Advanced&amp;quot; button won&#039;t be displayed until adding action buttons to the form during the next step of this tutorial.&lt;br /&gt;
====Date Time Selector====&lt;br /&gt;
Now add the date field as an optional element:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 // add optional grouping&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;header&#039;, &#039;optional&#039;, get_string(&#039;optional&#039;, &#039;form&#039;), null, false);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 // add date_time selector in optional area&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;date_time_selector&#039;, &#039;displaydate&#039;, get_string(&#039;displaydate&#039;, &#039;block_simplehtml&#039;), array(&#039;optional&#039; =&amp;gt; true));&lt;br /&gt;
$mform-&amp;gt;setAdvanced(&#039;optional&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The above code adds a form header and sets it to hide the date/time selector within the optional (advanced) form controls. &lt;br /&gt;
===Add State Variables and Finalize the Form===&lt;br /&gt;
====Adding Form Buttons====&lt;br /&gt;
Most moodle forms have a basic set of buttons. &amp;quot;Submit&amp;quot; and &amp;quot;Cancel&amp;quot; are added by calling the moodleform member function add_action_buttons(). Add the following at the end of simplehtml_form.php&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;add_action_buttons();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
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. &lt;br /&gt;
====Add State Variables====&lt;br /&gt;
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: &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// hidden elements&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;hidden&#039;, &#039;blockid&#039;);&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;hidden&#039;, &#039;courseid&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
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:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$toform[&#039;blockid&#039;] = $blockid;&lt;br /&gt;
$toform[&#039;courseid&#039;] = $courseid;&lt;br /&gt;
$simplehtml-&amp;gt;set_data($toform);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
===Process Form Data===&lt;br /&gt;
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 :&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
} else if ($fromform = $simplehtml-&amp;gt;get_data()) {&lt;br /&gt;
    // We need to add code to appropriately act on and store the submitted data&lt;br /&gt;
    // but for now we will just redirect back to the course main page.&lt;br /&gt;
    $courseurl = new moodle_url(&#039;/course/view.php&#039;, array(&#039;id&#039; =&amp;gt; $courseid));&lt;br /&gt;
    redirect($courseurl);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Notice that the else if statement has been modified to create the variable $fromform.&lt;br /&gt;
&lt;br /&gt;
For now comment out the redirect and add the following above it.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
print_object($fromform);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
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 &amp;quot;Add Page&amp;quot; link for the block and submit some form data. You should see something similar to: &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
stdClass Object&lt;br /&gt;
(&lt;br /&gt;
    [pagetitle] =&amp;gt; fish&lt;br /&gt;
    [displaytext] =&amp;gt; &amp;lt;p&amp;gt;fish&amp;lt;/p&amp;gt;&lt;br /&gt;
    [filename] =&amp;gt; 687195712&lt;br /&gt;
    [displaypicture] =&amp;gt; 1&lt;br /&gt;
    [picture] =&amp;gt; 1&lt;br /&gt;
    [description] =&amp;gt; ocean blue&lt;br /&gt;
    [displaydate] =&amp;gt; 1333609200&lt;br /&gt;
    [mform_showadvanced_last] =&amp;gt; 1&lt;br /&gt;
    [blockid] =&amp;gt; 114&lt;br /&gt;
    [courseid] =&amp;gt; 1&lt;br /&gt;
    [submitbutton] =&amp;gt; Save changes&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The values in brackets are the keys and the portion after =&amp;gt; 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, &#039;block_simplehtml&#039; 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: &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// We need to add code to appropriately act on and store the submitted data&lt;br /&gt;
if (!$DB-&amp;gt;insert_record(&#039;block_simplehtml&#039;, $fromform)) {&lt;br /&gt;
    print_error(&#039;inserterror&#039;, &#039;block_simplehtml&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
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&#039;t work. Continue on to the next section and create the database before testing this code.&lt;br /&gt;
&lt;br /&gt;
=Creating a Database=&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
First create a folder named &#039;&#039;&#039;db&#039;&#039;&#039; under you main block directory. Next login to Moodle and navigate to the XMLDB editor, located in the &#039;Site administration-&amp;gt;Development-&amp;gt;XMLDB editor&#039;. 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 &#039;&#039;&#039;blocks/simplehtml/db&#039;&#039;&#039; and click on Create. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now add the following fields:&lt;br /&gt;
&lt;br /&gt;
#blockid&lt;br /&gt;
#pagetitle&lt;br /&gt;
#displaytext&lt;br /&gt;
#format&lt;br /&gt;
#filename&lt;br /&gt;
#picture&lt;br /&gt;
#description&lt;br /&gt;
#displaypicture&lt;br /&gt;
#displaydate&lt;br /&gt;
&lt;br /&gt;
==blockid==&lt;br /&gt;
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:&lt;br /&gt;
#Click the &amp;quot;New Field&amp;quot; link&lt;br /&gt;
#Change the Name to blockid&lt;br /&gt;
#Enter a Comment about the field&lt;br /&gt;
#Set the Type to int&lt;br /&gt;
#Enter a Length of 10&lt;br /&gt;
#Set Not Null to not null&lt;br /&gt;
#Set Sequence to No&lt;br /&gt;
#Enter 0 for the Default&lt;br /&gt;
#Click the Change button.&lt;br /&gt;
&lt;br /&gt;
==pagetitle==&lt;br /&gt;
The pagetitle is simply text that will be used for links to this simplehtml page. &#039;&#039;&#039;Using default Moodle Themes, Moodle blocks cannot handle more than 25 characters without wrapping&#039;&#039;&#039;. To add the pagetitle field:&lt;br /&gt;
&lt;br /&gt;
#Click the &amp;quot;New Field&amp;quot; link&lt;br /&gt;
#Change the Name to pagetitle&lt;br /&gt;
#Enter a Comment about the field&lt;br /&gt;
#Set the Type to char&lt;br /&gt;
#Enter a Length of 25&lt;br /&gt;
#Set Not Null to not null&lt;br /&gt;
#Click the Change button.&lt;br /&gt;
&lt;br /&gt;
==display text==&lt;br /&gt;
The displaytext field will be displayed as text on the simplehtml page, potentially as HTML. To add the dispaytext field:&lt;br /&gt;
&lt;br /&gt;
#Click the &amp;quot;New Field&amp;quot; link&lt;br /&gt;
#Change the Name to displaytext&lt;br /&gt;
#Enter a Comment about the field&lt;br /&gt;
#Set the Type to text&lt;br /&gt;
#Set Not Null to not null&lt;br /&gt;
#Click the Change button.&lt;br /&gt;
&lt;br /&gt;
==format==&lt;br /&gt;
The format field will contain the integer value that represents the format the text was entered in. To add the format field:&lt;br /&gt;
&lt;br /&gt;
#Click the &amp;quot;New Field&amp;quot; link&lt;br /&gt;
#Change the Name to format&lt;br /&gt;
#Enter a Comment about the field&lt;br /&gt;
#Set the Type to int&lt;br /&gt;
#Enter a Length of 3&lt;br /&gt;
#Set Not Null to not null&lt;br /&gt;
#Set Sequence to No&lt;br /&gt;
#Enter 0 for the Default&lt;br /&gt;
#Click the Change button.&lt;br /&gt;
&lt;br /&gt;
==filename==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
#Click the &amp;quot;New Field&amp;quot; link&lt;br /&gt;
#Change the Name to filename&lt;br /&gt;
#Enter a Comment about the field&lt;br /&gt;
#Set the Type to char&lt;br /&gt;
#Enter a Length of 255&lt;br /&gt;
#Set Not Null to not null&lt;br /&gt;
#Click the Change button.&lt;br /&gt;
&lt;br /&gt;
==picture==&lt;br /&gt;
The URL for the user&#039;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&#039; 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:&lt;br /&gt;
&lt;br /&gt;
#Click the &amp;quot;New Field&amp;quot; link&lt;br /&gt;
#Change the Name to picture&lt;br /&gt;
#Enter a Comment about the field&lt;br /&gt;
#Set the Type to int&lt;br /&gt;
#Enter a Length of 2&lt;br /&gt;
#Set Not Null to not null&lt;br /&gt;
#Set Sequence to No&lt;br /&gt;
#Enter 0 for the Default&lt;br /&gt;
#Click the Change button.&lt;br /&gt;
&lt;br /&gt;
==description==&lt;br /&gt;
Add the description field that will be displayed on the page. To add the description field:&lt;br /&gt;
&lt;br /&gt;
#Click the &amp;quot;New Field&amp;quot; link&lt;br /&gt;
#Change the Name to description&lt;br /&gt;
#Enter a Comment about the field&lt;br /&gt;
#Set the Type to text&lt;br /&gt;
#Set Not Null to not null&lt;br /&gt;
#Click the Change button.&lt;br /&gt;
&lt;br /&gt;
==displaypicture==&lt;br /&gt;
The displaypicture field will be the &amp;quot;yes&amp;quot; or &amp;quot;no&amp;quot; question on the form. This is best represented as an &#039;int&#039;. To add the displaypicture field:&lt;br /&gt;
&lt;br /&gt;
#Click the &amp;quot;New Field&amp;quot; link&lt;br /&gt;
#Change the Name to displaypicture&lt;br /&gt;
#Enter a Comment about the field&lt;br /&gt;
#Set the Type to int&lt;br /&gt;
#Enter a Length of 1&lt;br /&gt;
#Set Not Null to not null&lt;br /&gt;
#Set Sequence to No&lt;br /&gt;
#Enter 0 for the Default&lt;br /&gt;
#Click the Change button.&lt;br /&gt;
&lt;br /&gt;
==displaydate==&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
#Click the &amp;quot;New Field&amp;quot; link&lt;br /&gt;
#Change the Name to displaydate&lt;br /&gt;
#Enter a Comment about the field&lt;br /&gt;
#Set the Type to int&lt;br /&gt;
#Enter a Length of 10&lt;br /&gt;
#Set Not Null to not null&lt;br /&gt;
#Set Sequence to No&lt;br /&gt;
#Enter 0 for the Default&lt;br /&gt;
#Click the Change button.&lt;br /&gt;
&lt;br /&gt;
Now that the fields have been added to the table the install.xml needs to be saved. Click the &amp;quot;Back&amp;quot; link and the &amp;quot;Back to Main&amp;quot;. Once on the main page click the &amp;quot;Save&amp;quot; link to save the changes to the install.xml. Remember update code wasn&#039;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. &lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
=Refining the User Interface=&lt;br /&gt;
After successfully submitting data to the database via the form it is now time to begin displaying that data so that users can interact with the data and view what has been submitted. Both steps will be contained within simplehtml/block_simplehtml.php. &lt;br /&gt;
&lt;br /&gt;
==Add Links to Each Page of the Block==&lt;br /&gt;
To retrieve the relevant rows we will call $DB-&amp;gt;get_records(), which accepts two parameters::&lt;br /&gt;
#The table name&lt;br /&gt;
#An array with the name of the column or field to be queried and the value of the queried field we want to match.&lt;br /&gt;
&lt;br /&gt;
Add the following code:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
global $COURSE, $DB; //$COURSE should already be present&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
if (!empty($this-&amp;gt;config-&amp;gt;text)) {&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;text = $this-&amp;gt;config-&amp;gt;text;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// This is the new code.&lt;br /&gt;
if ($simplehtmlpages = $DB-&amp;gt;get_records(&#039;block_simplehtml&#039;, array(&#039;blockid&#039; =&amp;gt; $this-&amp;gt;instance-&amp;gt;id))) {&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;text .= html_writer::start_tag(&#039;ul&#039;);&lt;br /&gt;
    foreach ($simplehtmlpages as $simplehtmlpage) {&lt;br /&gt;
        $pageurl = new moodle_url(&#039;/blocks/simplehtml/view.php&#039;, array(&#039;blockid&#039; =&amp;gt; $this-&amp;gt;instance-&amp;gt;id, &#039;courseid&#039; =&amp;gt; $COURSE-&amp;gt;id, &#039;id&#039; =&amp;gt; $simplehtmlpage-&amp;gt;id, &#039;viewpage&#039; =&amp;gt; &#039;1&#039;));&lt;br /&gt;
        $this-&amp;gt;content-&amp;gt;text .= html_writer::start_tag(&#039;li&#039;);&lt;br /&gt;
        $this-&amp;gt;content-&amp;gt;text .= html_writer::link($pageurl, $simplehtmlpage-&amp;gt;pagetitle));&lt;br /&gt;
        $this-&amp;gt;content-&amp;gt;text .= html_writer::end_tag(&#039;li&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;text .= html_writer::end_tag(&#039;ul&#039;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Refactor Display Method==&lt;br /&gt;
To avoid any code duplication and make it easy to reuse this functionality create a function in &#039;&#039;&#039;lib.php&#039;&#039;&#039; to handle the page display. A preloaded simplehtml page is passed in as a single parameter, and an optional parameter will control whether the data is returned or directly printed out. Most Moodle functions that print information can be passed a true value as the last parameter. This is the function&#039;s return value, which tells the function to return the HTML and not print or echo it to the user. For development, set the return value to false so that the data is printed out.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function block_simplehtml_print_page($simplehtml, $return = false) {}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Now consider what the function needs to do in order to display all of the necessary information from our page.&lt;br /&gt;
&lt;br /&gt;
;Page Title:Print this out as a centered header for the HTML PAGE&lt;br /&gt;
&lt;br /&gt;
;Display Text:Print this out in whatever format the user specified, centered in a box on the page&lt;br /&gt;
&lt;br /&gt;
;Filename:Display a link to the file in the course file directory so the user has the option to download it. This will be centered in the same box as the display text.&lt;br /&gt;
&lt;br /&gt;
;Display Picture:Display the picture with the description on the right of the picture in a box if the user has chosen for the picture to display&lt;br /&gt;
&lt;br /&gt;
;Display date:Display the date under the page title in a smaller font&lt;br /&gt;
&lt;br /&gt;
===Add Page Title===&lt;br /&gt;
To display the page title use the $OUTPUT class. Add the following to block_simplehtml_print_page() in lib.php&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
global $OUTPUT, $COURSE;&lt;br /&gt;
$display = $OUTPUT-&amp;gt;heading($simplehtml-&amp;gt;pagetitle);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
After we have displayed the title, let&#039;s add a box to put around the rest of the elements that we will display.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $display .= $OUTPUT-&amp;gt;box_start();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This is the opening tag for the box, we will have to enter similar code later, to encapsulate the elements.&lt;br /&gt;
===Display the Date===&lt;br /&gt;
The requirements for date display call for displaying the date in a smaller font under the page title. Moodle has a userdate() function that has several advantages over PHP&#039;s date() function. It displays the date in the user&#039;s preferred format and adjusts the date for any timezone difference.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if($simplehtml-&amp;gt;displaydate) {&lt;br /&gt;
    $display .= userdate($simplehtml-&amp;gt;displaydate);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Notice that since the user had an option of choosing a date or not that you must check to ensure that it was set before trying to output it. Take a look at the displayed page: click on one of your page links from the block. There&#039;s no output. Add some additional code that handles the value of $return. Add the following at the end of the function definition: &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if($return) {&lt;br /&gt;
    return $display;&lt;br /&gt;
} else {&lt;br /&gt;
    echo $display;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
As mentioned earlier, the requirements for the date field were to be centered under the page title and smaller. This can be controlled with a stylesheet.&lt;br /&gt;
&lt;br /&gt;
First, put a div tag around the date, and give it a class to target with CSS later. Change the date output lines:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$display .= html_writer::start_tag(&#039;div&#039;, array(&#039;class&#039; =&amp;gt; &#039;simplehtml displaydate&#039;));&lt;br /&gt;
$display .= userdate($simplehtml-&amp;gt;displaydate);&lt;br /&gt;
$display .= html_writer::end_tag(&#039;div&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
There are two options for adding the stylesheet:&lt;br /&gt;
&lt;br /&gt;
#Add the CSS to the theme&#039;s CSS files in the theme directory&lt;br /&gt;
#Create a styles.css file in the block and add the CSS there&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Choosing the second option, adding a styles.css file, allows more flexibility and avoids needing to create multiple entries if the site is using more than one theme. Create styles.css and add this CSS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
.simplehtml .displaydate {&lt;br /&gt;
    font-size: .8em;&lt;br /&gt;
    text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
===Display Text===&lt;br /&gt;
Now the display text needs to be added. &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$display .= clean_text($simplehtml-&amp;gt;displaytext);&lt;br /&gt;
&lt;br /&gt;
//close the box&lt;br /&gt;
$display .= $OUTPUT-&amp;gt;box_end();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Display the Picture===&lt;br /&gt;
To selectively display the picture with its description text located underneath it:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if ($simplehtml-&amp;gt;displaypicture) {&lt;br /&gt;
    $display .= $OUTPUT-&amp;gt;box_start();&lt;br /&gt;
    $images = block_simplehtml_images();&lt;br /&gt;
    $display .= $images[$simplehtml-&amp;gt;picture];&lt;br /&gt;
    $display .= html_writer::start_tag(&#039;p&#039;);&lt;br /&gt;
    $display .= clean_text($simplehtml-&amp;gt;description);&lt;br /&gt;
    $display .= html_writer::end_tag(&#039;p&#039;);&lt;br /&gt;
    $display .= $OUTPUT-&amp;gt;box_end();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
===Final Alterations===&lt;br /&gt;
To have this all come together and work we need to make a few alterations to view.php&lt;br /&gt;
First we will add another optional parameter:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$id = optional_param(&#039;id&#039;, 0, PARAM_INT);&lt;br /&gt;
$viewpage = optional_param(&#039;viewpage&#039;, false, PARAM_BOOL);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
And then we check to see which page to display depending on which link was selected.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
echo $OUTPUT-&amp;gt;header();&lt;br /&gt;
if ($viewpage) {&lt;br /&gt;
    $simplehtmlpage = $DB-&amp;gt;get_record(&#039;block_simplehtml&#039;, array(&#039;id&#039; =&amp;gt; $id));&lt;br /&gt;
    block_simplehtml_print_page($simplehtmlpage);&lt;br /&gt;
} else {&lt;br /&gt;
    $simplehtml-&amp;gt;display();&lt;br /&gt;
}&lt;br /&gt;
echo $OUTPUT-&amp;gt;footer();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Try the simpleHTML block out and view the different pages that you have created.&lt;br /&gt;
&lt;br /&gt;
=Add editing capability=&lt;br /&gt;
At the moment we have no way to edit the pages that we have created. Our block really does need a way to edit the existing data. The edit feature will use an image to link to the view.php instead of text. This image will only appear when the instructor turns editing on.&lt;br /&gt;
&lt;br /&gt;
Moodle stores pictures and icons in the pix directory under the base moodle directory. You can also use pictures that are custom to a theme. These are stored within the theme&#039;s pix directory. For this example, use the icons in the pix directory for moodle. The image should be encapsulated in an HTML link to simplehtml.php. The url should pass the block instance id, block id, and course id to simplehtml.php.&lt;br /&gt;
&lt;br /&gt;
Edit the &#039;&#039;&#039;block_simplehtml.php&#039;&#039;&#039; file as follows:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
global $COURSE, $DB, $PAGE; //We are adding $PAGE here&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
// Check to see if we are in editing mode&lt;br /&gt;
$canmanage = $PAGE-&amp;gt;user_is_editing($this-&amp;gt;instance-&amp;gt;id);&lt;br /&gt;
&lt;br /&gt;
if ($simplehtmlpages = $DB-&amp;gt;get_records(&#039;block_simplehtml&#039;, array(&#039;blockid&#039; =&amp;gt; $this-&amp;gt;instance-&amp;gt;id))) {&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;text .= html_writer::start_tag(&#039;ul&#039;);&lt;br /&gt;
    foreach ($simplehtmlpages as $simplehtmlpage) {&lt;br /&gt;
        if ($canmanage) {&lt;br /&gt;
            $pageparam = array(&#039;blockid&#039; =&amp;gt; $this-&amp;gt;instance-&amp;gt;id, &lt;br /&gt;
                  &#039;courseid&#039; =&amp;gt; $COURSE-&amp;gt;id, &lt;br /&gt;
                  &#039;id&#039; =&amp;gt; $simplehtmlpage-&amp;gt;id);&lt;br /&gt;
            $editurl = new moodle_url(&#039;/blocks/simplehtml/view.php&#039;, $pageparam);&lt;br /&gt;
            $editpicurl = new moodle_url(&#039;/pix/t/edit.gif&#039;);&lt;br /&gt;
            $edit = html_writer::link($editurl, html_writer::tag(&#039;img&#039;, &#039;&#039;, array(&#039;src&#039; =&amp;gt; $editpicurl, &#039;alt&#039; =&amp;gt; get_string(&#039;edit&#039;))));&lt;br /&gt;
        } else {&lt;br /&gt;
            $edit = &#039;&#039;;&lt;br /&gt;
        }&lt;br /&gt;
        $pageurl = new moodle_url(&#039;/blocks/simplehtml/view.php&#039;, array(&#039;blockid&#039; =&amp;gt; $this-&amp;gt;instance-&amp;gt;id, &#039;courseid&#039; =&amp;gt; $COURSE-&amp;gt;id, &#039;id&#039; =&amp;gt; $simplehtmlpage-&amp;gt;id, &#039;viewpage&#039; =&amp;gt; true));&lt;br /&gt;
        $this-&amp;gt;content-&amp;gt;text .= html_writer::start_tag(&#039;li&#039;);&lt;br /&gt;
        $this-&amp;gt;content-&amp;gt;text .= html_writer::link($pageurl, $simplehtmlpage-&amp;gt;pagetitle);&lt;br /&gt;
        $this-&amp;gt;content-&amp;gt;text .= $edit;&lt;br /&gt;
        $this-&amp;gt;content-&amp;gt;text .= html_writer::end_tag(&#039;li&#039;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Notice that there&#039;s a link to the same file view.php that handled the page adding. Make a few adjustments to view.php so that pages can also be updated.&lt;br /&gt;
&lt;br /&gt;
First, modify the form to have a new hidden field called id to store the id of the record in the database to know which page to update. Add the following to &#039;&#039;&#039;simplehtml_form.php&#039;&#039;&#039; :&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$mform-&amp;gt;addElement(&#039;hidden&#039;,&#039;id&#039;,&#039;0&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Second, we alter the way the submit is handled in &#039;&#039;&#039;view.php&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
$toform[&#039;blockid&#039;] = $blockid;&lt;br /&gt;
$toform[&#039;courseid&#039;] = $courseid;&lt;br /&gt;
$toform[&#039;id&#039;] = $id;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
// We need to add code to appropriately act on and store the submitted data&lt;br /&gt;
if ($fromform-&amp;gt;id != 0) {&lt;br /&gt;
    if (!$DB-&amp;gt;update_record(&#039;block_simplehtml&#039;, $fromform)) {&lt;br /&gt;
        print_error(&#039;updateerror&#039;, &#039;block_simplehtml&#039;);&lt;br /&gt;
    }&lt;br /&gt;
} else {&lt;br /&gt;
    if (!$DB-&amp;gt;insert_record(&#039;block_simplehtml&#039;, $fromform)) {&lt;br /&gt;
        print_error(&#039;inserterror&#039;, &#039;block_simplehtml&#039;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
// form didn&#039;t validate or this is the first display&lt;br /&gt;
$site = get_site();&lt;br /&gt;
echo $OUTPUT-&amp;gt;header();&lt;br /&gt;
if ($id) {&lt;br /&gt;
    $simplehtmlpage = $DB-&amp;gt;get_record(&#039;block_simplehtml&#039;, array(&#039;id&#039; =&amp;gt; $id));&lt;br /&gt;
    if($viewpage) {&lt;br /&gt;
        block_simplehtml_print_page($simplehtmlpage);&lt;br /&gt;
    } else {&lt;br /&gt;
        $simplehtml-&amp;gt;set_data($simplehtmlpage);&lt;br /&gt;
        $simplehtml-&amp;gt;display();&lt;br /&gt;
    }&lt;br /&gt;
} else {&lt;br /&gt;
    $simplehtml-&amp;gt;display();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
=Page Deletion=&lt;br /&gt;
After being able to add a page and edit a page, what else would someone need to do with our html pages? Delete! Deleting is a simple operation; requiring a few simple steps::&lt;br /&gt;
&lt;br /&gt;
#Add a link to a new delete.php file&lt;br /&gt;
#Create the delete.php file&lt;br /&gt;
#Print a verification form to the screen in case the user made a mistake&lt;br /&gt;
#Use delete_record() to delete a record from the simplehtml table given an id and a confirmation.&lt;br /&gt;
==Add a link to delete a simpleHTML page==&lt;br /&gt;
Begin by editing &#039;&#039;&#039;block_simplehtml.php&#039;&#039;&#039; and creating a link just after the edit link.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    //delete&lt;br /&gt;
    $deleteparam = array(&#039;id&#039; =&amp;gt; $simplehtmlpage-&amp;gt;id, &#039;courseid&#039; =&amp;gt; $COURSE-&amp;gt;id);&lt;br /&gt;
    $deleteurl = new moodle_url(&#039;/blocks/simplehtml/delete.php&#039;, $deleteparam);&lt;br /&gt;
    $deletepicurl = new moodle_url(&#039;/pix/t/delete.gif&#039;);&lt;br /&gt;
    $delete = html_writer::link($deleteurl, html_writer::tag(&#039;img&#039;, &#039;&#039;, array(&#039;src&#039; =&amp;gt; $deletepicurl, &#039;alt&#039; =&amp;gt; get_string(&#039;delete&#039;))));&lt;br /&gt;
} else {&lt;br /&gt;
    $edit = &#039;&#039;;&lt;br /&gt;
    $delete = &#039;&#039;;&lt;br /&gt;
}&lt;br /&gt;
$pageurl = new moodle_url(&#039;/blocks/simplehtml/view.php&#039;, array(&#039;blockid&#039; =&amp;gt; $this-&amp;gt;instance-&amp;gt;id, &#039;courseid&#039; =&amp;gt; $COURSE-&amp;gt;id, &#039;id&#039; =&amp;gt; $simplehtmlpage-&amp;gt;id, &#039;viewpage&#039; =&amp;gt; true));&lt;br /&gt;
$this-&amp;gt;content-&amp;gt;text .= html_writer::start_tag(&#039;li&#039;);&lt;br /&gt;
$this-&amp;gt;content-&amp;gt;text .= html_writer::link($pageurl, $simplehtmlpage-&amp;gt;pagetitle);&lt;br /&gt;
$this-&amp;gt;content-&amp;gt;text .= $edit;&lt;br /&gt;
$this-&amp;gt;content-&amp;gt;text .= $delete;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
==Create delete.php==&lt;br /&gt;
Refresh the course page and you should now see a black X icon next to each page after the edit icon (when editing is turned on). The purpose of delete.php is to print out a notice to the user with a verification that the user wants to delete the simplehtml page. The notice will either return the user to the course if they say No, or delete the page and return the user to the course if they say Yes. Moodle has a predefined core function in weblib.php that will create the Yes-No form for you and send the user on to the correct locations based on the answer to the question. The function is called notice_yesno(). Before using this, setup the basic file structure for delete.php (it&#039;s similar to what has been used for most of the other files like view.php and simplehtml.php).&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once(&#039;../../config.php&#039;);&lt;br /&gt;
 &lt;br /&gt;
$courseid = required_param(&#039;courseid&#039;, PARAM_INT);&lt;br /&gt;
$id = optional_param(&#039;id&#039;, 0, PARAM_INT);&lt;br /&gt;
$confirm = optional_param(&#039;confirm&#039;, 0, PARAM_INT);&lt;br /&gt;
 &lt;br /&gt;
if (!$course = $DB-&amp;gt;get_record(&#039;course&#039;, array(&#039;id&#039; =&amp;gt; $courseid))) {&lt;br /&gt;
    print_error(&#039;invalidcourse&#039;, &#039;block_simplehtml&#039;, $courseid);&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
require_login($course);&lt;br /&gt;
 &lt;br /&gt;
if(! $simplehtmlpage = $DB-&amp;gt;get_record(&#039;block_simplehtml&#039;, array(&#039;id&#039; =&amp;gt; $id))) {&lt;br /&gt;
    print_error(&#039;nopage&#039;, &#039;block_simplehtml&#039;, &#039;&#039;, $id);&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
$site = get_site();&lt;br /&gt;
$PAGE-&amp;gt;set_url(&#039;/blocks/simplehtml/view.php&#039;, array(&#039;id&#039; =&amp;gt; $id, &#039;courseid&#039; =&amp;gt; $courseid));&lt;br /&gt;
$heading = $site-&amp;gt;fullname . &#039; :: &#039; . $course-&amp;gt;shortname . &#039; :: &#039; . $simplehtmlpage-&amp;gt;pagetitle;&lt;br /&gt;
$PAGE-&amp;gt;set_heading($heading);&lt;br /&gt;
echo $OUTPUT-&amp;gt;header();&lt;br /&gt;
echo $OUTPUT-&amp;gt;footer();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This common code:&lt;br /&gt;
&lt;br /&gt;
*Checks the courseid corresponds to a valid course&lt;br /&gt;
*Checks that the user is logged in&lt;br /&gt;
*Checks that the simplehtml page id corresponds to an existing page id&lt;br /&gt;
*Prints out the header and footer for the page&lt;br /&gt;
&lt;br /&gt;
Notice that this is similar to what has been used so far, but there another optional parameter &#039;confirm&#039; has been added.&lt;br /&gt;
&lt;br /&gt;
This variable will be set when the user clicks the Yes or No button on the form. This means that a test needs to be added to test for the return value; if it is set then the database record containing the simple page id should be deleted. Add the following code after the all to the $PAGE-&amp;gt;set_heading($heading); function:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!$confirm) {&lt;br /&gt;
    $optionsno = new moodle_url(&#039;/course/view.php&#039;, array(&#039;id&#039; =&amp;gt; $courseid));&lt;br /&gt;
    $optionsyes = new moodle_url(&#039;/blocks/simplehtml/delete.php&#039;, array(&#039;id&#039; =&amp;gt; $id, &#039;courseid&#039; =&amp;gt; $courseid, &#039;confirm&#039; =&amp;gt; 1, &#039;sesskey&#039; =&amp;gt; sesskey()));&lt;br /&gt;
    echo $OUTPUT-&amp;gt;confirm(get_string(&#039;deletepage&#039;, &#039;block_simplehtml&#039;, $simplehtmlpage-&amp;gt;pagetitle), $optionsyes, $optionsno);&lt;br /&gt;
} else {&lt;br /&gt;
    if (confirm_sesskey()) {&lt;br /&gt;
        if (!$DB-&amp;gt;delete_records(&#039;block_simplehtml&#039;, array(&#039;id&#039; =&amp;gt; $id))) {&lt;br /&gt;
            print_error(&#039;deleteerror&#039;, &#039;block_simplehtml&#039;);&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        print_error(&#039;sessionerror&#039;, &#039;block_simplehtml&#039;);&lt;br /&gt;
    }&lt;br /&gt;
    $url = new moodle_url(&#039;/course/view.php&#039;, array(&#039;id&#039; =&amp;gt; $courseid));&lt;br /&gt;
    redirect($url);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In the if statement above, the two variables optionsno and optionsyes are set. These are used to pass variables from the form to get or post when the user selects &amp;quot;yes&amp;quot; or &amp;quot;no.&amp;quot; They are passed to the $OUTPUT-&amp;gt;confirm() function as the third and fourth parameters. If the user clicks &amp;quot;no&amp;quot; they are sent to the course page, which means the courseid needs to be added to the form. If the user clicks &amp;quot;yes&amp;quot; the database record containing the simplehtml page id is deleted and the user is forwarded to the course. The page id, courseid, confirm, and the session key need to be passed to the form. The session key is passed to prevent the possibility of a cross-site scripting attach or users submitting valid form data without using Moodle.&lt;br /&gt;
&lt;br /&gt;
==Final Clean up==&lt;br /&gt;
The block is almost finished! The one thing that has not been done is the cleanup of all data associated with the block on deletion. This is accomplished by adding a function named instance_delete() to &#039;&#039;&#039;block_simplehtml.php&#039;&#039;&#039;. In this function call delete records uses the blockid to pass in the $this-&amp;gt;instance-&amp;gt;id variable. The function looks like this: &lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
public function instance_delete() {&lt;br /&gt;
    global $DB;&lt;br /&gt;
    $DB-&amp;gt;delete_records(&#039;block_simplehtml&#039;, array(&#039;blockid&#039; =&amp;gt; $this-&amp;gt;instance-&amp;gt;id));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
=Defining Roles for our Block=&lt;br /&gt;
We are going to create two capabilities for this block:&lt;br /&gt;
#View simplehtml page(s) which will be block/simplehtml:viewpages&lt;br /&gt;
#Modify/add simplehtml page(s) which will be block/simplehtml:managepages&lt;br /&gt;
We need to create an &#039;&#039;&#039;access.php&#039;&#039;&#039; file in the &#039;&#039;&#039;blocks/simplehtml/db directory&#039;&#039;&#039;. In that file add the simplehtml capability code:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
defined(&#039;MOODLE_INTERNAL&#039;) || die();&lt;br /&gt;
&lt;br /&gt;
$capabilities = array(&lt;br /&gt;
    &lt;br /&gt;
    &#039;block/simplehtml:viewpages&#039; =&amp;gt; array(&lt;br /&gt;
        &lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;read&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;legacy&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;guest&#039; =&amp;gt; CAP_PREVENT,&lt;br /&gt;
            &#039;student&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;teacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;coursecreator&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        )&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    &#039;block/simplehtml:managepages&#039; =&amp;gt; array(&lt;br /&gt;
        &lt;br /&gt;
        &#039;captype&#039; =&amp;gt; &#039;read&#039;,&lt;br /&gt;
        &#039;contextlevel&#039; =&amp;gt; CONTEXT_COURSE,&lt;br /&gt;
        &#039;legacy&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;guest&#039; =&amp;gt; CAP_PREVENT,&lt;br /&gt;
            &#039;student&#039; =&amp;gt; CAP_PREVENT,&lt;br /&gt;
            &#039;teacher&#039; =&amp;gt; CAP_PREVENT,&lt;br /&gt;
            &#039;editingteacher&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;coursecreator&#039; =&amp;gt; CAP_ALLOW,&lt;br /&gt;
            &#039;manager&#039; =&amp;gt; CAP_ALLOW&lt;br /&gt;
        )&lt;br /&gt;
    )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Now bump the version number up in &#039;&#039;&#039;blocks/simplehtml/version.php&#039;&#039;&#039;. Increment the last digit of $plugin-&amp;gt;version.&lt;br /&gt;
&lt;br /&gt;
Next go to the notifications link in the Site Administration block. This should update the simplehtml block. Verify that capabilities have been added by going to Users &amp;gt; Permissions &amp;gt; Define roles and selecting Manager. Search for simplehtml. &lt;br /&gt;
&lt;br /&gt;
What does the simplehtml:viewpages mean? The presence of a string surrounded by double square brackets implies that there is a string referenced in code that has not been defined in an appropriate language file. Add the following to &#039;&#039;&#039;lang/en/block_simplehtml.php&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;simplehtml:viewpages&#039;] = &#039;View Simple HTML Pages&#039;;&lt;br /&gt;
$string[&#039;simplehtml:managepages&#039;] = &#039;Manage Simple HTML Pages&#039;; &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
==Add check to the block for the capability==&lt;br /&gt;
With the two new capabilities created, it&#039;s time to use them and add a link to the form in the block. The link to the creation page is in the footer, so it&#039;s critical that the person viewing this link has the capability to manage a simplehtml page. Modify the get_content() function in blocks/simplehtml/block_simplehtml.php to check for the correct capabilities.To check for the capabilities, use the has_capability() function found in lib/access.php. Alter &#039;&#039;&#039;block_simplehtml.php&#039;&#039;&#039; to include checks for these capabilities.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$context = context_course::instance($COURSE-&amp;gt;id);&lt;br /&gt;
&lt;br /&gt;
if (has_capability(&#039;block/simplehtml:managepages&#039;, $context)) {&lt;br /&gt;
    $url = new moodle_url(&#039;/blocks/simplehtml/view.php&#039;, array(&#039;blockid&#039; =&amp;gt; $this-&amp;gt;instance-&amp;gt;id, &#039;courseid&#039; =&amp;gt; $COURSE-&amp;gt;id));&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;footer = html_writer::link($url, get_string(&#039;addpage&#039;, &#039;block_simplehtml&#039;));&lt;br /&gt;
} else {&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;footer = &#039;&#039;;&lt;br /&gt;
}&lt;br /&gt;
        &lt;br /&gt;
// Check to see if we are in editing mode and that we can manage pages.&lt;br /&gt;
$canmanage = has_capability(&#039;block/simplehtml:managepages&#039;, $context) &amp;amp;&amp;amp; $PAGE-&amp;gt;user_is_editing($this-&amp;gt;instance-&amp;gt;id);&lt;br /&gt;
$canview = has_capability(&#039;block/simplehtml:viewpages&#039;, $context);&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
if ($canview) {&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;text .= html_writer::link($pageurl, $simplehtmlpage-&amp;gt;pagetitle);&lt;br /&gt;
} else {&lt;br /&gt;
    $this-&amp;gt;content-&amp;gt;text .= html_writer::tag(&#039;div&#039;, $simplehtmlpage-&amp;gt;pagetitle);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Refresh the Moodle course to which you have added the simplehtml block. As an administrator or teacher you should see the &#039;addpage&#039; link; as a student you should not see the link. If you login as a guest you should also not that you can no longer view the pages.&lt;br /&gt;
&lt;br /&gt;
==Add Role to the simplehtml Form==&lt;br /&gt;
Currently any logged-in user can use the simplehtml form. In development this is not as big of a concern, but before moving into production always ensure that users have access to only those portions of the application that they should. Add the following line in &#039;&#039;&#039;view.php&#039;&#039;&#039; after &amp;lt;tt&amp;gt;require_login($course);&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_capability(&#039;block/simplehtml:managepages&#039;, context_course::instance($courseid));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This ensures the user cannot access this page without having the capability &#039;block/simplehtml:managepages&#039;.&lt;br /&gt;
&lt;br /&gt;
==Add Role to Delete==&lt;br /&gt;
To restrict deletion to those who have the managepages capability, add the following line to delete.php after require_login($course);&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_capability(&#039;block/simplehtml:managepages&#039;, context_course::instance($courseid));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Ivki</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Git_for_developers&amp;diff=42067</id>
		<title>Git for developers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Git_for_developers&amp;diff=42067"/>
		<updated>2013-08-14T15:12:43Z</updated>

		<summary type="html">&lt;p&gt;Ivki: Fixed broken URL to &amp;quot;Getting git&amp;quot; video&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document is for helping you get started on Moodle development with Git. For further details of Git, see [[:Category:Git]].&lt;br /&gt;
&lt;br /&gt;
== General workflow ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A reasonable knowledge of the Git basics is a good idea before you start to use it for development. If you are new to Git, you are encouraged to go to &#039;See also&#039; for some more general reading.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[image:git-pushpull-model.png|right|thumb|400px|Moodle development workflow with Git]]&lt;br /&gt;
In short, the Moodle development with Git looks like this:&lt;br /&gt;
&lt;br /&gt;
* You as the contributor commit changes into your personal repository at your computer&lt;br /&gt;
* You push the changes into your public repository and publish links to your changes in the Moodle Tracker&lt;br /&gt;
* You may ask for a peer review of your code from another developer (preferred but optional)&lt;br /&gt;
* When you are confident of your code you should submit it for integration (Integration request, also sometimes known as a pull request)&lt;br /&gt;
* Moodle integrators pull the changes from your public repository and if they like them, they put them into Moodle integration repository&lt;br /&gt;
* The integrated change is tested and finally pushed into Moodle production repository&lt;br /&gt;
* You update your local repository with all changes from the production repository and the next cycle may start again&lt;br /&gt;
&lt;br /&gt;
This workflow runs in roughly weekly cycles. The integration happens on Monday and the testing on Tuesday. On Wednesday, the production repository moodle.git is usually updated with changes from the last development week.&lt;br /&gt;
&lt;br /&gt;
Most Moodle developers have their public repositories hosted at [http://github.com/ Github]. Alternatively you may want to try [http://gitorious.org Gitorious] or the legendary [http://repo.or.cz repo.or.cz]. In the examples in this guide we assume you&#039;ll set up your public repository at Github.&lt;br /&gt;
&lt;br /&gt;
If you&#039;d like to be added to the developers group in the tracker (which allows you to assign issues to yourself), please send an email to michaeld@moodle.com with your tracker username and a link to an issue where you have contributed a patch.&lt;br /&gt;
&lt;br /&gt;
== Installing Git on your computer ==&lt;br /&gt;
&lt;br /&gt;
Install Git on your computer. Most Linux distributions have Git available as a package to install. If you are on Mac, [http://code.google.com/p/git-osx-installer/ git-osx-installer] installs it in a few clicks.&lt;br /&gt;
&lt;br /&gt;
Immediately after the installation, set your name and contact e-mail. The name and e-mail will become part of your commits and they can&#039;t be changed later once your commits are accepted into the Moodle code. Therefore we ask contributors to use their real names written in capital letters, eg &amp;quot;John Smith&amp;quot; and not &amp;quot;john smith&amp;quot; or even &amp;quot;john5677&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
    git config --global user.name &amp;quot;Your Name&amp;quot;&lt;br /&gt;
    git config --global user.email yourmail@domain.tld&lt;br /&gt;
&lt;br /&gt;
Unless you are the repository maintainer, it is wise to set your Git to not push changes in file permissions:&lt;br /&gt;
&lt;br /&gt;
    git config --global core.filemode false&lt;br /&gt;
&lt;br /&gt;
== Setting-up the public repository ==&lt;br /&gt;
&lt;br /&gt;
1. Go to [http://github.com/ Github] and create an account.&lt;br /&gt;
&lt;br /&gt;
2. Go to the [http://github.com/moodle/moodle official Moodle Github repository] and click on the Fork button. You now have your own Github Moodle repository.&lt;br /&gt;
&lt;br /&gt;
3. Now you need to set up your SSH public key, so you can push to your Github Moodle repository from your local Moodle repository. On Mac you can go on this [http://help.github.com/mac-key-setup/ Github help page]. If you are on another system, go to your Github administration page, to the section SSH Public Keys, and you should see a link to a help page. Done? Good! That was the most difficult part!&lt;br /&gt;
&lt;br /&gt;
== Setting-up the local repository at your computer  ==&lt;br /&gt;
&lt;br /&gt;
Create a local clone repository of your Github repository. In a terminal:&lt;br /&gt;
&lt;br /&gt;
    git clone git://github.com/YOUR_GITHUB_USERNAME/moodle.git LOCALDIR&lt;br /&gt;
&lt;br /&gt;
    (or:  git clone git@github.com:YOUR_GITHUB_USERNAME/moodle.git LOCALDIR)&lt;br /&gt;
&lt;br /&gt;
This command does several jobs for you. It creates a new folder, initializes an empty Git repository in it, sets your Github repository as the remote repository called &#039;origin&#039; and makes a local checkout of the branch &#039;master&#039; from it. The important point to remember now is that your Github repository is aliased as &#039;origin&#039; for your local clone.&lt;br /&gt;
&lt;br /&gt;
Note that the format of the URL here is important. In the first example, the URL starts &amp;quot;git://github.com&amp;quot; and this will give read-only access to the repository at github.com. If you use this URL, the &amp;quot;git push origin&amp;quot; command that appears later in this document will not work. Therefore, if you want to be able to update the &amp;quot;origin&amp;quot; repository, you should use the URL that starts &amp;quot;git@github.com&amp;quot;, i.e. the second of the two &amp;quot;git clone&amp;quot; commands given above. This will give you read and write access to the repository on github.com.&lt;br /&gt;
&lt;br /&gt;
== Keeping your public repository up-to-date ==&lt;br /&gt;
&lt;br /&gt;
[[image:git-sync-github.png|right|thumb|400px|Fetching changes from upstream and pushing them to github]]&lt;br /&gt;
Your fork at Github is not updated automatically. To keep it synced with the upstream Moodle repository, you have to fetch the recent changes from the official moodle.git and push them to your public repository. To avoid problems with this it is strongly recommended that you never modify the standard Moodle branches. &#039;&#039;Remember: never commit directly into master and MOODLE_xx_STABLE branches.&#039;&#039; In other words, always create topic branches to work on. In Gitspeak, the master branch and MOODLE_xx_STABLE branches should be always fast-forwardable.&lt;br /&gt;
&lt;br /&gt;
To keep your public repository up-to-date, we will register remote repository git://git.moodle.org/moodle.git under &#039;upstream&#039; alias. Then we create a script to be run regularly that fetches changes from the upstream repository and pushes them to your public repository. Note that this procedure will not affect your local working directory.&lt;br /&gt;
&lt;br /&gt;
To register the upstream remote:&lt;br /&gt;
&lt;br /&gt;
    cd moodle&lt;br /&gt;
    git remote add upstream git://git.moodle.org/moodle.git&lt;br /&gt;
&lt;br /&gt;
The following commands can be used to keep the standard Moodle branches at your Github repository synced with the upstream repository. You may wish to store them in a script so that you can run it every week after the upstream repository is updated.&lt;br /&gt;
&lt;br /&gt;
    #!/bin/sh&lt;br /&gt;
    git fetch upstream&lt;br /&gt;
    for BRANCH in MOODLE_19_STABLE MOODLE_20_STABLE MOODLE_21_STABLE MOODLE_22_STABLE MOODLE_23_STABLE MOODLE_24_STABLE master; do&lt;br /&gt;
        git push origin refs/remotes/upstream/$BRANCH:$BRANCH&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
&lt;br /&gt;
The git-fetch command does not modify your current working dir (your checkout). It just downloads all recent changes from a remote repository and stores them into so called remote-tracking branches. The git-push command takes these remote-tracking branches from upstream and pushes them to Github under the same name. Understanding this fully requires a bit knowledge of Git internals - see gitrevisions(7) man page.&lt;br /&gt;
&lt;br /&gt;
Note there is no need to switch the local branch during this. You can even execute this via cron at your machine. Just note that the upstream repository updates typically just once a week.&lt;br /&gt;
&lt;br /&gt;
=== New branches ===&lt;br /&gt;
&lt;br /&gt;
Occasionally, moodle.org will create a new branch that does not exist in your public (e.g. Github.com) repository. If you try to push this new branch, you will see an error such as the following:&lt;br /&gt;
&lt;br /&gt;
    error: unable to push to unqualified destination: MOODLE_99_STABLE&lt;br /&gt;
    The destination refspec neither matches an existing ref on the remote&lt;br /&gt;
    nor begins with refs/, and we are unable to guess a prefix based on the source ref.&lt;br /&gt;
    error: failed to push some refs to &#039;git@github.com:YOUR_GITHUB_USERNAME/moodle.git&#039;&lt;br /&gt;
&lt;br /&gt;
In the above example, &amp;quot;MOODLE_99_STABLE&amp;quot;, is the name of the new branch that does not exist in your public repository. To fix the error, you need to create the new branch on your public repository, using the following commands, replacing &amp;quot;MOODLE_99_STABLE&amp;quot; with the name of the new branch you wish to create:&lt;br /&gt;
&lt;br /&gt;
    git checkout MOODLE_99_STABLE&lt;br /&gt;
    git push origin MOODLE_99_STABLE:MOODLE_99_STABLE&lt;br /&gt;
&lt;br /&gt;
The above code will create a new copy of the &amp;quot;MOODLE_99_STABLE&amp;quot; branch in your local repository. If you do not need to keep a local copy of the new branch - and probably you do not need it, you then can remove it from your local repository as follows:&lt;br /&gt;
&lt;br /&gt;
    git checkout master&lt;br /&gt;
    git branch -D MOODLE_99_STABLE&lt;br /&gt;
&lt;br /&gt;
== Preparing a patch ==&lt;br /&gt;
&lt;br /&gt;
As said earlier at this page, you never work on standard Moodle branches directly. Every time you are going to edit something, switch to a local branch. Fork the local branch off the standard branch you think it should be merged to. So if you are working on a patch for 1.9 or 2.0, fork the branch off MOODLE_19_STABLE or MOODLE_20_STABLE, respectively. Patches for the next [[Moodle versions|major version]] should be based on the master branch.&lt;br /&gt;
&lt;br /&gt;
    git checkout -b MDL-xxxxx-nasty-bug origin/master&lt;br /&gt;
&lt;br /&gt;
Note that if you forget to specify the starting point, the branch is based on the currently checked-out branch. It may not be what you want. It is recommended to always specify the starting point.&lt;br /&gt;
&lt;br /&gt;
To check the current branch, run&lt;br /&gt;
&lt;br /&gt;
    git branch&lt;br /&gt;
&lt;br /&gt;
The current branch is highlighted.&lt;br /&gt;
&lt;br /&gt;
Now go and fix the issue with your favorite IDE. Check the status of the files, view the change to be committed and finally commit the change:&lt;br /&gt;
&lt;br /&gt;
    vim filename.php&lt;br /&gt;
    git status&lt;br /&gt;
    git diff&lt;br /&gt;
    git commit -a&lt;br /&gt;
&lt;br /&gt;
Note that this is safe as the commit is recorded just locally, nothing is sent to any server yet (as it would in CVS). To see history of the commits, use&lt;br /&gt;
&lt;br /&gt;
    git log&lt;br /&gt;
&lt;br /&gt;
Once your local branch contains the change (note that it may consists of several patches) and you are happy with it, publish the branch at your public repository:&lt;br /&gt;
&lt;br /&gt;
    git push MDL-xxxxx-nasty-bug&lt;br /&gt;
&lt;br /&gt;
Because we did not specify explicit remote repository, the &#039;origin&#039; is used. Because we did not specify the branch to push, the Git will use the current branch and push it to the remote repository under the same name (by default, this is a subject of your configuration. See push.default config variable).&lt;br /&gt;
&lt;br /&gt;
Now as your branch is published, you can ask Moodle core developers to review it and eventually integrate it into the standard Moodle repository.&lt;br /&gt;
&lt;br /&gt;
=== Checking if a branch has already been merged ===&lt;br /&gt;
&lt;br /&gt;
After some time contributing to Moodle you would have a lot of branches both in your local repository and in your public repository. To prune their list and delete those that were accepted by upstream, use the following&lt;br /&gt;
&lt;br /&gt;
    git fetch upstream                                      (1)&lt;br /&gt;
    git branch --merged upstream/master                     (2)&lt;br /&gt;
    git branch --merged upstream/MOODLE_20_STABLE           (3)&lt;br /&gt;
&lt;br /&gt;
The command (1) fetches the changes from your upstream repository at git.moodle.org (remember that git-fetch does not modify your working dir so it is safe to run it whenever). Command (2) and (3) print all branches that are merged into the upstream master branch and MOODLE_20_STABLE branch, respectively. To delete these local branches, use&lt;br /&gt;
&lt;br /&gt;
    git branch -d MDL-xxxxx-accepted-branch&lt;br /&gt;
&lt;br /&gt;
The similar approach can be used to check the branches published at your origin repository at github.com&lt;br /&gt;
&lt;br /&gt;
    git fetch origin                                        (1)&lt;br /&gt;
    git fetch upstream&lt;br /&gt;
    git branch -r --merged upstream/master                  (2)&lt;br /&gt;
    git branch -r --merged upstream/MOODLE_20_STABLE        (3)&lt;br /&gt;
&lt;br /&gt;
The command (1) makes sure that you have all your branches from github.com recorded as the remote tracking branch locally. Commands (2) and (3) work the same as in the previous example but they list remote tracking branches only ([http://www.kernel.org/pub/software/scm/git/docs/git-branch.html see -r param]). To delete a branch at github.com, use&lt;br /&gt;
&lt;br /&gt;
    git push origin :MDL-xxxx-branch-to-delete&lt;br /&gt;
&lt;br /&gt;
This syntax may look weird to you. However it is pretty logical. The general syntax of the git-push command is&lt;br /&gt;
&lt;br /&gt;
    git push &amp;lt;repository&amp;gt; &amp;lt;source ref&amp;gt;:&amp;lt;target ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
so deleting a remote branch can be understood as pushing an &amp;quot;empty (null) reference&amp;quot; to it.&lt;br /&gt;
&lt;br /&gt;
== Peer-reviewing someone else&#039;s code ==&lt;br /&gt;
&lt;br /&gt;
To review a branch that someone else pushed into their public repository, you do not need to register a new remote (unless you work with such repository frequently, of course). Let us imagine your friend Alice pushed a work-in-progress branch called &#039;wip-feature&#039; into her Github repository and asked you to review it. You need to know the read-only address of the repository and the name of the branch.&lt;br /&gt;
&lt;br /&gt;
    git fetch git://github.com/alice/moodle.git wip-feature&lt;br /&gt;
&lt;br /&gt;
This will download all required data and will keep the pointer to the tip of the wip-feature branch in a local symbolic reference FETCH_HEAD. To see what&#039;s there on that branch, use&lt;br /&gt;
&lt;br /&gt;
    git log -p FETCH_HEAD&lt;br /&gt;
&lt;br /&gt;
To see how a particular file looks at Alice&#039;s branch&lt;br /&gt;
&lt;br /&gt;
    git show FETCH_HEAD:admin/blocks.php&lt;br /&gt;
&lt;br /&gt;
To create a new local branch called &#039;alice-wip-feature&#039; containing the work by Alice, use&lt;br /&gt;
&lt;br /&gt;
    git checkout -b alice-wip-feature FETCH_HEAD&lt;br /&gt;
&lt;br /&gt;
To merge Alice&#039;s work into your current branch:&lt;br /&gt;
&lt;br /&gt;
    git merge FETCH_HEAD&lt;br /&gt;
&lt;br /&gt;
To see what would be merged into the current branch without actually modifying anything:&lt;br /&gt;
&lt;br /&gt;
    git diff ...FETCH_HEAD&lt;br /&gt;
&lt;br /&gt;
Once you are all set and reviewing code, this [[Peer_reviewing_checklist|checklist]] should prove to be useful.&lt;br /&gt;
&lt;br /&gt;
== Rebasing a branch ==&lt;br /&gt;
&lt;br /&gt;
Rebasing is a process when you cut off the branch from its current start point and transplant it to another point. Let us assume the following history exists:&lt;br /&gt;
&lt;br /&gt;
          A---B---C topic&lt;br /&gt;
         /&lt;br /&gt;
    D---E---F---G master&lt;br /&gt;
&lt;br /&gt;
From this point, the result of the command:&lt;br /&gt;
&lt;br /&gt;
    git rebase master topic&lt;br /&gt;
&lt;br /&gt;
would be:&lt;br /&gt;
&lt;br /&gt;
                  A&#039;--B&#039;--C&#039; topic&lt;br /&gt;
                 /&lt;br /&gt;
    D---E---F---G master&lt;br /&gt;
&lt;br /&gt;
and would end with &#039;topic&#039; being your current branch.&lt;br /&gt;
&lt;br /&gt;
You may be asked to rebase your branch submitted for the integration if the submitted branch was based on an outdated commit. The typical case is if you create a new branch as a fork off the upstream master branch on Tuesday. Then on Wednesday, the upstream master branch grows as all changes from the last integration cycle are merged to it. To make diff easy on Github for next weekly pull request review, you want to rebase your branch against the updated master.&lt;br /&gt;
&lt;br /&gt;
    git rebase master MDL-xxxxx-topic-branch&lt;br /&gt;
&lt;br /&gt;
Note that rebasing effectively rewrites the history of the branch. &#039;&#039;&#039;Do not rebase the branch if there is a chance that somebody has already forked it and based their own branch on it.&#039;&#039;&#039; For this reason, many Git tutorials discourage from rebasing any branch that has been published. However in Moodle, all branches submitted for integration are potential subject of rebase (even though we try to not to do it often) and you should not base your own branches on them.&lt;br /&gt;
&lt;br /&gt;
=== Conflicts during rebase ===&lt;br /&gt;
&lt;br /&gt;
During the rebase procedure, conflicts may appear. git-status commands reports the conflicted files. Explore them carefully and fix them in your editor (like you would do with CVS). Then add the files with &#039;git add&#039; command and continue.&lt;br /&gt;
&lt;br /&gt;
    vim conflicted.php&lt;br /&gt;
    git add conflicted.php&lt;br /&gt;
    git rebase --continue&lt;br /&gt;
&lt;br /&gt;
== Applying changes from one branch to another ==&lt;br /&gt;
&lt;br /&gt;
Most bugs are fixed at a stable branch (like MOODLE_20_STABLE) and the fix must be prepared for other branches, too (like MOODLE_21_STABLE and the main development branch - master). In Moodle, we do not merge stable branches into the master one. So usually the contributor prepares at least two branches - with the fix for the stable branch(es) and with the fix for the master branch.&lt;br /&gt;
&lt;br /&gt;
If you have a patch prepared on a local branch (let us say MDL-xxxx-topic_20_STABLE), it is possible to re-apply it to another branch.&lt;br /&gt;
&lt;br /&gt;
=== Cherry-picking a single commit ===&lt;br /&gt;
&lt;br /&gt;
Let us have two local Git repositories ~/public_html/moodle21 containing local installation of Moodle 2.1 and ~/public_html/moodledev with the local installation of most recent development version of Moodle. They both use your public repository at github.com as the origin. You have a branch in moodle21 called MDL-xxxx-topic_21_STABLE that was forked off MOODLE_21_STABLE. It contains one commit. Now you want to re-apply this commit to a branch MDL-xxxx-topic in moodledev.&lt;br /&gt;
&lt;br /&gt;
    cd ~/public_html/moodledev&lt;br /&gt;
    git checkout -b MDL-xxxx-topic origin/master            (1)&lt;br /&gt;
    git fetch ../moodle21 MDL-xxxx-topic_21_STABLE          (2)&lt;br /&gt;
    git cherry-pick FETCH_HEAD                              (3)&lt;br /&gt;
&lt;br /&gt;
The command (1) creates new local branch forked off the CONTHERE The command (1) fetches all data needed to re-apply the topic branch and stores the pointer to the tip of that branch to FETCH_HEAD symbolic reference. The command (2) picks the tip of the branch (the top-most commit on it) and tries to apply it on the current branch. There is also a variant of the cherry-pick command that supports multiple commits (see its man page for details) but we will use another approach for that situation.&lt;br /&gt;
&lt;br /&gt;
=== Applying a set of patches ===&lt;br /&gt;
&lt;br /&gt;
If the branch MDL-xxxx-topic_21_STABLE from the previous example consists of several commits, it may be easier to use git-format-patch and git-am combo to re-apply the whole set of patches (aka patchset). Firstly you will export all commits from the topic branch to files.&lt;br /&gt;
&lt;br /&gt;
    cd ~/public_html/moodle21&lt;br /&gt;
    mkdir .patches&lt;br /&gt;
    git format-patch -o .patches MOODLE_21_STABLE..MDL-xxxx-topic_21_STABLE         (1)&lt;br /&gt;
&lt;br /&gt;
The command (1) takes all commits from the topic branch that are not in MOODLE_21_STABLE and exports them one by one to the output directory .patches. Look at the generated files. They contain the patch itself (in diff format) and additional information about the commit. You could eg send these files by email to a friend of yours for peer-review. We will use them in another repository.&lt;br /&gt;
&lt;br /&gt;
    cd ~/public_html/moodledev&lt;br /&gt;
    git checkout -b MDL-xxxx-topic origin/master&lt;br /&gt;
    git am -3 ../moodle21/.patches/*                        (1)&lt;br /&gt;
&lt;br /&gt;
The command (1) applies all the files from the .patches directory. When a patch does not apply cleanly, the command tries fall back on 3-way merge (see the -3 parameter). If conflicts occur during the procedure, you can either deal with them and then use `git am --continue` or abort the whole procedure with `git am --abort`.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
; Moodle forum discussions&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=168094 GIT help needed]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=165236 Best way to manage CONTRIB code with GIT]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=167063 Handy Git tip for tracking 3rd-party modules and plugins]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=167730 Moodle Git repositories]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=183409 Git help!! I don&#039;t understand rebase enough...]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=217617 add MOODLE_24_STABLE to github.com repository]&lt;br /&gt;
&lt;br /&gt;
; External resources &lt;br /&gt;
* [http://www.kernel.org/pub/software/scm/git/docs/everyday.html Everyday GIT With 20 Commands Or So]&lt;br /&gt;
* [http://gitref.org/ Git Reference]&lt;br /&gt;
* [http://progit.org/book/ Pro Git book]&lt;br /&gt;
* [http://vimeo.com/14629850 Getting git by Scott Chacon] - an recording of an excellent 1-hour presentation that introducing git, including a simple introduction to what is going on under the hood.&lt;br /&gt;
&lt;br /&gt;
[[Category:Git]]&lt;br /&gt;
&lt;br /&gt;
[[ja:開発者用Git]]&lt;/div&gt;</summary>
		<author><name>Ivki</name></author>
	</entry>
</feed>