development moodle
TRANSCRIPT
Development:Developer documentation(Redirected from Development)
This Developer section of Moodle Docs is aimed at developers who contribute to the
Moodle code, plugins, themes, and so on.
← If you manage a Moodle site, Administrator documentation may suit your
needs better.
← If you teach using Moodle, try Teacher documentation.
Note: New developer documentation pages should be added to the Development
namespace by typing Development: before the new page name i.e.
[[Development:New page name]]. If you are a developer, you probably want to
change your preferences to include the Development namespace in searches.
A page may be added to the Developer category by adding the template
{{CategoryDeveloper}} to the bottom of the page. - If required, you can use
[[Category:Developer|Sort key]] to provide a sort key other than the default page
name.
Contents
[hide]
1 How Moodle development works
2 Guidelines
3 Documentation for core components
← 3.1 Core components that affect everything
← 3.2 Core libraries with a more specific uses
← 3.3 Modules included in the standard distribution
4 How you can contribute
← 4.1 Make a new plugin
← 4.2 Change core code
← 4.3 Ways to contribute that do not involve PHP
programming
5 Plans for the future
6 Resources
7 Tools
← 7.1 IDEs
← 7.2 Browser add-ons
← 7.3 Miscellaneous
8 See also
How Moodle development works
The overview of the Moodle development process explains how Moodle
development occurs and how people become Moodle developers. Current plans are
listed on the Roadmap.
You can also enrol in one of the Moodle Developer Courses.
ConceptsOverview | Unit 1 "To Do" List
Welcome to this Introduction to Moodle Programming course developed and offered at
Humboldt State University!
Since 2004, staff at Humboldt State University have taken a leadership role in the
international community in the support of Moodle. This leadership was recognized by the
Andrew W. Mellon Foundation with a grant to support the development of this course to
further expand our contributions.
What is Moodle? Moodle is software that can be used to produce web-based courses and web
sites to support collaborative projects. It is designed to support a social constructivist model
of education.
There are many ways to customize Moodle--both at a system level and at a course level. The
Moodle interface consists of "sections" and "blocks." The content of "sections" is managed by
the Teacher or course developer by adding text and/or activities."Blocks" are created by
programmers and installed at the system level as options the Teacher can select from to
customize the online classroom. Blocks typically appear in the right and left columns of the
course main page, while sections appear down the center column. Some blocks are a
"standard" part of the Moodle core and others are options available from third parties in the
Moodle community. Examples of standard "blocks" selected to be used in this course include
the "Calendar" and "People."
Moodle's "modules" generally contain the code controlling instructional activities, such as a
quiz or a discussion forum.
Moodle is provided freely as "open source" software. This distribution model has contributed
to Moodle's growing popularity and made it an on-going development project with support
from developers around the world. Because Moodle uses PHP coding, the developer
community is quite large and even small organizations can support it by finding staff with
modest object-oriented programming experience.
This course will guide you to the introductory principles of creating a "block" that can be
added to your own Moodle installation, or--when shared--others' Moodle sites around the
world as an optional enhancement.
Moodle developers have made significant and impressive progress to make Moodle a learning
management system that is widely adopted around the world. One of the critical areas where
it has compared favorably to commercial alternatives is its attention to universal
accessibility. While commercial vendors have been slow to respond to accessibility concerns
raised by users, the open source environment of Moodle allows adaptations to be made more
quickly. Complying with principles of "universal accessibility" ensures that all users,
regardless of their computer input and output devices, have equivalent access. Individuals
with physical disabilities are particularly impacted when they use assistive technologies to
access the World Wide Web. It is imperative that programmers adhere to principles of
accessibility as they create enhancements and modifications to Moodle for their users or the
Moodle community at large so that Moodle adoption and use doesn't fall off due to it failing to
meet accessibility standards. Therefore, in this week's lesson, you'll find an introduction to
web accessibility which will provide the foundation for references to accessibility that occur
throughout this course.
The Moodle community gathers for information exchange at Moodle.org. This first week, as
part of our introductory activities, create an account for yourself at Moodle.org and login to
explore for yourself the wealth of information there.
Use this week to also review fundamentals of SQL and PHP to ready yourself for activities in
the weeks ahead.
Expect to see each unit in this course in the same format:
Overview
"To Do" List summarizing all participant activities for the week, including reading
assignments or supporting web sites to visit
Check the course schedule and course Calendar block for deadlines for assignments.
Be sure to post any questions you have in the "Questions?" forum in the top section of this
course's main page.
"To Do" List
New browser windows open for each external resource.
1. Introduce yourself to other class participants in the designated discussion Forum.
Greet others.
2. Visit Moodle.org. Join the online community by creating a new account for yourself.
Browse the site, including the Moodle Development section and the links in the Main
Menu at the left margin for "Documentation," "Moodle Buzz," and "Issue Tracker."
Take a look at the Tracker and locate an open ticket that interests you.
3. Submit the URL of the open ticket you selected in Bug Tracker in the "Open Ticket"
Assignment area of this course.
4. What exactly is "open source" software? Read The Open Source Definition
(Annotated) from the Open Source Initiative
5. Read Introduction to Web Accessibility from the W3C Web Accessibility Initiative. Be
sure to explore the related comprehensive information on ... Different Disabilities that
Can Affect Web Accessibility.
6. Carefully review the WebAIM Section 508 Checklist. These standards are widely
adopted and significantly enhance accessibility. What is "Section 508?"
"Section 508 (the 1998 Amendment to Section 508 of the [U.S.] Rehabilitation Act)
requires the [U.S.] federal government to make all goods and services—including
Web pages—fully accessible. It identifies specific standards for Internet and Web
accessibility, which are often used as a basis for evaluating whether or not Web sites
meet accessibility requirements." University of Maryland University College
Accessibility in Distance Education Glossary.
7. Review this description of Object-oriented programming from Wikipedia.
8. Read the first six Moodle Coding Guidelines as well as the Coding Style section.
9. Complete the tutorials for PHP (PHP Tutorial - from Refsnes Data) and SQL (SQL
Course - Interactive Online SQL Training for Beginners). If you're already familar with
the basics of PHP and SQL but can use a review to refresh your memory, practice
with these online tutorials. Focus on the PHP Basic list to understand thoroughly, as
well as Include, Sessions, and Date from the PHP Advanced list . Glance through other
PHP Advanced topics also, like Email and File.
10. Review the important terminology included in the Glossary as well as the PHP and
SQL tutorials before taking the quiz.
11. Take the quiz before the deadline noted on the course Calendar (top left corner of the
course main page). Two attempts are allowed.
12. Post your response to the assigned discussion questions as early after beginning Unit
1 as possible. Watch for others' responses and respond to at least two classmates--
beginning with those without replies already.
Unit 2: Creating and Working in the Development Environment
Overview | Unit 2 "To Do" List
External resources open in new browser windows.
In this unit, we will be examining a variety of tools to make the job of creating and editing
Moodle code easier. As with any creative task, having the right tools will make the job easier.
By making the mechanics more transparent, it allows us to focus our thoughts on the creative
process (the actual code we want) instead of fumbling with the process of recording our
thoughts.
There are several developer tools that will be introduced this week along with practice
exercises so you can explore the features of each.
The two browser plug-ins introduced help when creating and debugging browser issues. Both
are invaluable tools to help troubleshooting issues--especially CSS and Javascript problems.
You may be familiar
with other tools that do
similar tasks--please
share those
experiences in the
discussion this week.
Most development for
Moodle starts with a
programmer working
on his or her local
computer. In order to
develop locally you will
need to first configure
your development
environment. In this
Unit we will install and configure the tools that you will need to develop for Moodle locally.
Local Web and Database Server
Moodle requires a web server that can interpret PHP code as well as a database server to
which you can save content. XAMPP is a preconfigured web and database server for a specific
set of operating systems. XAMPP has been preconfigured for four operating systems
Windows, Mac OS X , Linux and Solaris. We will focus on Windows, Mac OS X and Linux as
development environments.
XAMPP, MAMP and LAMPP are acronyms for Windows, Mac or Linux, respectively, and
Apache, MySQL, Perl and PHP.
Integrated Development Environment
Review Wikipedia's entry describing the Integrated Development Environment (IDE).
After installing a web and database server, you will need to setup and configure your
Integrated Development Environment (IDE). At Humboldt State University we use Eclipse,
which is a free open source java-based IDE. Other Universities like San Francisco State
University use PhpED, which is also a full featured commercial IDE with a PHP debugger.
Other potential development environments for Moodle development are vim, Adobe's
Dreamweaver, Nvu or any text editor. For the purposes of this course we will use Eclipse.
Alternative Development Environments
PhpED
PhpED is a Windows-only IDE developed by NuSphere. It has an integrated debugger and
most of the same features as Eclipse.
VIM
Vim is a highly-configurable text editor built to enable efficient text editing. It is an improved
version of the vi editor distributed with most UNIX systems.
Vim is often called a "programmer's editor" and is so useful for programming that many
consider it an entire IDE. It's not just for programmers, though. Vim is perfect for all kinds of
text editing, from composing email to editing configuration files. Instructions on how to
configure Vim for use with Moodle.
Adobe Dreamweaver
Dreamweaver is a commercial tool commonly used for web development that can also be
used to develop PHP programs. It will work just as well for Moodle development but lacks
some of the features of a full IDE like Eclipse or PhpED.
Developer's Browser Toolbars
Firebug for Firefox
Firebug is an indispensable Firefox browser plugin for dynamically viewing and editing the
HTML, javascript and CSS source code for a web page.
Selenium for Firefox
Selenium is a test tool for web applications. Selenium tests run directly in a browser and act
like a real user would. A Selenium test will run in Internet Explorer, Mozilla and Firefox on
Windows, Linux, and Macintosh. Running Selenium for other web browsers involves
downloading Selenium core and unzipping the core folder to the root web directory of your
XAMPP install.
Molybdenum for Firefox
Molybdenum is another add-on for Firefox that can edit and run Selenium tests
Important Tip!
All of the validators' links to tests run on external websites, so the URL used to validate the sites must be
publicly viewable. To use the validators on your localhost address you will need to open port 80 on your
Windows firewall, which you should be asked to do the first time you start Apache through XAMPP. You
will also need to use the IP address to your computer instead of localhost (e.g.,
http://69.57.234.89/test/test.php). If you are behind a firewall router you will need to forward port 80 to the
computer you are using. If you are using DSL, your IP address will probably change on a daily basis,
which means you will need to change localhost to your new IP address for the validators to work.
Web Developer for Firefox
The Web Developer extension is designed for Firefox, Flock, Mozilla and Seamonkey, and will
run on any platform that these browsers support including Windows, Mac OS X and Linux.
(Note the Help available if you need assistance with the installation).The Web Developer
extension is an excellent tool for viewing forms variables, CSS and HTML inline as well as
validating css, html and accessibility. Patrick Lauke does an excellent job of explaining how to
use the Web Developer Extension for accessibility validation as well as explaining the
different parts of 508 compliance--see the assigned reading in this Unit's "To Do" List.
Web Developer for Internet Explorer
The Web Developer Toolbar for Internet Explorer is similar to the Web Developer Extension
for Firefox. It allows you to:
Explore and modify the document object model (DOM) of a Web page.
Locate and select specific elements on a Web page through a variety of techniques.
Selectively disable Internet Explorer settings.
View HTML object class names, IDs, and details such as link paths, tab index values,
and access keys.
Outline tables, table cells, images, or selected tags.
Validate HTML, CSS, WAI, and RSS web feed links.
Display image dimensions, file sizes, path information, and alternate (ALT) text.
Immediately resize the browser window to a new resolution.
Selectively clear the browser cache and saved cookies. Choose from all objects or
those associated with a given domain.
Display a fully featured design ruler to help accurately align and measure objects on
your pages.
Find the style rules used to set specific style values on an element.
View the formatted and syntax colored source of HTML and CSS.
XMLDB Editor
XMLDB is a database abstraction layer that provides a common way to create and update
database tables for Moodle. Each table's definition (fields, keys, and indexes) is saved in an
XML format. This file is read when the Moodle database is first created and whenever a
module or plugin is installed. This means developers create one definition of the table(s) used
by their module or plugin and system administrators can choose to use any supported
database system such as Oracle, MSSQL, MySQL or PostgreSQL. You'll use the XMLDB Editor
in Unit 7 when editing Moodle's database. More detail will be provided in Unit 7.
Web Accessibility
Evaluating web sites for accessibility is made easier by a variety of accessibility checkers and
validation tools. While manual checks are almost always necessary, software can streamline
a site's evaluation and spot errors that might be overlooked by the designer in a manual
evaluation. The assigned reading for this unit, Patrick Lauke's "Evaluating Web Sites for
Accessibility with Firefox," illustrates how Firefox's Web Developer Toolbar can be valuable in
detecting accessibility problems.
There are certainly other software tools available to enhance productivity in the development
environment and check for universal accessibility problems. If you have tried other tools that
you prefer, please share your experiences in this Unit's discussion forum.
top
"To Do" List
1. Install a Local Web and Database Server
Install XAMPP/MAMP/LAMPP
Follow the instructions below for your operating system to download and install
XAMPP/MAMP/LAMPP:
Windowshttp://www.apachefriends.org/en/xampp-windows.html
Mac OS X http://www.apachefriends.org/en/xampp-macosx.html
Linux http://www.apachefriends.org/en/xampp-linux.html
Start Apache and MySQL
To start Apache and MySQL locate the folder under which you installed
XAMPP, MAMP or LAMPP and find the corresponding icon and double click
it.
XAMPP View MAMP View
Then either select "Start Servers" (MAMP) or "Start" for both Apache and MySQL
(XAMPP). Test by going to http://localhost/ where you'll see a splash screen similar to:
Navigate to phpMyAdmin
Now that Apache and MySQL are started you should be able to visit phpMyAdmin,
which was installed with XAMPP. In your web browser visit
http://localhost/phpmyadmin .
Create a Database in phpMyAdmin
To create a database using phpMyAdmin:
i. Type "moodle18" in the "Create new database" field
ii. Select "utf8_general_ci" in the dropdown below in the related text field
iii. Click on the "Create" button immediately below the dropdown menu.
Other MySQL GUI Applications
MySql Admnistrator/Query Browser
Cocoa MySQL
HeidiSQL
SQLyog
Create a Directory for Moodle Source Code
To create a directory for Moodle you must first navigate to the root directory of the
webserver. In XAMPP this is located in the folder you installed the application to--for
Windows, usually C:\XAMPP and for Mac, usually /Applications/MAMP. In this directory
locate the htdocs folder. In this directory create a new directory named "moodle".
top
2. Install and Configure Eclipse
If you run into problems with Eclipse, refer to the detailed information in this Moodle
Docs article: Development: Setting up Eclipse.
Download Eclipse(new
browser windows will open)
Recommended Directory/Folder
for Extraction and Installation
Eclipse for Windows
"Program Files"
Eclipse for Mac OS X
"Applications"
Eclipse for Linux
Look for a package or rpm for your distribution.
PHP for Eclipse
After installing Eclipse configure it to edit PHP files. First install a plugin for Eclipse
and then perform some configuration (refer to the "Installing the necessary plugins"
section of the article.
SVN for Eclipse (Subclipse)
In later units of this course you might use Subversion for code management. Eclipse
has a handy plugin for subversion that allows you to perform subversion commands
without leaving Eclipse. Instructions for installing the subversion plugin.
Set Eclipse to PHP View
1. Choose Window-->Open Perspective-->Other
2. Select PHP and click OK.
top
2. Explore Toolbars
Web Accessibility
Read "Evaluating Web Sites for Accessibility with Firefox," an excellent summary by
Patrick Lauke of the value of Firefox's Web Developer Toolbar in detecting
accessibility problems.
Download and install Firefox Web Developer. (Install the latest Firefox browser first, if
you don't already have it!)
Download and install the Internet Explorer Developer Toolbar.
Select one or more web pages you commonly visit and evaluate their accessibility
using one or more of these accessibility validators:
o WebAIM's WAVE Web Accessibility Tool
o Watchfire's WebXACT
o HiSoftware's Cynthia Says Portal
Selenium
Step 1. Create a Selenium test case using the Selenium IDE for Firefox. First
navigate to the Firefox tools menu and select Selenium IDE.
To start recording a test case navigate to Humboldt State University's home page at
http://humboldt.edu and click the red circle in the top right corner of the Selenium
IDE interface. The circle will change colors to pink in the middle to designate you are
recording.
Go back to your Firefox browser window and click on the "Admissions" link on the
Humboldt State University main page. Next click on the "Apply" tab on the
Admissions web page.
Step 2. Return to the Selenium IDE and you should see that both actions were
recorded. You can stop recording your actions by clicking again on the record button.
Step 3. To execute a Selenium test case click on the green arrow next to "Step" in
the Selenium IDE toolbar. You will see Firefox progress through the web pages in the
same fashion you did, albeit faster, and you will see the log in the Selenium IDE
record warnings and Info. We will discuss more about how to use Selenium in testing
later in this course.
top
2. Create a Project and PHP File
Step 1. Using the Eclipse File menu, select New-->PHP Project.
Step 2. In the Project name field, enter "Test." Uncheck "Use default location" box.
Step 3. Click the Browse button to navigate to your XAMPP htdocs location or to your
MAMP location. Create a new directory called "test".
Step 4. The directory "Test" should show up in the Navigator screen.
Step 5. To create a PHP file, from the File menu, choose New-->PHP File.
Step 6. The container should be /Test and name the file "hello.php" in the "File
name" field.
Step 7. After the */ and before the ?> prompt, type echo "Hello Moodle
world";
Step 8. Save the changes and view your creation with your browser at
http://localhost/test/hello.php. Complete and submit the "Hello World" PHP
Assignment before the deadline noted on the course Calendar.
Create a project using the editing tools of your choice, then write a simple "Hello
World" php program--but use one of the development tools explored this week to
prepare your project. Submit a screen shot of a working "Hello World" php program
showing the file in a project in a development envrionment of your choice. The screen
shot may be a .gif, .jpg or the screen shot inserted into a .doc (MS Word) or .rtf file.
3. Take the quiz before the deadline noted on the course Calendar (top left corner of the
course main page). Prepare for the quiz by practicing with the developer tools.
4. Post your responses to the assigned discussion questions in the designated forums.
Respond to classmates.
Unit 3: Source Code ManagementOverview | Unit 3 "To Do" List
External resources will open in new browser windows.
Source management systems are essential for software development.
"Not using one is like driving a car too fast: it's fun and you might get to your destination
faster, but an accident is inevitable." M. Tim Jones in Version Control for Linux: Overview of
architectures, models, and examples.
Source management systems provide a reliable way to
Track changes
Collaborate with other developers
Provide management of files
Revert back to old versions
Versioning - grouping and tagging files together so that you can recover that exact
configuration at a later point in time.
In this Unit we will cover basic concepts necessary to use source code management for
software development.
For purposes of this course you will be using CVS exclusively, but in your everyday Moodle
development there will be times when you will be using SVN, CVS, or both.
top
"To Do" List
1. Read about using CVS for source code version
control
Using Fluid Thoughts' CVS tutorial, read over the commonly used CVS commands.
Make sure you cover add, commit, update, and remove. Although these
commands are similar to SVN commands, some of them behave differently than their
SVN counterparts.
2. Read about using SVN for source code version
control
See the available options for installing SVN. After reviewing some of the available
installation options, check to see if you have one of them already installed in your
development environment. If you do not have one installed, choose an appropriate
installation package and follow the instructions to install that package.
Read the section, "Initial Checkout" in Chapter 2 of the online book, "Version Control
with Subversion," which describes the steps that would apply to checking out a
working copy of Moodle from a SVN server.
Browse through the "Basic Work Cycle" section in Chapter 2 of the online book,
"Version Control with Subversion," to study the commands that you are likely to need
during a typical workday. Pay particular attention to the five commands you'll use
most:
o svn update
o svn status
o svn commit
o svn add
o svn delete
Review the other commands in this chapter's section so that you understand how and
when they are used. Remember that
svn help <command> (e.g., svn help commit)
will show you want the command is used for and some of the valid options. If you will
be using TortoiseSVN then take a look at the manual available either through the
application or online at TortoiseSVN.
Read Subversion Best Practices from Open Collabnet.
3. Obtain Moodle for your development environment.
Using CVS
CVS for Windows
a. Find the Moodle directory in C:\XAMPP\htdocs.
b. Right-mouse-click on the moodle directory and choose "CVS Checkout" from
the menu. You should see a dialog box.
c. Enter this text into the CVSROOT field:
:pserver:[email protected]:/
cvsroot/moodle (for U.S.-based developers, replace the "SERVER" with
"us"
d. Under the "Module" field, type "moodle" to get the moodle directory.
e. Click on the "Revisions" tab.
f. Select the "Choose branch or tag" radio button.
g. Click the "Update list ..." button.
h.
Important Tip!
If you ever want to check out a different version of Moodle (for example 1.9 or 2.0) or a
specific release (for example 1.8.4 or 1.8.3) you will want to change the name in the
branch or tag name field. After clicking on the "Update list… button" you will see a listing
in the drop down of all the possible Moodle branches to check out.
Later, to update your local copy of moodle to the most current 1.8 release version in
CVS, just right-mouse-click the moodle directory and choose "CVS Update".
Select MOODLE_18_STABLE from the list of all possible Moodle revisions.
i. Press the button "OK" and everything should be checked out into the
moodle directory.
CVS for Mac and Linux
Make sure you have a CVS client installed and working in your environment. If you
are working in a Linux or Unix environment you should already have CVS installed.
If you are working in a Mac OS X environment you should also already have CVS
installed that can be accessed via the command prompt. If you are working in a
Windows environment download CVS from TortoiseCVS.
Explore this documentation on checking out a copy of the Moodle CVS located at
Moodle.org and CVS Quick Reference Card.
To connect and login for the first time to the CVS server:
cvs -
d:pserver:[email protected]:/cvsroot/moodle
login
There is no password; when asked for one, just hit Enter. To checkout (download) the
entire Moodle code for the first time, use this command to get the latest STABLE
version:
cvs -z3 -
d:pserver:[email protected]:/cvsroot/moodle
co -r MOODLE_18_STABLE moodle
Or the latest development version:
cvs -z3 -
d:pserver:[email protected]:/cvsroot/moodle
co moodle
top
Later, to update your local copy of Moodle to the current version in CVS you just need
to go into your local Moodle directory and type:
cvs update -dP
To update your local copy and to save the log of the process:
cvs update -dP -r MOODLE_18_STABLE | tee upgrade.log
To update your local copy of Moodle to a new version (e.g. from 1.7+ to 1.8), go into
your local Moodle directory and type:
cvs update -dP -r MOODLE_18_STABLE
Then look at the upgrade.log, notably look for lines starting with "C" (conflict):
grep '^C' upgrade.log
Note!
Conflicts may appear if you have manually modified your source files. You have to
resolve conflicts before using the site. See CVS for Developers for more details.
Other Alternatives to Get Moodle Code
Windows
Download from 'Moodle Packages for Windows' from Moodle.org. Choose the Moodle
1.8.x+ version (for Windows, usually it is named as 'MoodleWindowsInstaller-latest-
18.zip').
Mac OS X
You will find some information about CVS and Mac OS X in the documentation for
the complete installation package Moodle4Mac. Please read How To Update Your
Moodle4Mac. It works fine with the new CVS servers.
Use the information in this Unit to select the type of checkout that applies to you,
then checkout a copy of Moodle to a directory in your local webroot of your
development environment.
2. Take the quiz.
3. Contribute to the discussion topic.
Which method did you use to checkout Moodle for your development environment?
What are the circumstances that influenced your decision to use SVN or CVS ?
SVN (Subversion) or CVS (Concurrent Versioning System) for Moodle Development?
Using Just CVS
The most common developer configuration for source code versioning with Moodle is
to use CVS and checkout the latest version of the Moodle stable branch of the Moodle
CVS repository. In this configuration the developer obtains all updates to Moodle
through Moodle's CVS repository. The developer then makes changes locally and
tests against the current CVS version of Moodle. The developer could also decide to
checkout the CVS contribute branch of the Moodle repository in order to test and
modify third-party Modules and Plugins. The developer may or may not have
permissions to commit changes back to Moodle's CVS repository or branches. In this
scenario the most common commands the developer will need to know are CVS
update and, if they have commit privileges, CVS commit.
Who does Just CVS work for?
o Developers who just want to help out Moodle
o Developers who don't have a production environment
o Developers who feel comfortable developing in their production environment
o Developer groups who don't need to share their code with others in their
group
o Developers that want to version control their own source code but don't care
about Moodle's version control
top
Using Just SVN
This option is for people who would prefer to download Moodle in a zip format and
need a way to version control the code they are creating. There can be many
configurations for this, with the most likely that you download the Moodle sourcecode
from www.moodle.org and merge it into your SVN repository. You manage all of your
code through SVN. In this case you could use all the commands within SVN, but the
most likely commands will be svn update, svn commit and svn merge.
Who does Just SVN work for?
o Someone who would like to version control their own code but don't care
about the version control for Moodle
o A group of developers who are in different locations but sharing a common
code base
Using CVS and SVN Together
This option is the most common for an organization that has multiple developers and
multiple servers. The developers generally checkout the most current version of
Moodle from the CVS repository and then merge the changes into their SVN
repository. This allows them to use all the power of SVN while minimizing the time it
takes to get the most current bug and security fixes from moodle.org's developers. In
this scenario you will use the CVS update command along with potentially all the SVN
commands.
Who does CVS and SVN work for?
o Multiple developer groups
o Organizations with multiple servers that use different modules or blocks
o Single developers who are interested in learning SVN
If you'll be developing in Moodle without using SVN for version control, then you only
need to follow the steps for checking out Moodle from a CVS repository.
If you'll be developing in Moodle in a shop that manages a code base in SVN, then
you may only need to follow the steps for checking out Moodle from an SVN
repository.
In some cases, such as at Humboldt State University's Courseware Development
Center, a SVN repository used by most developers is kept up to date via CVS updates
from a Moodle CVS repository. In this case, the administrator/lead developer must be
knowledgeable with both systems. If this is your case, then follow the steps to
checkout copies from both systems.
Unit 4: Configuring Moodle for Development
Overview | Unit 4 "To Do" List
External resources will open in new browser windows.
Now that you've configured your development environment, you're ready to begin your
official "Moodling!" After installing the Moodle program, you'll be creating the fundamental
elements of a Moodle environment so you can see the results of your programming efforts
from a user perspective.
Although it's possible with the most recent versions of Moodle to automatically populate the
database with an institution's courses and students, you will be manually creating a course
"shell," to contain the test course, as well as fictitious students. Each "user" you create will
have a different set of roles and permissions.
After creating the test course and a few users, you'll also begin customizing your Moodle
installation by installing an existing block and an existing module shared by the Moodle
community.
Moodle "blocks" offer a Moodle course developer (usually the "Teacher") an array of
opportunities to customize the features displayed in the online environment--usually to
provide additional information or functionality to the learner. There are a set of standard
blocks that come with Moodle but there are also many third-party blocks that a Moodle
system administrator can choose to add. In general, "blocks" can be distinguished from
modules because blocks affect layout and infrastructure of the course environment but do
not contain content, activities, or interaction opportunities. Blocks typically may appear only
once on a course main page in the left or right columns; activities (created by "modules")
may be repeated many times throughout the course sections in the center column. "Modules"
contain the code for creating the activities within the course for participant interaction and
assessment. For example, Moodle "Modules" include the discussion forum or a quiz creation
tools.
Basic Moodle Preparation
Be sure to read documentation carefully before and during the software installation. In
particular, Installing Moodle from Moodle.org is an invaluable resource to read before
beginning. During the install you'll find additional helpful information in the
readme_en.txt file unzipped in your C:\XAMPP directory..
The "contrib" branch is an area in the Moodle source repository where user contributed third-
party modules, blocks, and customizations are contained. It's a way of keeping the
development of those separate from core Moodle. This Unit gives considerable attention to
the contrib branch.
Important Tip!
Beware of role assignments that don't make sense when the underlying functionality does
not exist. The interface or facility must actually exist within the context that you have
assigned that right. For example, you can assign a user the right to create new categories at the Category
context. However, category creation is only available at the site level.
Roles and Permissions
There are six default roles:
1. Administrator
2. Course creator
3. Teacher
4. Non-editing teacher
5. Student
6. Guest
By assigning a role to a user in a certain context, you grant them the permissions contained
in that role for the current context and all lower contexts.
Contexts in hierarchical order are:
System (no parent)
Site (parent = system) - Moodle 1.8 onwards
Course category (parent = system)
Course (parent = category or system)
Module (parent = course or system/site(1.8 onwards))
Block (parent = course or system/site(1.8 onwards))
User (parent = system)
TRICK: Enabling teachers to assign teacher role
By default, teachers are only allowed to assign the roles of non-editing teacher, student
and guest. To enable teachers to assign the role of teacher:
1. Access Administration > Users > Permissions > Define roles.
2. Click the tab "Allow role assignments".
3. Click the checkbox where the teacher row and column intersect.
4. Click the "Save changes" button.
Inheritance will kick in if a role is assigned at a higher level. For example if a user is
assigned a Teacher role in a particular course category then the user will have this role in ALL
courses within the category.
Roles only work if the role assignment is made in the correct context. For example, the
Inspector role is an example of a role assigned in the system context, the Teacher role should
be assigned in the course or course category context, the Forum moderator role is an
example of a role assigned in the module context, and the Parent role is an example of a role
assigned in the user context.
As a system administrator, you could create additional roles (we will cover this in more detail
later in this course).
A significant part of the roles infrastructure is the ability to assign a user into multiple
roles (at the same time). The capabilities of each role are merged to produce the effective
set of capabilities. In particular it is perfectly possible for a user to be both a Teacher and
Student in the same course. This differs from the behavior of Moodle prior to the introduction
of roles. You should be careful to ensure that if you change a user's role that you remove
them from any other roles as required as this will no longer be done automatically. See more
information about managing roles as a system administrator.
As a developer, it is also important to understand the implementation of the ROLES and
PERMISSIONS system so that you could familiarize yourself for the debugging/programming
later on.
Installing Third Party Blocks and Modules
Moodle developers around the world program blocks and modules to add features to the
basic ("core") Moodle code. These enhancements are shared in the online Moodle community
so others can use or modify the customizations. In the activities for this Unit, you'll install an
existing block and an existing module from the Moodle.org site to customize your new
Moodle installation.
Basically there are two ways to obtain third party blocks developed by other Moodle
developers:
Approach A. In Unit 3 we covered how to checkout Moodle source code using CVS. You
could use CVS to checkout the contrib branch which contains a lot of third party patches,
plugins, modules, and blocks. Using CVS to checkout the Moodle contrib branch is advised
when you are planning to modify the code, or if you want to use CVS update to obtain new
versions of third party modules or blocks. CVS allows you to incorporate the third party block
or module owner's modifications with your own modifications to the third party block or
module. CVS will also inform you if there is a conflict between your code and the third party
owner's code.
Approach B. Navigate to the Modules and Plugins area at the Moodle.org website. ("Plugins"
is used interchangeably with "blocks.") This approach is advised if you don't plan to modify a
third party block or module and are satisfied with navigating the Moodle website to download
the latest code for a third party block or module.
Important Tip!
The PHP function echo or Moodle's print_object() function could be more
useful for debugging than enabling the Moodle "debug modes."
Debugging Mode
You can find debugging mode in the Site Administration block. To prepare for the debugging
activity later in this unit refer to this essential information about Debugging at the Moodle
site.
top
"To Do" List
1. Install Moodle
Install Moodle following the directions at http://docs.moodle.org/en/Installing_Moodle.
Previously in Unit 2 we learned how to setup XAMPP on PC (and Mac) and created the
Moodle database; in Unit 3 we learned how to use CVS to check out Moodle source
codes. Next you'll setup and configure your local Moodle installation for development.
Now carefully follow steps 5.5 through 7 in the installation directions.
2. Create the Moodle test environment (empty course,
test students, assign roles, restore test case
course).
Create an Empty Course
Login to Moodle as an administrator. Find the "Site Administration" block and click on
the "Courses" link, then "Add/edit courses" link.
Three fields are required: "Full name," "Short name," and "Summary." (*) For now you
could just put in something that you could remember and then click on the "Save
changes" button. If you do not understand some of the options (such as "Format"),
you could click on the help button right next to it (the yellow "question mark") for
more information.
Create Students for Testing
Return to the System Administrator main menu (click on the "Administration" link in
the breadcrumb area at the top left). Create two or more users now: click on "Users,"
then "Accounts," then "Add a new user."
Remember that the required fields must be entered before the user will be accepted
by Moodle. In this case the required fields are "Username," "New password," "First
name," "Surname," "Email address,"City/town," and "Select a country." Required
fields are marked with asterisks.
The new user information is saved by pressing the "Update user" button near the
bottom of the form. Other fields that are part of a user's profile can also be filled out
when the user is created. Some of the profile fields can be revealed by pressing the
"Show Advanced" button.
Assigning Roles
Now that you have created some new users, assign each with different roles.
Return to the empty course that you created (click on "Courses" in the "Site
Administration" block, then "Add/edit courses"). Once you get back to the course
view, click on the "Assign roles" in your "Administration" block.
Choose the type of role you want to assign from the list. For example, for assigning a
Student role to Martin, we'd first choose "Student" from the list of roles.
After choosing a role, two lists appear: a list of users who currently have that role
("Student Demo" in this example) in the left pane, and a list of users who don't in the
right pane. By selecting Martin in the right pane (clicking on his name) and using the
left-pointing arrow button in the middle of the two panes, Martin would be added to
the list of existing users on the left. Multiple users may be selected by holding down
the Apple (Mac) or Ctrl (PC) key while clicking n the users' names.
Removing someone from a role is done by moving the user from the left column to
the right by selecting their name and clicking on the right-pointing arrow.
Restore Demo Course Content
Download the Moodle 1.9.3 Features Demo course backup then return to the course
view to restore the course into the empty course you have already created (#2
above). Note that you can only restore the Moodle Features Demo course backup to a
Moodle 1.9.3 site or newer. Click on "Restore" link in the "Administration" block. You
will then be able to upload the test case course to your Moodle development server
and see it in your Files list.
Click on the "Restore" link to restore the course. Once you successfully restore the
course you could start to explore all the features provided by Moodle.
top
3.
Important Tip!
Some modules come with roles and capability settings. Pay close attention to the global settings.
Install New Blocks
There are two ways to obtain third party blocks: (A) through Moodle CVS "contrib"
branch (requires using CVS checkout) and (B) to download it from
http://download.moodle.org. These two different approaches are introduced below
using the Windows platform and the "Quickmail" block as an example block to
download and install.
Approach A: From Moodle CVS "contrib" Directory
i. Find the contrib directory or create a new directory where you want to place
downloaded third-party Moodle customizations (e.g., C:\XAMPP\moodle\
contrib\). .
ii. Right-mouse-click that directory and choose "CVS Checkout" from the
menu. You should see a dialog box.
iii. Enter this text into the CVSROOT field:
:pserver:[email protected]:/cvsroot
/moodle
(for US-based developers, replace the "SERVER" with "us")
iv. Under the "Module" field, type "contrib" to get contrib directory.
v. Press the button: "OK" and everything should be downloaded.
vi. Move some of the language files into the language directory. For example,
you need to copy the block_quickmail.php that is included in the \
lang\en directory into your development Moodle installation \lang\
en_utf8 directory. This will help define some of the strings that this block
uses.
vii. Take care of the Help files too: Put the /lang/en/help/*.html
into the /lang/en_utf8/help in your development Moodle
installation. These are the help button content of the quickmail block.
Later, to update your local copy of contrib to the current version in CVS, just right-
mouse-click the directory and choose "CVS Update".
Note: The enclosing Moodle directory is self-contained - you can move it anywhere
you like or even rename it.
Under your local contrib directory, you will find several directories.
Blocks are also referred to as "plugins," so to find the block called "quickmail,"
navigate into the "plugins" directory and click on "blocks." Here you should find the
"quickmail" directory.
Copy the whole quickmail directory and place it under your Moodle directory (e.g.,
C:\XAMPP\moodle18\blocks\quickmail). Login as admin on your local development
Moodle installation, then click on "notification" in your "Site Administration" block.
You should now be all set. Sometimes for some of the blocks there might be some
global settings or course level settings, so take care of these settings as well.
Approach B: Download from http://download.moodle.org
viii. Download the quickmail.zip file from http://download.moodle.org.
Moodle download site for plugins" alt="screen shot of Moodle download site
for plugins"
src="http://dev.moodle.org/file.php/2/pictures/Unit4screenshots/pluginsdownl
oadUnit4.jpg" />
ix. Unzip quickmail.zip to your local Moodle installation, putting it in the /block
directory.
x. Move some of the language files into the language directory. For example,
you need to copy the block_quickmail.php that is included in the \
lang\en directory into your development Moodle installation \lang\
en_utf8 directory. This will help define some of the strings that this block
uses.
xi. Take care of the Help files too: Put the /lang/en/help/*.html
into the /lang/en_utf8/help in your development Moodle
installation. These are the help button content of the quickmail block.
xii. After all these are done, login as the admin on your development Moodle
installation, and click on the "Notification" link in your "Site Administration"
block. You will be prompted that quickmail tables are created correctly and
now the quickmail block is ready for your users to use!
4. Verify your block is installed properly.
Regardless of whether using Approach A or Approach B, verify your block is properly
installed by adding the newly installed block to a course of your choice. First, while
logged in as an administrator or teacher, "Turn editing on," then (1) select the name
of your block from the Blocks drop down menu. (2) You should see your block appear
in the column on the right below existing blocks on your course main page.
5. Install New Modules
To install a third party module called "Face-to-Face":
i. Download the .zip file (or copy from your contrib directory--you can find it
in /contrib/plugins/mod directory).
ii. Copy the "facetoface" directory to the /mod directory.
iii. Be sure to read the README file inside the facetoface directory for more up-
to-date instructions. Usually, if there IS a README file in the directory of a
third party module (or block), it will also tell you which version of Moodle it is
compatible with.
iv. Login as admin on your Moodle development installation, then click on the
"Notification" link in the "Site Administration" block. You will be prompted
with several tables, then a "Continue" button at the end of the page.
v. Click on the "Continue" button and then you are done!
vi. Usually you also will want to check whether there is a "Global Setting"
associated with the module. Click on the "Modules" link under "Site
Administration" to see if there are global settings that need your attention.
Refer to the example illustrated for the "Face-to-face" third party module.
vii. After taking care of the global settings, try logging in as an administrator, an
instructor, or a student to create an instance of this new module. With editing
capabilities on the course, you can see the newly installed "Face-to-face"
module available from the dropdown menu.
6. Debugging Mode
After you login as Admin user, find the "Site Administration" block and click on the
"Server" link, then the "Debugging" link.
Step 1. Take a close look at the options for "debug messages debug." The default
setting is "NONE: Do not show any errors or warnings." You have the following five
options:
i. NONE: Do not show any errors or warnings
ii. MINIMAL: Show only fatal errors
iii. NORMAL: Show errors, warnings and notices
iv. ALL: Show all reasonable PHP debug messages
v. DEVELOPER: extra Moodle debug messages for developers
Experiment with these options. You might find out that if you set it to NORMAL (or
above), sometimes Moodle will display a lot of undesired error/warning messages
which might not be related to what you are looking for. Later in the course in "Quality
Assurance Testing Techniques" we will cover this in more depth and you will be able
to use functions such as Moodle's print_object() or PHP's echo, or
PhpED/Eclipse for debugging purposes.
Step 2. Enable the "Performance
info perfdebug" check box. After
you click on "Save changes", you will
start to see on the bottom of each
page (the footer) how many seconds
it took to load the page, and how
many files were included before PHP could render this page correctly.
In config.php you can enable other performance information, such as how many
database queries before displaying the page, etc.
For example, if you set Debug to "Yes" in the Configuration->Variables page, some
performance profiling data will show up on your footer (in default theme). With these
settings you get more granular control over the capture and printout of the data.
You could add these two lines right before the PHP closing ?> in config.php to enable
database query information:
define('MDL_PERF', true); // Capture performance profiling data
define('MDL_PERFDB', true); // Capture additional data from DB
This will allow you to actually see the performance data. You MUST check the
"Performance info" (perfdebug) checkbox in Debugging so that adding
these two lines in the config.php will work!
7. Following the steps in Approach A, above, pick a third party block to install on your
own Moodle installation. For troubleshooting, please participate in the forum in Unit
4.
8. Add to the discussion on your experience installing third-party materials.
StructureOverview | Unit 5 "To Do" List
External resources open in new browser windows.
This Unit refers to the directory structure in Moodle version 1.8.
The /admin directory
Files under this directory handle all the features under
the "Site Administration" block.
As of November 2007, there are 635 files spread out in
137 directories under this /admin directory (in Moodle
1.8.3+ version). For purposes of this course, we will
just focus on the most important file:
/admin/cron.php
Some of Moodle's modules require continual checks to
perform tasks. For example, Moodle needs to check
the discussion forums so it can mail out copies of posts
to people who have subscribed. The script that performs these continual checks is located in
the admin directory and is called cron.php. Usually we set up a mechanism where this script
runs regularly by itself, although you could also manually run it directly from a Web browser,
or from a command line. Cron.php provides a "heartbeat" to perform functions at intervals
defined by each module. This kind of regular mechanism is typically implemented using a
cron daemon/service via cron jobs.
The cron.php script:
1. Searches the mdl_modules table (assuming the default table prefix, of course) in the
Moodle database for modules scheduled to have their cron functions run
2. In each such module directory locates any function called module-name_cron in the
lib.php file and runs it
3. Searches the mdl_block table for blocks scheduled for their cron methods (object
functions) to be run
4. for each such block, runs the cron method for a new object associated with that block
These files (the lib.php files and the files where the block classes are defined) can contain
cleanup functions, email functions or anything that needs to be run on a regular basis. For
example, cron will trigger the system to create the backups of courses at the time specified
in the administration settings. It also triggers any messaging module or forum email
notifications, but not all functions are called each time the cron runs. Some functions, such as
unenrolling students who have not logged in or deleting old copies of log files, are only run
occasionally. The cron.php file has a section which will randomly call these core tasks
approximately 1 in 5 times the cron runs.
Note that the machine performing the cron does not need to be the same machine
that is running Moodle. For example, if you have a limited web hosting service that does
not have a cron service, then you might choose to run cron on another server or on your
home computer. All that matters is that the cron.php file is called regularly.
The load of this script is not very high, so 5 minutes is usually reasonable, but you can reduce
the time period to 15 minutes or even 30 minutes. It's best not to make the time period too
long, as delaying mail-outs can slow down activity within the course. Remember that mail-
outs also wait for the editing time to expire before being queued for sending. As long as cron
is run regularly and fairly frequently, the load is not very high. However, if it hasn't been run
in a long time or the proceessing frequency is too far apart the loads can be considerable
depending on site activity and any background batch processes such as enrolling or un-
enrolling that may need to occur.
top
The /blocks directory
By now you probably already know about 'blocks' in moodle. Moodle blocks typically appear
in the left and right margins of a course's main page. They typically contain a function and
differ from the "sections" that appear down the center column of a course's main page that
contain the content and Activities or Resources added by the instructor.
When a Moodle course is created it automatically generates several 'blocks' that allow you to
control how you navigate or find information in Moodle (examples of these include the "Site
Administration" block for administrator, the "Search Forums" block or the "Calendar" block for
all users, etc.). In addition to the blocks that automatically appear, you will notice that you
have several options for further blocks of tools (from the Blocks drop down menu when
editing is turned on) to add to your course. Examples include the "Remote RSS Feeds" block,
the "Blog" block, etc.). Similarly, you can delete any of the existing blocks if you feel they are
unnecessary to your course and you can also move the blocks so that they appear on a single
side rather than on both sides of the middle content (this can only be achieved using the
move or delete buttons with editing turned on).
In a typical Moodle 1.8 installation, you will see a set of standard blocks available for each
course creator.
If you look into your local Moodle installation and navigate to /blocks directory, you will find a
matching directory for each block.
If you need to debug the "Blog Menu" block, for example, you go to the "blog_menu'
directory. If you need to debug the "Search Forums" block, begin with the "search_forums"
directory, etc. Later in this course we will introduce more about how to write a Moodle block
from a programmer's perspective. Additional details about "Blocks administration" (usually
from a system administrator's perspective).
Important Tip:
Localized strings should be in a separate language directory such as en_custom. The
default is if a string is not found in one language it falls back to en_utf8. This way, your
changes override the default, but you do not have to include every string or manage changing core
language strings. You just have to manage your localized settings.
The /lang directory
This directory contains all the different language files, including their related help button
content. The one to pay most attention to is the "en_utf8" directory. Under this directory you
will be able to understand how Moodle defines all the strings in different modules or blocks.
For example, all the strings that are related to the admin module defined in admin.php.
The /lib directory
For a Moodle developer, this is probably one of the most important directories that you will
use. The /lib directory contains many library files (275 directories and 2179 files, as of Moodle
1.8.3+) ranging from ajax and adodb libraries, to xmldb and yui (Yahoo User Interface)
libraries. The most important three library files are probably moodlelib.php, weblib.php, and
accesslib.php. These three library files will be discussed in more depth in Part B of this Unit.
However, this is a brief summary of these three library files:
moodlelib.php is the Moodle "main" library. This file contains of miscellaneous general-
purpose Moodle functions (such as set_user_preferences(),
get_user_timezone(), and so on).
weblib.php contains functions that help Moodle produce web output. For example, it has
functions such as format_text_email(), print_header(),
print_group_menu(), etc.
datalib.php contains functions that alllow moodle to access the database, it also has
functions that deal with the role capabilities, such as load_defaultuser_role(),
get_guest_role(), etc.
The /mod directory
This directory contains most of the Moodle key modules. Currently in moodle 1.8 there are 18
key modules under /mod directory.
top
"To Do" List
1. Experiment with the cron script by running it directly from your browser
(http://localhost/moodle/admin/cron.php). If cron is called from the command line by
any user logged in to your Moodle it will create a temporary admin environment in
order to run and then log the user out. You can disable command line running of cron
by disabling the appropriate section in the cron.php file. See more details about how
to set up automated execution of this script (cron.php) on (1) Windows, (2) Web
hosting services, or (3) Using the crontab program on Unix. Usually this is a system
administrator's job to set up so it is beyond the scope of this introductory Moodle
programmer's course.
2. Run admin/auth.php from your Web browser
(http://localhost/moodle18/moodle/admin/auth.php) to see what it does. You could
also access this file through the "Site Administration" menu (under Users ->
Authentication).
Unit 5 Part B: Global VariablesOverview | Unit 5 "To Do" List
External resources open in new browser windows.
In Part B we will focus on Moodle's global variables. Later in Part C of this unit we will
introduce Moodle API and some of the most important Moodle library files.
Moodle Globals
Most PHP programmers should know that in general, you want to avoid the use of global
variables as much as possible. Regardless of this general guideline Moodle still uses a few
global variables. As a Moodle programmer, you should not use any other global variables
other than those listed in this lesson. In general when programming with Moodle you should
not use PHP's built-in superglobals either--instead you should access data in these variables
via Moodle's API functions.
$CFG
The $CFG object holds many of Moodle's configuration directives. In general when linking to
items you want to use the variables in $CFG so that your code is portable to other sites, and
the calling order of scripts is not critical.
You can find most $CFG variables in the /config.php file. We will not cover all of the attributes
of $CFG, but rather we will focus on those you are most likely to use while programming.
$CFG->wwwroot: This is the base address of the moodle installation. Use this
when constructing URL's so that it doesn't matter what other script includes your
script. That is, since your script can potentially be included from an arbitrary
directory you will not reliably be able to construct relative URLs. Take a look at
your config.php and see how this variable was defined.
$CFG->dirroot: This is the base file path of the Moodle installation. This is the
directory where Moodle is installed. So you will find your blocks in "{$CFG-
>dirroot}/blocks"
$CFG->dataroot: This is the data directory for your Moodle site.
$CFG->admin: This is the administrator username.
$CFG->httpswwwroot: If https is enabled this is the secure wwwroot base
address. If https is not enabled this is the same as $CFG->wwwroot.
$CFG->libdir: This is the location of the moodle library files.
$CFG->textfilters: Is a comma separated list of the currently enabled text
filters.
$CFG->loginhttps: Is a boolean value indicating whether or not https is
enabled for login.
$CFG->noreplyaddress: The email address to use for email that should not
receive a reply.
$CFG->sesskey: The current sesskey. Use the sesskey() function to obtain
the current users session key for form and data processing. Using the sesskey()
function rather than the value in $USER->sesskey or $CFG->sesskey is
preferred as the sesskey() function allows the API to change and you will not
need to update your code.
$CFG->themedir: This is the location of the theme directory via the filesystem.
$CFG->themewww: The web accessible base URL for the theme directory.
$CFG->theme: Is the current site theme.
$CFG->pixpath: The web accessible base URL of the pix directory. This is where
the moodle icons will come from.
$CFG->modpixpath: The web accessible base URL of the module icons.
$CFG->mailsessiontime: This variable stores the number of hours email
sessions persist (default is 1 month). A cron function (cleanup function) written in
admin/cron.php is used to prune the session table.
Additionally, if your code stores any information in the config table (usually named as
mdl_config) then that information will be accessible via the $CFG variable as well.
top
$USER
The $USER object holds information pertaining to the currently logged in user. This global
variable was first declared in /lib/setup.php.We will not cover all of the attributes of this
object, but instead will focus on those attributes you are most likely to use. Most of these
attributes come from the user profile.
$USER->id: The user's Moodle user id.
$USER->auth: The user's authentication method.
$USER->username: The user's username
$USER->idnumber: The user's idnumber, this is typically used to uniquely
identify the user on an external system.
$USER->firstname: The user's firstname.
$USER->lastname: The user's lastname
$USER->email: The user's email address.
$USER->emailstop: Indicates if the user has disabled their email.
$USER->institution: The user's institution.
$USER->department: The user's department.
$USER->address: The user's address.
$USER->city: The user's city.
$USER->country: The user's country
$USER->lang: The user's default language
$USER->theme: The user's theme if user themes are allowed.
$USER->lastlogin: The last time the user logged in.
$USER->currentlogin: The user's current login time.
$USER->lastIP: The last IP the user logged in from.
$USER->picture: If the user has a picture set or not.
$USER->timemodified: The last time the user profile was modified.
$USER->student: An array of course id numbers the user is a student in.
$USER->timeaccess: An array keyed by course id which lists the access time
for that particular course.
$USER->teacher: An array of course id numbers the user is a teacher for.
$USER->teacheredit: An array of course id numbers the user is an editing
teach for.
$USER->sesskey: The user's current session key.
top
$COURSE
The $COURSE object holds information pertaining to the currently viewing course. This
global variable was also declared in /lib/setup.php.We will not cover all of the attributes of
this object, but instead will focus on those attributes you are most likely to use in the future.
$COURSE->id: The course's Moodle course id.
$COURSE->category: The course's category. Usually moodle administrator may
have setup up several course categories, for example, "Science," "Humanities,"
"Public Health," etc. (or based on semester). When you create a new course
manually, by default the category will be set to "Miscellaneous" for which the
category id is 1.
$COURSE->fullname: The course's full name, such as "Computer Science Basic
Programming Logic"
$COURSE->shortname: The course's shortname, such as CS101.
$COURSE->format: The "format" of the course is usually "site" (for the Moodle
root course), "weeks," or "topics" (based on the format the teacher chooses).
$COURSE->visible: This specifies whether the course is visible to the students
or not
$COURSE->groupmode: This specifies whether the course uses group mode or
not. 0 is no, and 1 is yes.
$COURSE->timecreated: The time that the course was created. This uses
Unix time stamp format so to really understand what the actual date is, you need
some conversion (see the link below for more details)
$COURSE->timemodified: The time that the course was last modified. Again
it is using Unix time stamp format.
$COURSE->guest: Whether the course allows "guest access." If the value is set
to 0 then no, but if the value is set to 1 then yes.
$COURSE->startdate: The starting date of the Moodle course. Note that
Moodle uses "Unix timestamp" to convert the actual date/time to startdate. So for
example, if you want to do a SQL query to list out all the courses that has starting
date from 2007-08-01 to 2007-09-01 you could write the query like this using
"unix_timestamp":
select fullname, shortname, cat.name from mdl_course,
mdl_course_categories as cat where
startdate > unix_timestamp('20070801 00:00:00') and
startdate < unix_timestamp('20070901 00:00:00')
and category = cat.id order by cat.name
More information on the Unix timestamp.
For other attributes under $COURSE object, browse the Moodle table mdl_course.
Name Default Value Type
$COURSE Object(stdClass) (44 elements)
id "1" String
category "0" String
sortorder "1000" String
password "" String
fullname "Moodle 1.8.x +" String
shortname "mdl18x" String
idnumber "" String
summary "test" String
format "site" String
showgrades "1" String
modinfo NULL Undefined
newsitems "3" String
teacher "Teacher" String
teachers "Teachers" String
student "Student" String
students "Students" String
Guest "0" String
Startdate "0" String
Enrolperiod "0" String
Numsections "0" String
Marker "0" String
Maxbytes "0" String
Showreports "0" String
Visible "1" String
Hiddensections "0" String
Groupmode "0" String
Groupmodeforce
'0' String
Lang "" String
Theme "" String
Cost "" String
Currency "USD" String
Timecreated "0" String
Timemodified "1197679457" String
Metacourse "0" String
Requested "0" String
Restrictmodules "0" String
Expirynotify "0" String
Expirythreshold "0" String
Notifystudents "0" String
Enrollable "1" String
Enrolstartdate "0" String
Enrolenddate "0" String
Enroll "" String
Defaultrole "0" String
top
$SITE
Site variables are settings that determine how your entire Moodle site functions. The $site
variables are the most technical settings. This is the only global variable that is not declared
in the /lib/setup.php file. These are some commonly used attributes in Moodle 1.8:
$SITE->fullname: The Moodle site's full name. This is based on what you
described during the Moodle installation process.
$SITE->shortname: The Moodle site's short name. This is also based on what
you named it during the Moodle installation process.
$SITE->numsections: The Moodle site's number of sections.
$SITE->id: The Moodle site ID number. By default it is assigned as "1".
$SITE->category: The Moodle site category number. By default it is assigned
as "0", which is the root category. Usually only the Moodle "root course"--the front
page of Moodle, that is assigned to category 0. The "Miscellaneous" course category
is category 1.
$SITE->password: This is the admin admin stite password, which is the super admin
(username: admin) password. Note: Don't confuse this one with the $CFG->dbpass--
these two are different. The $CFG->dbpass is usually defined in the config.php and is
the Moodle database password.
Name Default Value Type
$SITE Object(stdClass) (44 elements)
Visible "1" String
Timemodified "1182375379' String
Timecreated "0" String
Theme "" String
Teachers "teachers" String
Teacher "teacher" String
Summary "test" String
Students "students" String
Student "student" String
Startdate "0" String
Sortorder "1000" String
Showreports "0" String
Showgrades "1" String
Shortname "moodle18p" String
Restrictmodules "0" String
Requested "0" String
Password "" String
Numsections '0' String
Notifystudents "0" String
Newsitems "3" String
Modinfo NULL Undefined
Metacourse "0" String
Maxbytes "0" String
Marker '0' String
Lang "" String
Idnumber "" String
Id "1" String
Hiddensections "0" String
Guest "0" String
Groupmodeforce
"0" String
Groupmode "0" String
Fullname "Moodle 1.8.x+" String
Format "site" String
Expirythreshold "0" String
Expirynotify "0" String
Enrolstartdate "0" String
Enrolperiod "0" String
Enrolenddate "0" String
Enroll "" String
Defaultrole "0" String
Currency "USD" String
Cost "" String
Category "0" String
Note: Other global variables such as $THEME, $db, $MCACHE, and $HTTPSPAGEREQUIRED
are found in the /lib/setup.php.
"To Do" List
1. Read additional Moodle Coding Guidelines: #10 in the General rules section; #6
under the Security issues section.
2. Use print_object() (defined in /lib/datalib.php at around line 1610),
print() (http://us2.php.net/print), or echo()
(http://us2.php.net/manual/en/function.echo.php) to print out some of the values of
the global variables mentioned in this unit for debugging purposes.
3. Contribute your ideas to the discussions for this Unit on global variables.
Unit 5 Part C: Moodle LibrariesOverview | Unit 5 Part C "To Do" List
External resources will open in new browser windows.
Important Tip:
Discuss with the Moodle core team (using moodle.org "General Developer" forum) when
planning changes to any of these three files, and preferably (if you have write access to the
Moodle CVS tree) after approved by the Moodle core team, you should commit your changes into the
Moodle CVS
In Part A of this Unit you were introduced to one of the most important directories for Moodle
developers, the /lib directory. In Part C you will learn more about this directory, specifically
the three major library files: moodlelib.php, weblib.php, and datalib.php.
As you review code examples in Moodle and begin to prepare code as part of this lesson,
refer to the "General Programming and Security Overview" Unit in this course.
For a general overview, take some time to browse through the Moodle Core API, usually
covered in these three files, so that you could get a rough idea the scale of these three
library files. This page is automatically generated using PHPEdit (a PHP software tool) from
the three main library files in moodle/lib.
Very few Moodle programmers could master every single function or class among these three
library files. Usually you look up these three major library files for what you need to know
when you are troubleshooting a problem. There is a very useful website provided by Moodle,
http://xref.moodle.org/ (referred to in this course as "xref"). Browse this site to get ideas how
to use this site to look up specific functions, classes, or variables.
As it might not be easy to master every single function inside of these three library files, it is
probably better to explain with some examples. Here are three examples of how you can
troubleshoot with these three files.
Case A - moodlelib.php
As we already learned from Part A, the moodlelib.php IS the main library file of miscellaneous
general-purpose Moodle functions. This means that it also contains functions related to login,
etc. If we look at an example case MDL-10375 at Bug Tracker you will notice the problem was
undefined mnethostid (which you might guess it means "mnet host id"). In the description of
the bug report it mentions that the plan is to create one new create_guest_user() function
under moodlelib.php with correct settings. This is the type of function that usually goes into
moodlelib.php
Case B - weblib.php
This is the library of all general-purpose Moodle PHP functions and constants that produce
HTML output. In Moodle 1.8 code, it defines one class (tabobject) and nine functions. See an
example case using weblib.php with MDL-11506 at Bug Tracker.
Case C - datalib.php
This is the library that contains functions for database manipulation. In Moodle 1.8 code,
datalib.php defines 43 functions. Some examples are get_admin() (returns $user object
of the main admin user), search_users() (search through course users),
get_users() (returns a subset of users), get_courses() (returns list of courses, for
whole site, or category), get_logs(), etc.
The datalib.php sometimes can be confused with dmllib.php, which is another very
important library that contains functions for database manipulation as well. However,
dmllib.php in general deals with the record level (more micro level) type of database
manipulation, while datalib.php deals with users, admins, courses, logs and other higher
levels of database manipulations. See two examples using datalib.php at Bug Tracker: MDL-
11135 and MDL-8549.
During major Moodle version upgrades, usually there will be more functions added to these
three files (moodlelib.php, weblib.php, and datalib.php).
Other Important Libraries
Remember:
Assume a function exists before writing the functionality on your own.
Moodle's API is rather robust, and functions can be broken down into several main categories.
Understanding where portions of the API are located in Moodle's lib structure can be
extremely helpful in determining where to check if a particular function exists or how to call a
particular function.
There are a few functions that are used often with which you should become familiar. As you
become more familiar with Moodle through programming experience it will become obvious
which functions these are. We will wait until we begin writing some code before we cover the
API in detail, but below is a brief overview of functionality and a good starting place to look:
lib/dmllib.php: inserting, updating, and retrieving data from the database. These
are more micro-level functions, including execute_sql(),
db_uppercase(), modify_database(), count_records(),
get_record(), get_field(), delete_record(),
insert_record(), update_record(), etc. As of moodle 1.8.3+, there are
around 69 functions defined in this library file (for more details please refer to the
Moodle xref site). The most important (or most frequently used) functions in this
library are:
o get_record() Get a single records as an "object." This function is very
frequently used (i.e., referenced 1500+ times in Moodle 1.8 code).
o get_records() Get a number of records as an array of objects. This
function is also frequently used (i.e., referenced 460+ times in Moodle 1.8.
code). If the query succeeds and returns at least one record, the return value
is an array of objects, one object for each record found. The array key is the
value from the first column of the result set. The object associated with that
key has a member variable for each column of the results.
o get_record_sql() Get a single record as an object using an SQL
statement. The SQL statement should normally only returns one record. In
debug mode you will get a warning if more records are returned (unless you
set $expectmultiple to true). In non-debug mode, it just returns the
first record.
Important Tip:
When accessing the database use the Moodle database API. The database API
abstracts the database calls allowing system administrators to choose which
relational database works best for this installation. Not using the database API forces the
developer to create SQL queries for all of the relational databases Moodle supports (MySQL,
Postgresql, MSSQL, and Oracle).
lib/ddlib.php: modifying, creating, or deleting database schema. In Moodle 1.8 it
contains 27 functions. This library includes functions such as table_column(),
table_exists(), field_exists(), index_exists(),
find_index_name(), create_table(), rename_table(),
add_field(), drop_field(), rename_field(), add_key(),
drop_key(), etc. Some of the most important or most frequently used functions
in this library file are:
o table_column() This function will add a new field to a table, or modify an
existing one (if oldfield is defined). It was referenced 850+ times in Moodle
codes. Warning: Please be careful on primary keys in different tables, as this
function will eat auto_increments.
o create_table() This function will create the table passed as an argument
with all its fields/keys/indexes/sequences--everything based in the XMLDB
object. As you would have guessed, there are also drop_table(),
rename_table(), add_field(), drop_field(),
rename_field(), and change_field_type() functions. All are
related to manipulating database schema.
lib/accesslib.php: This is a new library file created beginning in Moodle 1.7. It
mainly covers context, roles, and permission related functions. In Moodle 1.8.x there
are around 80 functions defined in this accesslib.php file. Frequently used functions
are:
o require_capability() Checks for a capability assertion being true.
If it isn't then the page is terminated neatly with a standard error message.
o has_capability() You will see this function being referenced a lot (in
Moodle 1.8.3+, at least 915 times; see the Moodle xref site for more details).
This function returns where the current user has the capability of performing
a function. For example, we can do
has_capability(‘mod/forum:replypost',$context) in
forum. This is a recursive function, by the way.
o get_context_instance() Get the context instance as an object.
This function is frequently used and will create the context instance if it does
not exist yet.
o create_role() and delete_role() Creates a role and deletes a
role (as well as cleaning it up after it)
lib/blocklib.php: In short, this library file includes all the necessary functions to use
blocks in a typical course page. As of Moodle 1.8.3+, there are around 27 functions
included in this file. Some of the most important (or frequently used) functions
include:
o block_instance() Loads the necessary class files for a block.
Whenever you want to load a block, use this function first.
o blocks_have_content() This function will accept an array of block
instances and checks to see if any of them have content to display. Will
return true or false. It is being referenced in
/course/format/scorm/format.php, /admin/settings.php, and other places.
o block_print_group() Prints one group of blocks in a page.
Parameters passed by reference for speed; they are not modified.
lib/formslib.php: This is a VERY important library file in Moodle 1.8. This is the
library of classes for creating forms in Moodle, based on PEAR QuickForms. Want to
know more about the features of formslib? Additional useful related resources are
Formslib Usage, Formslib Form Definition, and Formslib Validation.
Information is also available on the most recent changes for the library files mentioned
above.
Important Tip:
Knowing where to look and what functions to use will become easier with time and
familiarity with the Moodle codebase. It may seem frustrating at first--but be patient!
Selecting Library Files to Include
When including Moodle core libraries it is best to follow the practice of less is more: including
only the libraries that contain the functions that you require for the program to work. Always
use the function require_once()to avoid including files that may have already been
included in other portions of Moodle code. The most common file to include is config.php.
This file sets up the global variable $CFG (more about $CFG to come in Unit 5 Part C), as well
as includes other essential files. Another common practice is to store all common functions
for a block or module in a library file called lib.php file.
This is just a brief overview and the above library files cover more functionality than what is
suggested by the above list. There are many other functions available via the API.
Example Code Snippets Using Functions from Three Main
Library Files
Example 1
Objective: Implement an if statement to see if a user with username 'joe' exists in the user
database.
Step 1: Analyze the task. As the task is dealing with the user database,we look into the
/lib/dmllib.php to look for useful functions that we could use to retrieve user data. We found
the function "record_exists()".
Step 2: Implement the code snippets:
global $CFG;
require once ($CFG->dirroot . 'config.php');
require once ($CFG->dirroot . '/lib/dmllib.php');
if (record_exists('user', 'username', 'joe')) {
print 'joe is an existing username';
}
else {
print 'joe is not an existing username';
}
Step 3: Test out the code to see if it works. Testing methods are covered in more depth in
Unit 8.
top
Example 2
Objective: Printing a yes/no combination box for an HTML form with the element name
'active', 'no' as selected.
Step 1: Analyze the task. As the task is dealing with HTML output, we look into the
/lib/weblib.php to look for useful functions that help us achieve our goal. We found the
function 'choose_from_menu()' (at around line #642).
Step 2: Implement the code snippets:
global $CFG;
require once ($CFG->dirroot . 'config.php');
require once ($CFG->dirroot . '/lib/weblib.php');
$options = array();
$options[0] = get_string('no');
$options[1] = get_string('yes');
choose_from_menu($options, 'active', 'no');
Step 3: Test the code.
Example 3
Objective: Cleaning and sanitizing some data submitted from a form and inserting the data
into the 'mdl_notes' table where 'mdl_' is the database prefix. Assuming that 'notes' is a
textarea and 'url' is a text box.
Step 1: Analyze the task. The task is dealing with (1) cleaning data submitted from a form,
and (b) inserting data into a Moodle table. We realize that we probably have to look into the
/lib/weblib.php (for data submitted from a form) and /lib/moodlelib.php (for cleaning data),
and /lib/dmllib.php (for inserting data into the table. So we probably have to deal with three
library files: weblib.php, moodlelib.php, and dmllib.php. We find the data_submitted()
function in weblib.php (at around line #285), and clean_param() function in
moodlelib.php (at around line #336), and finally, the insert_record() function in
dmllib.php. If we want to handle the code writing in a more "Moodle" way, we could use
get_string() (returns a localized string), and print_string() (print out a
translated string) functions to display success/error messages. This way it would allow the
error message to be displayed in different languages (if the string is defined in a particular
language pack).
Step 2: Implement the code snippets:
global $CFG;
require once ($CFG->dirroot . 'config.php');
require once ($CFG->dirroot . '/lib/dmllib.php');
require once ($CFG->dirroot . '/lib/weblib.php');
require once ($CFG->dirroot . '/lib/moodlelib.php');
if ($data = data_submitted()) {
if (!empty($data->notes) && !empty($data->url)) {
// build a new object to insert into the database
$insert = new stdClass;
$insert->notes = clean_param($data->notes,
PARAM_CLEAN);
$insert->url = clean_param($data->url, PARAM_URL);
if (insert_record('notes', $insert)) {
print_string('notesinserted');
}
else {
error(get_string('insertnoteserror'));
}
}
else {
error(get_string('missingrequireddata'));
}
}
else {
error(get_string('nodatasubmitted'));
}
Step 3: Test the code.
top
"To Do" List
1. Open your favorite PHP editor and browse through the moodlelib.php now.
Important Tip:
The "search" feature on the xref site is sometimes difficult to find and use. The
search link is located on the upper-right corner of the site and when you "mouse-
over" the link, you will see a embedded pop-up window of options (class, function, variable,
constant, and table).
2. Go to xref (http://xref.moodle.org/) and browse through the same file
(moodlelib.php). This time you will be able to click on functions or variables right
away and know where they were defined or referenced. This site can be particularly
useful when you try to skim through all major functions covered in moodlelib.php.
This "search feature" will also record your search history. If you click on the link
"Search history +" link, you will see all of your search history on this site:
3. Pick a file not covered in this Unit's discussion of the /lib directory and browse the
code to determine what it does.
4. Navigate weblib.php on xref.moodle.org to get a rough idea what functions are
covered in this library file.
5. Write a simple snippet that would list out all courses (with their id, shortname, and
fullname) that were created between 2006-10-01 to 2007-12-01. (Hint: You may need
to use a function in the moodlelib.php library to convert a date to a unix timestamp.)
The output should be using the get_string() function (instead of just using
echo or print so that it complies with the Moodle standard (to make it easier for
other languages). Submit your snippet as a text file in the designated Assignment
area.
6. Share your comments on Moodle libraries in the designated discussion forum.
7. Take the quiz. Two attempts are allowed.
8. Add to the discussion on Moodle libraries.
Unit 6: Programming Practices Overview
Overview | Unit 6 "To Do" List
External resources will open in new browser windows.
There are definite challenges to creating and maintaining code created by programmers
around the world that may be accustomed to their own programming standards. So it should
not be surprising that Moodle has developed coding guidelines to streamline the integration
of code from many sources. In addition to the assigned reading on Moodle coding guidelines,
as you prepare to write your own Moodle programs, remember these quick tips:
Use four spaces instead of the Tab key. This can be easily accomplished by properly
configuring your editor as you did in Unit 2 for Eclipse.
Variable names should be descriptive and useful
Write your code to be readable instead of writing comments to explain badly written
code.
Any good security resource will first cover social engineering aspects because many security
breaches are a result of lack of policy or following existing policy protocol. This Unit will only
briefly cover social engineering aspects--not all possible aspects of security. There are many
other quality resources out there that will do a much better job (reference appendix) than we
could possibly do here. For this reason we will focus on how to manage risks involved with
database driven web applications. Also we will briefly cover other security issues and include
some security best practices.
'The big lie of computer security is that security improves by imposing complex passwords on
users. In real life, people write down anything they can't remember. Security is increased by
designing for the way humans actually behave.' --Jakob Nielsen
How do most web-based security issues occur?
Errors in Programming
Giving too much permission to a user or not restricting user permission: This
happens when we do not, or can not, properly check to see if a user has the appropriate
authority to execute a command. This means that users should not be able to edit another
user's account unless they have administrative privileges. Or a user should not be able to
change a course unless they are the teacher for that course or they are an admin or some
other user that should have that privilege.
General logic errors: There are general logic errors that appear to go through the proper
steps, but maybe a boolean conditional is reversed or improperly negated. That is, we
proceed down the wrong branch of execution.
Errors in Handling Data
Improperly handling data: Essentially no data coming from users should ever be trusted.
What this means is that regardless of who our current user is we should treat the data
coming in as though it may have malicious content. We should always appropriately clean
and filter data coming from the user. Data stored in the database was probably initially
submitted by a user so that data needs to be properly handled when redisplayed to users.
Lack of casting/type checking: This is essentially an extension of improperly handling
data. When we are expecting a number as input from the user we should ensure that a
number is supplied. Wherever possible numeric data should be used because it is extremely
easy to clean. However, we still need to do appropriate user level checks to ensure they have
the rights to see or modify data.
Exposing too much information: - Some systems have been referred to as "loose lipped"
when they expose too much information. A common example is a login script that may
respond with "Incorrect password for user 'Joe'" this system is loose lipped because it alerts
the user that 'Joe' is a valid user account. A better message would be "Incorrect username or
password" this provides a valid user with information as to what went wrong and a person
trying to hack a login with essentially no information. Most often too much information is
exposed via error messages; unfortunately it is frequently the case that too little information
is returned. Your script should only return enough information, and no more, for the user to
understand what happened so they can fix their error.
When handling data from a user you want to apply the tightest filtering possible. You want to
let only the data you want to get through. No more and no less. If you are expecting a
number, ensure that the data provided is in fact a number. If you are expecting an
alphanumeric string, ensure that is what is provided.
A solid and robust API will have solid ways to handle incoming data. Unfortunately sometimes
you may not be able to filter the data very strictly. This is where it becomes incredibly
important that you treat the data appropriately before trying to do anything with the
database involving that data, or properly handle the data before redisplaying it in the users
browser.
Properly handling data involves not only handling incoming data, but also properly handling
outgoing data.
Errors in Trust
Trusting data from a non-trusted user: As covered above you should not trust data
coming from users. So the statement can more succinctly be "trusting data from a user." This
may seem overly harsh or restrictive, but the reason for not trusting users is that an
unintended person may gain access to a user account. That is, the person on the other end
may not be who you think it is.
Trusting data from the database: This has already been touched on as well. A common
mistake is the assumption that user input was cleaned before it was put into the database so
it is safe when it comes back from the database. This is an extremely dangerous assumption
as the user may have posted malicious code that was not executed initially due to proper
handling, but now if we assume it is safe the original exploit may still be possible. The reason
for this is that when we initially handled the data we may have protected against the
malicious code, but the malicious code is still present in the data. That is, rather than
executing the malicious code we have stored it in the database. Now, if we later assume it is
safe then we may inadvertently execute the malicious code.
Why you shouldn't trust users
This may sound like a harsh policy or procedure, but this is a fair assumption and is good
practice.
Users make mistakes. Sometimes we do things that we don't intend to do
A user may not be who you think they are. It may be that the user on the other end
of the computer may not be who you think they are. This can happen for various
reasons that are outside of the scope of this document.
A user may need to educate students about exploits.It is plausible that a user may
need to educate their students about common security exploits. During this process
they may need to post code that if not properly handled would be malicious or have
unintended consequences. The instructor may post this code, so you do not want to
trust that the information provided by the instructor is safe.
Trusting users leads to vulnerabilities: By trusting your users you are placing the security of
your whole site into your entire userbase. If that doesn't make you nervous maybe you
should consider another profession, and certainly not system administration! When you trust
users you are assuming they will not do anything dangerous or malicious either intentionally
or accidentally. For instance, a flaw that allows elevated permissions is a vulnerability that
might allow a student to gain teacher privileges and a teacher to gain administrator
privileges. Once the system is penetrated, problems seem to escalate and security breaches
will become increasingly serious.
top
Cross-Site Scripting (XSS)
What is XSS?
Cross-Site Scripting exploits are typically the result of trusting data from one source and
presenting it to another user without properly scanning and handling the initial data or
properly filtering the data before sending it to a second user to be displayed.
Why should we protect against XSS, or what are some
implications of a XSS exploit?
Many vendors downplay the seriousness of XSS exploits. This is rather unfortunate because
as we will see XSS pose security issues for other websites as well as a user's personal
information stored on their computer. Below are some potential results from employing XSS:
Cookie theft: Obtaining cookie data from websites in a different domain. This can
expose personal information stored in a cookie issued by a website in a different
domain. This is a direct circumvention of the DOM and can expose a user's personal
information or give access to information stored in a cookie for another website.
Account hijacking: "Logging in" to a different user's account. This could potentially
be accomplished by stealing the cookie information from another website that
employs persistent connections. Or perhaps a user alters an account for a particular
web application to make it trivially easy to login.
Alteration of web application settings: Changing a user's password or
preferences for a particular website making it unavailable to or unusable by the
correct user.
Exploit of a web browser security issue to access a user's underlying
operating system: This is a double exploit issue here. By employing a known
security issue for a particular web browser it is possible that a user employing an XSS
attack may gain elevated privileges to the underlying operating system that the
browser is running on.
How do we protect against XSS?
There are two key major points in protecting against XSS, and another which some may
argue is not related to XSS per se, but does alleviate some of the potential security issues of
someone exploiting a XSS vulnerability. The two major points are:
Input validation: By validating input we can try to recognize data that may have
unintended consequences when retrieved from the database and sent to the browser
or directly sent to a browser. There are several options to take when trying to handle
user input. We can refuse to do anything for data that looks suspicious, or we can
choose to filter the incoming data. Since XSS exploits are not a static target it is
critical that there is a single function to handle identifying and cleaning potentially
problematic data. (Moodle has created the function clean_param() for this
purpose.) This makes the code manageable as new exploits are invented there is one
place to update to ensure that all of the code-base is safe. This of course assumes
that everyone is properly coding and using the appropriate API functions for whatever
application they are programming for.
Encoding data before sending to a user: by encoding data before it is sent to the
user we can ensure that certain text that may be interpreted as valid JavaScript (or
other scripting code) is properly escaped so that it is shown as text and not
interpreted as valid markup to be executed. This prevents the user from
inadvertently running some type of script. See the general rules of the Moodle Coding
Guidelines.
The other method is verification of a private token, and really protects against "Cross-Site
Request Forgery" (CSRF), but this is often lumped in with XSS. (Moodle uses sesskey() as
its private token.) A Cross-Site Request Forgery is when one user crafts a URL that appears to
do one thing, yet when another user clicks on it some command or procedure will be
executed. For example Joe could create a controversial post in a forum or something that
would likely cause users to click a crafted URL that takes advantage of a CSRF vulnerability in
an application. Now let us assume that Mary is reading Joe's post and clicks on the URL. If an
application is vulnerable to CSRF attacks, Mary may have just deleted a file or unknowingly
altered her user preferences. To protect against CSRF attacks the application can generate
private tokens that must be submitted along with requests to update, create, or delete data.
The private token is generated for each session and is verified any time that the user
attempts to alter data. See the Security Issues section of the Moodle Coding Guidelines.
How do we protect against XSS in Moodle?
Input validation: Review lib/moodlelib.php for appropriate PARAM_TYPE information
o required_param($parameter, PARAM_TYPE);
Use this function when a parameter must be present. $parameter is expected
to be a parameter name that will be obtained via POST or GET in that
order.The Moodle API will throw an error and stop execution of the script if
the parameter is not present. Use an appropriate PARAM_TYPE to filter the
variable.
o optional_param($parameter, $default, PARAM_TYPE);
Use this function when a parameter may be present. $parameter is expected
to be a parameter name that will be obtained via POST or GET in that order. If
the variable is not present then $default is returned. Use an appropriate
PARAM_TYPE to filter the variable.
o clean_param($variable, PARAM_TYPE);
Use this function to clean a variable that is already set in the code.
Encoding data: See Moodle Output Functions developer documentation.
Private token:
o sesskey()
Make sure that the sesskey() parameter is set in any form that
will result in the user making changes to data in the database. These
forms should use the POST method rather than GET wherever
possible.
echo '<input type="hidden" name="sesskey"
value="'.sesskey().'" />';
echo '<input type="hidden" name="sesskey"
value="'.$USER->sesskey.'" />';
o confirm_sesskey()
When processing form data and your script will change any data in
the database always ensure to confirm that the session key
parameter is present and the session key matches the current
session key. Use confirm_sesskey() which will throw an
error and stop execution if the values do not match.
SQL Injections
What are SQL injections?
SQL injections are a form of security exploit where arbitrary database commands can be
executed. This usually occurs when user input is not properly filtered or when the data is not
strongly typed.
An example of SQL injection would be a credit card company's website using your username
and password to look up your credit card number, social security number, and mailing
address. If the programmer trusts the user to enter in the information without cleaning the
username or password and decides to add the username and password directly to the php
code that creates the SQL query, the SQL query code looks like:
$sql = "SELECT creditcardnum, ssn, address
FROM userdata
Where username = '".$username."'
And password = '".$password".'";
Now assume that a malicious hacker sent the following information to the program:
Username = test
Password = blah' or '1' = '1
These parameters create an SQL query:
SELECT creditcardnum, ssn, address
FROM userdata
Where username = 'blah'
And password = 'blah' or '1' = '1'
The "or" statement causes this to select all records in the user table--not just the one with the
correct username and password. Looks like that malicious hacker has a lot of customer's
credit card information now!
Why is it important to protect against SQL injections?
It is important to protect against SQL injections because a user may be able to execute any
database command. Possible scenarios include catastrophic deletion of the whole database,
exposure of sensitive user information, or subtle hard to detect changes such as adding a few
points to a graded assignment.
How do we protect against SQL injections?
To protect against SQL injections we must properly filter user text and be careful how we use
user input to generate SQL queries. Additionally we can strongly type the queries so that
parameters are appropriately handled. To filter text we need to properly handle escape
characters so that they are not misinterpreted, allowing for a user to run modified or multiple
SQL queries. Strongly typing data passed in by the user ensures that the data is of the type
we expect it to be. That is, if we are expecting a number from the user then we can strongly
type that variable to ensure it holds a number rather than a string.
How do we protect against SQL injections in Moodle?
Filter user input - appropriately filter user input using:
o required_param()
o optional_param()
o clean_param()
Strongly type user input - Where possible, the PARAM_TYPE's for the above three
functions will approximate this method.
top
Moodle Data Cleaning Parameters
The following is an overview of the parameter cleaning types to be used with
required_param(), optional_param(), and clean_param().
PARAM_RAW: specifies a parameter that is not cleaned or processed in any way.
PARAM_CLEAN: Obsolete, please try to use a more specific type of parameter.
PARAM_INT: Integers only, use when expecting only numbers
PARAM_INTEGER: Alias for PARAM_INT
PARAM_ALPHA: Contains only english letters.
PARAM_ACTION: Alias for PARAM_ALPHA, use for various actions in forms and URLs.
PARAM_FORMAT: Alias for PARAM_ALPHA, use for names of plugins, formats, etc.
PARAM_NOTAGS: All HTML tags are stripped from the text. Do not abuse this type.
PARAM_MULTILANG: Alias of PARAM_TEXT.
PARAM_TEXT: General plain text compatible with multilang filter, no other html tags.
PARAM_FILE: Safe file name, all dangerous chars are stripped, protects against XSS,
SQL injections and directory traversals.
PARAM_PATH: Safe relative path name, all dangerous chars are stripped, protects
against XSS, SQL injections and directory traversals
o note: The leading slash is not removed, window drive letter is not allowed
PARAM_HOST: expected fully qualified domain name (FQDN) or an IPv4 dotted quad
(IP address)
PARAM_URL: expected properly formatted URL.
PARAM_LOCALURL: expected properly formatted URL as well as one that refers to the
local server itself. NOT orthogonal to the others! Implies PARAM_URL!
PARAM_CLEANFILE: safe file name, all dangerous and regional chars are removed,
PARAM_ALPHANUM: expected numbers and letters only.
PARAM_BOOL: converts input into 0 or 1, use for switches in forms and urls.
PARAM_CLEANHTML: cleans submitted HTML code and removes slashes
o note: do not forget to addslashes() before storing into database!
PARAM_ALPHAEXT: the same contents as PARAM_ALPHA plus the chars in quotes: "/-
_" allowed, suitable for include() and require()
PARAM_SAFEDIR: safe directory name, suitable for include() and require()
PARAM_SEQUENCE: expects a sequence of numbers like 8 to 1, 5, 6, 4, 6, 8, 9.
Numbers and commas only.
top
Security Aspects of Moodle's Roles and Capabilities System
Beginning with Moodle version 1.7 a system of roles and capabilities was introduced to
replace the existing system of fixed roles (e.g., administrators, course creators, editing
teachers, students, etc.). Of the errors in security described earlier, some errors in logic and
some errors in trust are mitigated by this system of roles, capabilities, and permissions.
A capability is usually some specific Moodle action that can be executed by a user. For
example, the capability 'moodle/course:update' refers to the action of updating course
settings. Another capability, 'moodle/course:viewhiddencourses', refers to the action of
viewing courses that have been hidden.
A role is a named set of all the capabilities with associated permissions (e.g., student, forum
moderator, teacher, teacher assistant).
A permission describes the ability of a role to perform a certain capability. Permissions for a
particular capability of a specific role are set within a context or "space" in Moodle. For
example, a course would be considered one context. The four permissions available to be set
for a capability of a role in a specified context are:
1. CAP_INHERIT
2. CAP_ALLOW
3. CAP_PREVENT
4. CAP_PROHIBIT
To understand how these four permissions work it is necessary to understand that contexts
are hierarchical. From the broadest to the most specific, the contexts are:
1. CONTEXT_SYSTEM
2. CONTEXT_PERSONAL
3. CONETXT_USER
4. CONEXT_COURSECAT
5. CONTEXT_COURSE
6. CONTEXT_MODULE
7. CONTEXT_BLOCK
Permissions not set in a context for a role's capability are inherited (CAP_INHERIT) from a
more general context.
For example, if the student role has a CAP_ALLOW permission for the 'moodle/course:view'
capability in a CONTEXT_COURSE context and the underlying contexts (CONTEXT_MODULE
and CONTEXT_BLOCK) have not been "overridden" then the role will also have CAP_ALLOW
for 'moodle/course:view' in those more specific contexts.
The CAP_PREVENT permission will deny a user that capability in that context and more
specific contexts unless overridden in those contexts. It is important to realize that
CAP_PREVENT permissions can be overridden in more specific contexts. For example, a
student role may have CAP_PREVENT on the capability 'mod/forum:rate' in a course context,
but for a specific forum (module context) they have CAP_ALLOW. The permission in the
specific context "wins."
The CAP_PROHIBIT permission also denies a user that capability in the context in which it is
set, but the permission in more specific contexts can not be overridden.
top
Legacy Permissions
Legacy permissions in the Moodle roles system have been implemented for backwards
compatibility. In versions of Moodle before 1.7 there were five static roles:
1. Administrators
2. Course Creators
3. Teachers
4. Students
5. Guests
In Moodle 1.7 and beyond those same roles exist in a default installation of Moodle. A Moodle
administrator now has the capability to add, delete, or change any permission in their Moodle
installation. When creating a new capability developers set the default value for each of
these default roles in the legacy section in order to configure the default permissions for a
Moodle installation. All non-default roles will need to be configured manually by the Moodle
administrator when a block or module with a new capability is installed.
Moodle Functions for Roles and Capabilities
There are several important functions in Moodle in the roles and capabilities system.
The first line of defense in a script is the require_login() function to restrict access
to logged-in users. This function first checks that the user is logged in and then optionally
checks whether they are allowed to be in a particular course and/or view a particular course
module.
To check a user's permission for a capability in a certain context requires a couple of
functions. The first, get_context_instance(), returns a context instance as an
object. A context instance is a context level (e.g. CONTEXT_COURSE) and an instance id (e.g.,
a course id).
Once you have the context instance you can require a capability in a script using the function
require_capability() or you can check to see if a user has a particular capability
before performing some action with the function has_capability(). An application of
these functions might look like this:
$context = get_context_instance(CONTEXT_COURSE, $courseid);
$require_capability('moodle/course:view', $context);
// some things that anyone with ‘moodle/course:view can
// do or see here
// now check for a more restrictive capability
if (has_capability('moodle/course:update' $context) {
// do some update to the course
} else {
error('You do not have the correct permissions');
}
top
Programming for Accessibility
As mentioned in the Introduction of this course, Moodle developers around the world have
made progress toward universal accessibility--in large part because of commitment to
making improvements in the code that improve usability. It is imperative that future
developers of Moodle code not dismantle the significant strides made to date and continue to
observe some key programming practices that impact users.
Some quick tips to keep in mind when designing Moodle elements:
As much as possible avoid events that cause pop-up windows.
Use meaningful link names and form element labels
Functions must be executable from a keyboard
Never use color alone to convey meaning
Avoid blinking or animated elements
Provide descriptive and relevant alternative text for any graphics or images,
remembering that it will be read aloud to visually-impaired users
In-Development Documentation of Code
Moodle uses PHPDocumentor to generate online documentation about common classes and
functions. It is recommended that you use PHPDocumentor format when documenting your
functions and classes. This allows other developers to view information about the functions
you create online without needing to search your code. PHPDocumentor's style also makes
for clean, easy-to-read code that a developer can use to quickly understand what a function
is supposed to do and what each parameter is without reading the entire function. See
Moodle's PHP documentation.
top
"To Do" List
1. Carefully read the Coding Guidelines at Moodle.org--giving special attention to the
Security Issues section.
2. Review the WebAIM Section 508 Checklist for important suggestions to achieve
universal accessibility.
3. Read over Moodle resources for best security practices and addslashes(),
which can sometimes be confusing.
4. Complete the PHPDocumentor Tutorial
5. Detect the security, accessibility, documentation, and coding guideline errors from
the following example. Submit your corrections in the designated drop box in this
Unit's section on the course main page. Copy your changed code into a text-only file
and submit the file.
<?php
/*
* Created on Dec 11, 2007
*
* This script tests the user has the course view
* capability and then verifies that the password
entered
* is correct. if the password is correct it prints out
a webpage.
*/
require_once('http://www.somesite.com/abadfile.php');
required_param($id,PARAM_INTEGER);
required_param($password,PARAM_TEXT);
required_param($courseid, PARAM_INTEGER);
optional_param($sitename, "HUMBOLDT", PARAM_TEXT);
$file = get_file_contents($_GET['url']);
$context = get_context_instance(CONTEXT_COURSE,
$courseid);
$require_capability('moodle/course:view', $context);
if($password != 'thisistherightpassword'){
error("<blink>Your Password is not correct</blink>");
} else {
echo $file;
//This function does some addition
function block_addition($a, $b){
return($a+$b);
}
?>
6. Take the quiz. Two attempts are allowed.
7. Add your thoughts to the discussion on accessibility.
Unit 7 - Part A - Block Basics
Part A - Block Basics
1. Create a simple block following Moodle's tutorial. The block will be named "simplehtml."
2. Create a language file and directory.
3. Create a database table into which our block will insert information.
Part B - Forms
1. Add a form using the Moodle forms library to insert information into the table
o Define a new form.
o Display the new form.
o Add a header.
o Add access control.
o Add logging.
o Add form elements.
o Add state variables.
o Finalize the form.
2. Process the form.
Part C - Refine the User Interface
1. Add links to each page of the block.
2. Add methods to view pages.
3. Refactor display method.
o Add page title.
o Display the date
4. Display text.
5. Display link to file.
6. Display the picture.
Part D - Add Editing Capabilities
Add editing capabilities that allow users to edit data, including
1. Delete a page
2. Add a link to the delete.php file
3. Create the delete.php file
4. Clean up all data associated with the block with the instance_delete() function
Part E - Define a Role for the Block
1. Add check to the block for the capability
2. Add a role to the simplehtml form
3. Add a role to edit
4. Add a role to delete
Block Basics | Forms | Refine the User Interface | Add Editing Capabilities | Define a Role
Hyperlinks will open in new browser windows.
Now that we have covered the basics about Moodle libraries, secure programming, your
development environment, and how to install and configure Moodle, we will get to the fun
part--coding! As you learned in Unit 5, Moodle is modularized as much as possible to allow for
third party programs to integrate with Moodle. The simplest way to integrate a program with
Moodle or to develop new functionality is to create a self-contained block.
In Unit 7 you will create a block called simplehtml. You'll begin with a Moodle.org tutorial that
will teach you how to create a basic Moodle block with commonly-used functions.
By completing the simplehtml block, you will:
Add a database table to Moodle
Create a Moodle form
Add multiple HTML QuickForm elements to a Moodle form
Process a Moodle form with multiple HTML QuickForm elements
Insert, update and delete data from database table in Moodle using the form.
Some of the examples in this course may not seem logical or useful in the context they are
used. In general this is intentional to illustrate different methods. Because of the amount of
detail in this topic, it is broken into parts that should be completed in sequence, beginning
with this Part A, "Block Basics."
Creating a Simple Block
Follow the tutorial in the Moodle site documentation to create a simple block. Test it to make
sure it installs and works. If you need help, review "Unit 4 - Configuring Moodle for
Development!" which covers installing blocks and modules. In order to fix some PHP warnings
that will pop up from the code in the Moodle tutorial you will want to change your
specialization function to the following.
function specialization() {
if(!empty($this->config->title)){
$this->title = $this->config->title;
}
if(empty($this->config->text)){
$this->config->text = '';
}
}
Notice that this code checks if the configuration variables were set; if either variable has not
been set it assigns an empty string to that variable or does not use it. This reduces warnings
and follows good coding practice of checking if a variable is instantiated before it is used.
Verify that the block you created using the tutorial works by installing it (see "Unit 4 -
Configuring Moodle for Development!") and adding the block to a test course.
Introduction to Moodle's Language and Internationalization
Now that the simple block has been created, it is
time to expand it to do more things. As discussed in
Unit 5, one of the most important directories for the
customization of Moodle is the lang directory. Each
block can have its own language directory. In the
block directory create a lang directory (right click on the simplehtml directory, then select
New > Folder) .
Next create a new directory within the lang directory called en_utf8 (English encoded using
the utf8 character encoding). Now add a new PHP file with the name block_simplehtml.php
to the simplehtml/lang/en_utf8 directory.
This file will hold all the static strings that the simplehml block will use. Later if you want to
translate your string to another language you can add another directory within lang for the
language you are translating to. Example utf8 directories can be found in the site lang
directory if you have installed other language packs. More about language translations.
Now that the language file is created, a new string can be added to Moodle for the block
using something like the sample code below--replacing the 'name of the string' with a valid
PHP array key and the 'Text for the string' with a PHP string:
$string'name of the string' = 'Text for the string';
Practice by adding the line below to your block_simplehtml.php file.
$string'blockname' = 'Simple HTML Block';
To retrieve this string within the block you would use the Moodle function get_string()
found in lib/moodlelib.php. To get the title string into a variable use:
$this->title = get_string('blockname', 'block_simplehtml');
Replace the line in the class definition for block_simplehtml.php that assigns a value to
$this->title with the line of code above.
Create a Database Table for the Block
With the language file started it's time to move on to using the XMLDB Editor to design and
create the database table that will hold the data from the form that you will create later. [If
you want more detail on the XMLDB Editor, see Appendix B.] The user will input eight pieces
of information to the simplehtml form:
1. Text to be displayed with the link to the display of the form information
2. Displayable HTML or text
3. HTML area format
4. A file name
5. A "yes or no" question
6. A picture choice
7. HTML or plain text from a text area
8. A date and time stamp
Important Tip!
Avoid using enum because not all databases support this type. It is better to use an integer that is coded to
a string value. Integers also scale better than enums.
To begin, create the correct directory structure in Moodle. Add a file directory named db
under your main block directory. Next login to Moodle and navigate to the XMLDB editor,
located in the "Site administration" block > Miscellaneous > 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.
Refresh the Eclipse navigator. Now 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
top
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 Unsigned to unsigned
7. Set Not Null to not null
8. Set Sequence to No
9. Enter 0 for the Default
10. 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.
displaytext
The
displaytext field will be displayed as text on the simplehtml page, potentially as HTML. This
will be an HTML text area where the user should be allowed to write as much text or HTML as
desired--which means it should be defined as a 'big' length text field. 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. Enter a Length of big
6. Set Not Null to not null
7. 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 Unsigned to unsigned
7. Set Not Null to not null
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 Unsigned to unsigned
7. Set Not Null to not null
8. Set Sequence to No
9. Enter 0 for the Default
10. Click the Change button.
top
description
Add the
description field that will be displayed on the page. This will be an HTML text area where the
user is allowed to write as much as desired so it is a 'big' text field. 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. Enter a Length of big
6. Set Not Null to not null
7. 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 Unsigned to unsigned
7. Set Not Null to not null
8. Set Sequence to No
9. Enter 0 for the Default
10. 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 Unsigned to unsigned
7. Set Not Null to not null
8. Set Sequence to No
9. Enter 0 for the Default
10. 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. With the install.xml created anyone who installs the simplehtml
block fresh will have the table setup when they check the notifications link (as discussed in
Unit 4).
Unit 7 - Part B - Forms
Part A - Block Basics
1. Create a simple block following Moodle's tutorial. The block will be named "simplehtml."
2. Create a language file and directory.
3. Create a database table into which our block will insert information.
Part B - Forms
1. Add a form using the Moodle forms library to insert information into the table
o Define a new form.
o Display the new form.
o Add a header.
o Add access control.
o Add logging.
o Add form elements.
o Add state variables.
o Finalize the form.
2. Process the form.
Part C - Refine the User Interface
1. Add links to each page of the block.
2. Add methods to view pages.
3. Refactor display method.
o Add page title.
o Display the date
4. Display text.
5. Display link to file.
6. Display the picture.
Part D - Add Editing Capabilities
Add editing capabilities that allow users to edit data, including
1. Delete a page
2. Add a link to the delete.php file
3. Create the delete.php file
4. Clean up all data associated with the block with the instance_delete() function
Part E - Define a Role for the Block
1. Add check to the block for the capability
2. Add a role to the simplehtml form
3. Add a role to edit
4. Add a role to delete
Block Basics | Forms | Refine the User Interface | Add Editing Capabilities | Define a Role
Hyperlinks open in new browser windows.
In Part A of this unit you learned how to create a basic block with all the standard functions
that Moodle needs to display the block with some limited configuration. You learned how to
create a database table using the XMLDB editor in Moodle, added a new language file for the
block.
Next you will work on creating a form to add information to the database table you created.
Add a Form to a Block Using the Forms Library
Read through Moodle's documentation on forms library usage and the definition of the forms
library fields. After reading about how to create a form, create one for the block_simplehtml
block that allows the user to:
1. Enter text to describe the html page the user will be going to when they click on a
link in the block
2. Display a link to a file in the course file directory
3. Display the picture (answer a question Yes or No)
4. Select between three pictures to display
5. Enter text for the html area under the picture
6. Display a date and time
7. Place the fields created in #3, #4, and #5 (above) into a separate fieldset
8. Add the field created in #6 (above) to the advanced features section of a form
9. Require #1 (above) to be entered before the form can be submitted.
Define a New Form
The first step in creating a form is to create the form class which extends moodleform. Create
a file called simplehtml_form.php (observing Moodle's naming conventions, see Appendix
A) and add the following code:
<?php
require_once("$CFG->libdir/formslib.php");
class simplehtml_form extends moodleform {
function definition() {
global $CFG;
$mform =& $this->_form;
$mform->addElement('header', 'displayinfo',
get_string('textfields', 'block_simplehtml'));
}
}
?>
The "definition" function is a function that will be overridden and adds the static elements to
a form. This is the basic class definition for the form. Anytime you want to create a form you
can copy the above code and replace "simplethml" with the name of the form you are
creating. The code adds an HTML header to the form, which means that the textfields string
needs to be added to the language file for the block.
Display a Form
Now that the basic form definition has been created, the next step is to create the php
program that will display the form. Create a new file in the blocks/simplehtml directory called
view.php. To this file, add the following code:
<?php
require_once('../../config.php');
require_once('simplehtml_form.php');
$simplehtml = new simplehtml_form();
$simplehtml->display();
?>
The code above will display and render the form. You can test it by clicking on the addpage
link in the footer of the block. As you can see, the use of inheritance has made form display
very straightforward. The base class does most of the heavy lifting, so all that's left to do is
define a form class that extends the base class (moodleform) where the display()
member function is defined.
Although this code is functional, we have skipped many important steps. Now we will add in
the missing pieces.
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:
To have access to $CFG and $USER add the following after
require_once('../../config.php');;
global $CFG, $USER;
A populated course object is needed which will contain various course details. Since
passing in the courseid as a parameter, that can be used to build a course object. To
do this, add the following code after
require_once('simplehtml_form.php'):
$courseid = required_param('courseid',PARAM_INT);
if (! $course = get_record('course', 'id', $courseid) )
{
error(get_string('invalidcourse', 'block_simplehtml').
$courseid);
}
Notice that getting a valid object or generating an error is ensured.
To display a proper header add the following before $simplehtml-
>display();
print_header(strip_tags($site->fullname), $site->fullname,
'<a href="'.$CFG->wwwroot.'/course/view.php?id='.
$courseid.'">'.$course->shortname.
'</a> ->'.get_string('formtitle',
'block_simplehtml'), '',
'<meta name="description" content="'.
s(strip_tags($site->summary)) .'">',
true, '', '');
Just before $simplehtml->display(); add:
print_header(strip_tags($site->fullname), $site->fullname,
'<a href="'.$CFG->wwwroot.'/course/view.php?
id='.$courseid.'">'.$course->shortname.
'</a> ->'.get_string('formtitle',
'block_simplehtml'), '',
'<meta name="description" content="'.
s(strip_tags($site->summary)) .'">',
true, '', '')
Add Access Control
Currently any user can visit this page. Right now this is not as big of a concern since the form
does not do anything, but always ensure that users have access only to those portions of the
application that they should. After loading the course object, add:
require_login($course);
This will ensure that only a logged in user with access to the course will be able to use the
simplehtml form. See the Access Controls section of this Unit for more details.
Your view.php file should now look similar to:
<?php
require_once('../../config.php');
global $CFG, $USER;
require_once('simplehtml_form.php');
$courseid = required_param('courseid',PARAM_INT);
if (! $course = get_record('course', 'id', $courseid) ) {
error(get_string('invalidcourse', 'block_simplehtml'). $courseid);
}
require_login($course);
$simplehtml = new simplehtml_form();
$site = get_site();
print_header(strip_tags($site->fullname), $site->fullname,
'<a href="'.$CFG->wwwroot.'/course/view.php?id='.
$courseid.'">'.$course->shortname.
'</a> ->'.get_string('formtitle',
'block_simplehtml'), '',
'<meta name="description" content="'.
s(strip_tags($site->summary)) .'">',
true, '', '');
$simplehtml->display();
print_footer();
?>
Add Logging
Moodle uses the function add_to_log() to log information about the user's actions. Add
this line of code after the if statement containing insert_record() in simplehtml.php:
add_to_log($id, 'block_simplehtml', 'insert page', $CFG-
>wwwroot.'blocks/simplehtml/view.php?courseid='.
$courseid.'&blockid='.$blockid,
'', 0, $USER->id);
The first parameter sent to add_to_log is the course id, which is passed via the url or
form to simplehtml.php. The second parameter is the block or module name. The third
paramater is the action taken, which is usually something simple. The fourth parameter is the
url from the referring page. The fifth parameter is additional information if the string
representing the action in the third parameter is not descriptive enough. The sixth parameter
is the id of the course module. The final parameter is the user id.
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 course main page
redirect("$CFG->wwwroot/course/view.php?id=$id");
} else if ($fromform = $simplehtml->get_data()) {
// we need to add code to appropriately act on and store the
submitted data
redirect("$CFG->wwwroot/course/view.php? id=$courseid");
} else {
//form didn't validate or this is the first display
$site = get_site();
print_header(strip_tags($site->fullname), $site->fullname,
'<a href="'.$CFG->wwwroot.'/course/view.php?id='.
$courseid.'">'.$course->shortname.
'</a> ->'.get_string('formtitle',
'block_simplehtml'), '',
'<meta name="description" content="'.
s(strip_tags($site->summary)) .'">',
true, '', '');
$simplehtml->display();
print_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:
o loads base moodle API and any necessary third party modules or non-base
API files
o loads the necessary course object and globals
o performs necessary access control
o 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 title element
$mform-
>addElement('text','pagetitle',get_string('pagetitle','block_simplehtm
l'));
$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');
The page will now display:
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('choosecoursefile', 'filename',
get_string('displayfile', 'block_simplehtml'),
array('courseid'=>$COURSE->id));
This 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. Notice that the code uses $COURSE->id:
this means that the $COURSE variable needs to be added to the global variables line next
to $CFG.
This next set of widgets allows optional display of a picture the user selects via a radio
button, and adds alternate text that is displayed with the image. You would most likely do
this directly via the HTML editor, but it's added to the form for illustration.
Fieldset Header
//add picturefields header
$mform->addElement('header', 'pictureinfo',
get_string('picturefields', 'block_simplehtml'));
Yes/No Select
// add display picture yes/no option
$mform->addElement('selectyesno', 'displaypicture',
get_string('displaypicture','block_simplehtml'));
$mform->setDefault('displaypicture', 1);
Note the default value for the display pictures is set to "yes."
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.
<?php
/**
* Library functions for the simplehtml block
**/
function block_simplehtml_images() {
global $CFG;
return array('<img src="' . $CFG->wwwroot .
'/blocks/simplehtml/pix/picture0.jpg" alt="'.get_string('red',
'block_simplehtml').'">',
'<img src="' . $CFG->wwwroot .
'/blocks/simplehtml/pix/picture1.jpg" alt="'.get_string('blue',
'block_simplehtml').'">',
'<img src="' . $CFG->wwwroot .
'/blocks/simplehtml/pix/picture2.jpg" alt="'.get_string('green',
'block_simplehtml').'">');
}
?>
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');
Add the referenced pictures above to the appropriate directory. Create a directory called
pix in your simplehtml block directory, and extract the following archive there. 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);
$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:
$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. Before the display function in view.php add:
$toform['blockid'] = $blockid;
$toform['courseid'] = $courseid;
$simplehtml->set_data($toform);
Add $blockid as a required parameter in the form display file view.php. Add this
code after $courseid = required_param('courseid',PARAM_INT);;
$blockid = required_param('blockid', PARAM_INT);
One final note: language strings have not been added to the language file
lang/en_utf8/block_simplehtml.php. Add the appropriate entries to the
language file. Remember the presence of a string surrounded by double square brackets
(e.g., somestring) indicates that the string is missing from a language definition. After adding
your language strings your form should look something like:
Process Form Data
Important notes
Use add_to_log() sparingly. Each block, module and other PHP code will be adding data
to the log table. The more information in the log table, the less useful it becomes and the slower
the database queries on the table.
Always use add_to_log() when a user performs actions such as adding, editing, and
deleting. Actions outside of add, edit, and delete should be used sparingly. For instance, it may
be useful for an instructor to know when (or if) a student has accessed certain material in the
course.
One of the more important administrative aspects wiithin Moodle is logging user actions. This
helps site administrators diagnose problems, catch cheaters, and in general figure out what a
user did to get to where they had a problem. This can also be invaluable to developers to
determine where in your code someone was able to get to before they had a problem. Of course,
the logs are also critical for teachers to monitor student activities in a course.
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
redirect("$CFG->wwwroot/course/view.php? id=$courseid");
}
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
(
[MAX_FILE_SIZE] => 2097152
[pagetitle] => This is my first simplehthml page
[displaytext] => Lorem ipsum dolor sit amet...
[filename] => blockimage1.gif
[displaypicture] => 1
[picture] => 0
[description] => Red is a great color
[displaydate] => 1222722600
[mform_showadvanced_last] => 1
[blockid] => 13
[courseid] => 2
[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:
if(!insert_record('block_simplehtml',$fromform)){
error(get_string('inserterror' , 'block_simplehtml'));
}
Notice that upon checking for a call to insert_record an okay status is returned; and if
not an error is produced. Now comment out the print_object() call and un-comment
the call to redirect(). Finally, test to see if the form submission and saving works
properly by submitting some data using the form. You can review that the data was stored in
the proper table by viewing the table block_simplehtml via phpmyadmin. You should see
something similar to the this:
Note if you receive an error, verify that your table exists in the database. 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.
Unit 7 - Part C - Refine the User Interface
Part A - Block Basics
1. Create a simple block following Moodle's tutorial. The block will be named "simplehtml."
2. Create a language file and directory.
3. Create a database table into which our block will insert information.
Part B - Forms
1. Add a form using the Moodle forms library to insert information into the table
o Define a new form.
o Display the new form.
o Add a header.
o Add access control.
o Add logging.
o Add form elements.
o Add state variables.
o Finalize the form.
2. Process the form.
Part C - Refine the User Interface
1. Add links to each page of the block.
2. Add methods to view pages.
3. Refactor display method.
o Add page title.
o Display the date
4. Display text.
5. Display link to file.
6. Display the picture.
Part D - Add Editing Capabilities
Add editing capabilities that allow users to edit data, including
1. Delete a page
2. Add a link to the delete.php file
3. Create the delete.php file
4. Clean up all data associated with the block with the instance_delete() function
Part E - Define a Role for the Block
1. Add check to the block for the capability
2. Add a role to the simplehtml form
3. Add a role to edit
4. Add a role to delete
Block Basics | Forms | Refine the User Interface | Add Editing Capabilities | Define a Role
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.
Add Links to Each Page of the Block
To retrieve the relevant rows call get_records(), which accepts three parameters::
1. the table name
2. the name of the column or field to be queried
3. the value of the queried field we want to match (note the use of $this-
>instance->id, which is the same as blockid within this scope)
Add the following code after $this->content->text = $this->config-
>text:
if($simplehtmlpages = get_records('block_simplehtml', 'blockid',
$this->instance->id)){
$this->content->text .= '<ul class="block-simplehtml-pagelist">';
foreach($simplehtmlpages as $simplehtmlpage){
$this->content->text .= '<li><a href="'.$CFG->wwwroot.
'/blocks/simplehtml/view.php?id='.
$simplehtmlpage->id.
'&courseid='.$COURSE->id.'">'.
$simplehtmlpage->pagetitle.'</a></li>';
}
$this->content->text .= '</ul>';
}
Add Methods to View Pages
Review the links created earlier to see that the file view.php is needed that will:
1. Check for any required variables; id (references the simplehtml page id), courseid
2. Verify the courseid given is a valid course
3. Verify the user is logged in
4. Verify thathte user has the appropriate permissions to view any output thescript may
generate
5. Retrieve the database record for the simplehtml page requested
6. Print the header for the page
7. Display the information for the page requested
8. Print the page footer
Many of these steps have previously been completed. Try to work through the list above,
skipping over the "display information for the page requested". Your code should look similar
to:
<?php
// include moodle API and any supplementary files/API
require_once('../../config.php');
require_once('simplehtml_form.php');
// declare any globals we need to use
global $CFG, $USER;
// check for all required variables
$id = required_param('id', PARAM_INT);
$courseid = required_param('courseid',PARAM_INT);
// ensure we have a valid courseid and can load the associated course
object
if (! $course = get_record('course', 'id', $courseid) ) {
error(get_string('invalidcourse', 'block_simplehtml', $courseid));
}
// ensure the user has access to this course
require_login($course);
// ensure the user has appropriate permissions to access this area
require_capability('block/simplehtml:viewpages',
get_context_instance(CONTEXT_COURSE, $courseid));
// ensure we have a valid simplehtml page id and can load the
associated page
if(!$simplehtmlpage = get_record('block_simplehtml', 'id', $id)){
error(get_string('nopage','block_simplehtml', $id));
}
// print the header and associated data
$site = get_site();
print_header(strip_tags($site->fullname), $site->fullname,
'<a href="'.$CFG->wwwroot.'/course/view.php?id='.$courseid.'">'.
$course->shortname.
'</a> ->'.$simplehtmlpage->pagetitle, '',
'<meta name="description" content="'. s(strip_tags($site-
>summary)) .'">', true, '', '');
// display page information
// print the footer
print_footer();
?>
Note the use of a third parameter with get_string(). The third parameter allows
Moodle's translation system to substitute variables in proper locations after being translated.
Consider one example from the above code.
error(get_string('invalidcourse', 'block_simplehtml', $courseid));
This calls get_string() searching for 'invalidcourse' in the 'block_simplehtml' language
file, and finally it passes in $courseid. Then in the language file for the block this string will
have acess to the value passed in through the third paramter as $a.
$string['invalidcourse'] = 'The courseid $a does not exist';
Refactor Display Method
To avoid any code duplication and make it easy to reuse this functionality create a function in
lib.php 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'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.
function block_simplehtml_print_page($simplehtml, $return = FALSE){}
Important Tip
The function block_simplehtml_print_page uses
block_simplehtml in the beginning of the function name to avoid any
namespace collisions. Namespace collisions are important to consider when naming variables and
functions in Moodle beause Moodle has many hooks that call different functions at different times. It is
generally considered good practice to preface a varable or function name with the name of the block or
module to avoid problems with namespace collisions.
Now consider what the function needs to do in order to display all of the necessary
information from our page.
Page Title
Print this out as a centered header for the HTML PAGE
Display Text
Print this out in whatever format the user specified, centered in a box on the page
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.
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
Display date
Display the date under the page title in a smaller font
Add Page Title
To display the page title use moodle's print_heading() function. Add the following to
block_simplehtml_print_page() in lib.php
$output = print_heading($simplehtml->pagetitle, 'center', 2, 'main',
TRUE);
The parameters in order are 'text', 'text-alignment', 'header size', 'css class', and finally
whether to directly print the output or return it.
Display the Date
The requirements for date display call for displaying the date ni a smaller font under the page
title. First, display the date. Moodle has a userdate() function that has several
advantages over PHP's date() function. It displays the date in the user's preferred format
and adjusts the date for any timezone difference.
if ($simplehtml->displaydate) {
$output .= userdate($simplehtml->displaydate);
}
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's no output. Add some additional code that
handles the value of $return. Add the following at the end of the function definition:
if ($return) {
return $output;
}
else {
print $output;
}
Now try refreshing your page. You should see something like:
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.
First, add a div tag around the date, and give it a class to target with CSS later. Change the
date output line:
$output .= '<div class="simplehtml
displaydate">'.userdate($simplehtml->displaydate).'</div>';
There are two options for adding the stylesheet:
1. Add the CSS to the theme's CSS files in the theme directory
2. Create a styles.php file in the block and add the CSS there
Choosing the second option, adding a styles.php file, allows more flexibility and avoids
needing to create multiple entries if the site is using more than one theme. Create
styles.php and add this CSS:
.simplehtml.displaydate {
font-size: .8em;
text-align: center;
}
Now refresh the page and the date should be displayed properly.
Display Text
Now the display text needs to be added to a box.
Within moodle there are two ways to display a box:
1. print_box() and
2. a combination of print_box_start() and print_box_end().
The output is the same; which one you choose is mostly a matter of preference. To add two
different pieces of data to the box, display text and the file link, the example code uses
print_box_start() and print_box_end() for readability.
$output .= print_box_start('generalbox', '', TRUE);
$output .= clean_text($simplehtml->displaytext);
$output .= print_box_end(TRUE)
Display Link to File
To generate a file URL call the function get_file_url(), but the function is defined in
lib/filelib.php and is not a part of the core moodle API. So ensure you have access
to this file by calling include_once(). Add the following near the top of the function:
global $CFG, $COURSE;
include_once($CFG->dirroot.'/lib/filelib.php');
Now add the following lines just before the call to print_box_end()
$fileurl = get_file_url($COURSE->id.'/'.$simplehtml->filename);
$output .= '<br /><a href="'.$fileurl.'">'.get_string('viewfile',
'block_simplehtml').'</a>';
Notice that providing more than just the filename of the file to create a proper URL is
necessary. The course id for the course in question must also be provided.
Display the Picture
To selectively display the picture with its description text located to the right of it:
if ($simplehtml->displaypicture) {
$images = block_simplehtml_images();
$output .= print_box_start('generalbox', '', TRUE);
$output .= $images[$simplehtml->picture];
$output .= $simplehtml->description;
$output .= print_box_end(TRUE);
}
The page should now look like:
Unit 7 - Part D - Add Editing Capabilities
Part A - Block Basics
1. Create a simple block following Moodle's tutorial. The block will be named "simplehtml."
2. Create a language file and directory.
3. Create a database table into which our block will insert information.
Part B - Forms
1. Add a form using the Moodle forms library to insert information into the table
o Define a new form.
o Display the new form.
o Add a header.
o Add access control.
o Add logging.
o Add form elements.
o Add state variables.
o Finalize the form.
2. Process the form.
Part C - Refine the User Interface
1. Add links to each page of the block.
2. Add methods to view pages.
3. Refactor display method.
o Add page title.
o Display the date
4. Display text.
5. Display link to file.
6. Display the picture.
Part D - Add Editing Capabilities
Add editing capabilities that allow users to edit data, including
1. Delete a page
2. Add a link to the delete.php file
3. Create the delete.php file
4. Clean up all data associated with the block with the instance_delete() function
Part E - Define a Role for the Block
1. Add check to the block for the capability
2. Add a role to the simplehtml form
3. Add a role to edit
4. Add a role to delete
Block Basics | Forms | Refine the User Interface | Add Editing Capabilities | Define a Role
Students and teachers can view links and the teacher can create links, but what happens if
they make a mistake? There is no way to edit anything that has previously been entered.
Good developers want their blocks to be used, which means the block needs to include a way
for the user to edit the existing data. A way to edit what a user entered must be added to the
simplehtml block. The edit feature will use an image to link to the edit.php instead of text.
This image will only appear when the instructor turns editing on.
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'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.
Before displaying the added edit image and link verify that editing has been turned on
(checking that the user has appropriate permissions is covered in the last section, Access
Controls). The function isediting() is used to determine if the user has editing turned
on for the course. The isediting() function is passed the pageid for the block
instance, which in most cases is the same as courseid. Edit the block_simplehtml.php file, as
follows:
if($simplehtmlpages = get_records('block_simplehtml', 'blockid',
$this->instance->id)){
$this->content->text .= '<ul class="block-simplehtml-pagelist">';
foreach($simplehtmlpages as $simplehtmlpage){
if ($canmanage) {
$edit = '<a
href="'.$CFG->wwwroot.'/blocks/simplehtml/view.php?id='
.$simplehtmlpage->id.'&blockid='.$this-
>instance->id.'&courseid='.
$COURSE->id.'"><img src="'.$CFG-
>pixpath.'/t/edit.gif" alt="'.
get_string('editpage',
'block_simplehtml').'" /></a>';
} else {
$edit = '';
}
$this->content->text .= '<li><a href="'.$CFG->wwwroot.
'/blocks/simplehtml/view.php?id='.
$simplehtmlpage->id.
'&courseid='.$COURSE->id.'">'.
$simplehtmlpage->pagetitle.'</a>'.$edit.'</li>';
}
$this->content->text .= '</ul>';
}
Notice that there'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.
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 simplehtml_form.php :
$mform->addElement('hidden','id','0');
Second, add an optional parameter to the form to track the id in the event you update an
existing page. Add the following code to view.php
$id = optional_param('id',0, PARAM_INT);
Third, adjust the first time display or failed form validation display portion of view.php to
load necessary data when $id is present:
//form didn't validate or this is the first display
if ($id != 0) {
if (!$toform = get_record('block_simplehtml', 'id', $id)) {
error(get_string('nopage', 'block_simplehtml', $id));
}
} else {
$toform = new stdClass;
}
$toform->blockid = $blockid;
$toform->courseid = $courseid;
$site = get_site();
print_header(strip_tags($site->fullname), $site->fullname,
'<a href="'.$CFG->wwwroot.'/course/view.php?id='.
$courseid.'">'.$course->shortname.
'</a> ->'.get_string('formtitle', 'block_simplehtml'),
'',
'<meta name="description" content="'. s(strip_tags($site-
>summary)) .'">', true, '', '');
$simplehtml->set_data($toform);
$simplehtml->display();
print_footer();
Notice that handling of the $toform variable has been adjusted. It is now an object rather
than an array. This is to provide consistency regardless of whether we are adding a new page
or updating an existing one.
Finally, change the code to conditionally update or insert a new record. In the middle
conditional block (elseif) adjust as follows to update records when the id field is non-zero
// add code to appropriately act on and store the submitted data
if ($fromform->id != 0) {
if (!update_record('block_simplehtml', $fromform)) {
error(get_string('updateerror', 'block_simplehtml'));
}
add_to_log($blockid, 'block_simplehtml', 'update page', $CFG-
>wwwroot.
'blocks/simplehtml/view.php?blockid='.
$blockid.'&courseid'.
$courseid, '', $blockid, $USER->id);
} else {
if (!insert_record('block_simplehtml',$fromform)) {
error(get_string('inserterror' , 'block_simplehtml'));
}
add_to_log($id, 'block_simplehtml', 'insert page', $CFG-
>wwwroot.'blocks/simplehtml/view.php?courseid='.$courseid.'&blockid='.
$blockid,
'', 0, $USER->id);
}
redirect("$CFG->wwwroot/course/view.php? id=$courseid");
Page Deletion
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::
1. Add a link to a new delete.php file
2. Create the delete.php file
3. Print a verification form to the screen in case the user made a mistake
4. Use delete_record() to delete a record from the simplehtml table given an id
and a confirmation.
Add a Link to delete.php
Begin by editing block_simplehtml.php and creating a link just after the edit link.
$delete = '<a href="'.$CFG->wwwroot.'/blocks/simplehtml/delete.php?
id='.
$simplehtmlpage->id.'&courseid='.$COURSE->id.'"><img
src="'.
$CFG->pixpath.'/t/delete.gif" alt="'.
get_string('deletepage','block_simplehtml').'" /></a>';
Remember to set the links to a blank string if the user doesn't have the correct permissions:
if ($canmanage) {
$edit = '<a href="'.$CFG->wwwroot.'/blocks/simplehtml/view.php?
id='
.$simplehtmlpage->id.'&blockid='.$this->instance-
>id.'&courseid='.
$COURSE->id.'"><img src="'.$CFG->pixpath.'/t/edit.gif"
alt="'.
get_string('editpage', 'block_simplehtml').'" /></a>';
$delete = '<a
href="'.$CFG->wwwroot.'/blocks/simplehtml/delete.php?id='.
$simplehtmlpage->id.'&courseid='.$COURSE->id.'"><img
src="'.
$CFG->pixpath.'/t/delete.gif" alt="'.
get_string('deletepage','block_simplehtml').'"
/></a>';
} else {
$edit = '';
$delete = '';
}
$this->content->text .= '<li><a href="'.$CFG->wwwroot.
'/blocks/simplehtml/view.php?id='.
$simplehtmlpage->id.
'&courseid='.$COURSE->id.'">'.
$simplehtmlpage->pagetitle.'</a>'.$edit.$delete.'</li>';
}
Create delete.php
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's similar to what has been used for most of the other
files like view.php and simplehtml.php).
<?php
require_once('../../config.php');
global $CFG, $USER, $SITE;
$courseid = required_param('courseid',PARAM_INT);
$id = optional_param('id',0, PARAM_INT);
$confirm = optional_param('confirm',0,PARAM_INT);
if (! $course = get_record('course', 'id', $courseid) ) {
error(get_string('invalidcourse', 'block_simplehtml'). $courseid);
}
require_login($course);
require_capability('block/simplehtml:managepages',
get_context_instance(CONTEXT_COURSE, $courseid));
if(! $simplehtmlpage = get_record('block_simplehtml', 'id', $id)){
error(get_string('nopage','block_simplehtml',$id));
}
$site = get_site();
print_header(strip_tags($site->fullname), $site->fullname,'<a href="'.
$CFG->wwwroot.
'/course/view.php?id='.$courseid.'">'.$course->shortname.'</a> -
>'.
$simplehtmlpage->pagetitle, '','<meta name="description"
content="'.
s(strip_tags($site->summary)) .'">',true, '', '');
print_footer();
?>
This common code:
Checks the courseid corresponds to a valid course
Checks that the user is logged in
Checks that the simplehtml page id corresponds to an existing page id
Prints out the header and footer for the page
Notice that this is similar to what has been used so far, but there another optional parameter
'confirm' has been added.
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
print_header() function:
Important Tip!
Most IDEs and programmer's text editors allow you to create templates for commonly used
code snippets. Turning sections of code you use often into templates can save a lot of time
and typing!
if(!$confirm){
$optionsno = array('id'=>$courseid);
$optionsyes = array ('id'=>$id,
'courseid'=>$courseid,'confirm'=>1, 'sesskey'=>sesskey());
print_heading(get_string('confirmdelete', 'block_simplehtml'));
notice_yesno(get_string('deletepage', 'block_simplehtml',
$simplehtmlpage->pagetitle), 'delete.php',
$CFG->wwwroot.'/course/view.php', $optionsyes,
$optionsno, 'post', 'get');
}
else {
if (confirm_sesskey()) {
if (! delete_records('block_simplehtml','id',$id)) {
error('deleterror','block_simplehtml');
}
}
else {
error('sessionerror','block_simplehtml');
}
add_to_log($id, 'block_simplehtml', 'delete page', $CFG-
>wwwroot.'course/view.php?&id='.
$courseid, '', $id, $USER->id);
redirect("$CFG->wwwroot/course/view.php?id=$courseid");
}
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 "yes" or
"no." They are passed to the notice_yesno() function as the fifth and sixth
parameters. If the user clicks "no" they are sent to the course page, which means the
courseid needs to be added to the form. If the user clicks "yes" 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.
Now take a look at the parameters passed the notice_yesno() function. The first
parameter is the text string that is displayed before the Yes and No buttons. The second
parameter is the url where the form sends the user when they click the yes button.The third
parameter is the url to where the user will be sent if they click on the no button. The sixth
and seventh parameters are the http methods (Get or Post) used to send the form data for
the yes and no buttons.
Final Cleanup
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 the block. In this function call the delete records and use the
blockid to pass in the $this->instance->id variable. The function looks like this:
function instance_delete(){
delete_records('simplehtml','blockid', $this->instance->id);
}
Unit 7 - Part E - Define a Role for the Block
Part A - Block Basics
1. Create a simple block following Moodle's tutorial. The block will be named "simplehtml."
2. Create a language file and directory.
3. Create a database table into which our block will insert information.
Part B - Forms
1. Add a form using the Moodle forms library to insert information into the table
o Define a new form.
o Display the new form.
o Add a header.
o Add access control.
o Add logging.
o Add form elements.
o Add state variables.
o Finalize the form.
2. Process the form.
Part C - Refine the User Interface
1. Add links to each page of the block.
2. Add methods to view pages.
3. Refactor display method.
o Add page title.
o Display the date
4. Display text.
5. Display link to file.
6. Display the picture.
Part D - Add Editing Capabilities
Add editing capabilities that allow users to edit data, including
1. Delete a page
2. Add a link to the delete.php file
3. Create the delete.php file
4. Clean up all data associated with the block with the instance_delete() function
Part E - Define a Role for the Block
1. Add check to the block for the capability
2. Add a role to the simplehtml form
3. Add a role to edit
4. Add a role to delete
Block Basics | Forms | Refine the User Interface | Add Editing Capabilities | Define a Role
Hyperlinks appear in new browser windows.
With the table established, create a capability to allow the Moodle Administrator to determine
which roles can add links to the simple html block. Read the Programming Interface section
of Moodle docs to get a basic idea of how to create a capability. Create two capabilities for
this block:
1. View simplehtml page(s) which will be block/simplehtml:viewpages
2. Modify/add simplehtml page(s) which will be block/simplehtml:managepages
Following the instructions in the Programming Interface section of Moodle docs, create an
access.php file in the blocks/simplehtml/db directory. In that file add the simplehtml
capability array:
<?php
/*
* Capabilities for simplehtml block
*/
$block_simplehtml_capabilities = array(
);
?>
Next add the two capabilities arrays, block/simplehtml:viewpages and
block/simplehtml:managepages to the above array. Each array should have the following
attributes:
block/simplehtml:viewpages
o type: read
o context: course
o Legacy:
Guest: prevent
Student: allow
Teacher: allow
Editing teacher: allow
Coursecreator: allow
Admin: allow
block/simplehtml:managepages
o type: write
o context: course
o Legacy:
Guest: prevent
Student: prevent
Teacher: prevent
Editing teacher: allow
Coursecreator: allow
Admin: allow
In the end, your access.php should look like:
<?php
/*
* Capabilities for simplehtml block
*/
$block_simplehtml_capabilities = array(
'block/simplehtml:viewpages' => array(
'captype' => 'read',
'contextlevel' => CONTEXT_COURSE,
'legacy' => array(
'guest' => CAP_PREVENT,
'student' => CAP_ALLOW,
'teacher' => CAP_ALLOW,
'editingteacher' => CAP_ALLOW,
'coursecreator' => CAP_ALLOW,
'admin' => CAP_ALLOW
)
),
'block/simplehtml:managepages' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_COURSE,
'legacy' => array(
'guest' => CAP_PREVENT,
'student' => CAP_PREVENT,
'teacher' => CAP_PREVENT,
'editingteacher' => CAP_ALLOW,
'coursecreator' => CAP_ALLOW,
'admin' => CAP_ALLOW
)
)
);
?>
Now bump the version number up in blocks/simplehtml/block_simplehtml.php. Change
the last 0 to a 1 where you set $this->version. The line should look like:
$this->version = 2008010101;
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 > Permissions >
Define roles and selecting Administrator. Search for simplehtml.
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 lang/en_utf8/block_simplehtml.php:
$string['simplehtml:viewpages'] = 'View Simple HTML Pages';
$string['simplehtml:managepages'] = 'Manage Simple HTML
Pages';
With the problem fixed, your Define Roles page will now look like:
In this part of the unit so far, you have learned how to create a basic block with all the
standard functions that Moodle needs to display the block with some limited configuration.
You have learned how to create a database table using the XMLDB editor in Moodle, added a
new language file for the block, and created capabilities that a block can use to determine if
a user has the correct permissions. Next you will work on creating a form to add information
to the database table you created.
Add check to the block for the capability
With the two new capabilities created, it's time to use them and add a link to the soon-to-be-
created form in the block. The easiest place to add the link is in the footer, but it's critical
that the person viewing this link has the capability to manage 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. But first add the global variable $COURSE and $CFG to the function
using:
global $COURSE, $CFG;
To check if the user has the correct view permissions replace:
$this->content->text = $this->config->text;
with
$context = get_context_instance(CONTEXT_COURSE, $COURSE-
>id);
if (has_capability('block/simplehtml:viewpages', $context))
{
$this->content->text = $this->config->text;
} else {
$this->content->text = '';
}
To add the link to the form replace:
$this->content->footer = '';
with:
if (has_capability('block/simplehtml:managepages',
$context)) {
$this->content->footer = '<a href="'. $CFG->wwwroot.
'/blocks/simplehtml/simplehtml
.php?blockid='.
$this->instance->id.'&courseid='.
$COURSE->id.'">'.
get_string('addpage','block_simplehtml').'</a>';
} else {
$this->content->footer = '';
}
Your final get_content() should look like:
function get_content() {
global $COURSE, $CFG;
if ($this->content !== NULL) {
return $this->content;
}
$this->content = new stdClass;
$context = get_context_instance(CONTEXT_COURSE, $COURSE->id);
if (has_capability('block/simplehtml:viewpages', $context)) {
$this->content->text = $this->config->text;
}
else {
$this->content->text = '';
}
if (has_capability('block/simplehtml:managepages', $context)) {
$this->content->footer = '<a href="'. $CFG->wwwroot .
'/blocks/simplehtml/page.php?blockid='.
$this->instance->id.'&courseid='.
$COURSE->id.'">'.
get_string('addpage',
'block_simplehtml').'</a>';
}
else {
$this->content->footer = '';
}
return $this->content;
}
Notice while building the link that $this->instance->id is used. This is an identifier
that is unique to each block instance in a course and enables the use of multiple blocks in a
course. Courseid is also used, along with the block instance id, to easily find all pages
associated with the block for a course. The link to page.php is also sent, which is non-
existent; it will be added with the necessary code in the next section.
While constructing our link, get_string() is also used, so an entry for the string
'addpage' will need to be added to the language file for the block with text of your
choice.
Finally, refresh the Moodle course to which you have added the simplehtml block. As an
administrator or teacher you should see the 'addpage' link; as a student you should not see
the link.
Add Role to the simplehtml Form
Currently any logged in user can use the simplehtml form. In development this is not as big
of a concern, but before moving intro production always ensure that users have access only
to those portions of the application that they should. In page.php after
require_login($course); add the following line:
require_capability('block/simplehtml:managepages',
get_context_instance(CONTEXT_COURSE, $courseid));
This ensures the user cannot access this page without having the capability
'block/simplehtml:managepages'.
Add Role to Editing
Restrict editing to users who have the block/simplehtml:managepages capability by adding
access control to the editing action. In edit.php use the variable $canmanage to determine
access. Set this variable by verifying the user has the proper capability.
$canmanage = isediting($course->id) &&
has_capability('block/simplehtml:managepages',
get_context_instance(CONTEXT_COURSE, $courseid));
Add Role to Delete
To restrict deletion to those who have the managepages capability, add the following line to
delete.php after require_login($course);
require_capability('block/simplehtml:managepages',
get_context_instance(CONTEXT_COURSE, $courseid));
Unit 8: Testing MethodsOverview | Unit 8 "To Do" List
External resources will open in new browser windows.
Software Testing and Q.A. (Quality Assurance) is a big topic, although it is also a very
important topic to all programmers. Big companies usually have dedicated software Q.A.
engineers responsible only for software testing or QA.
Although crucial to software quality and widely deployed by programmers and testers,
software testing still remains an art, due to limited understanding of the principles of
software. The difficulty in software testing stems from the complexity of software: we can not
completely test a program with moderate complexity. [Software-Engineering. (2002). Hagen:
Fernuniv., Fachbereich Informatik.]
Testing is more than just debugging. The purpose of testing can be quality assurance,
verification and validation, or reliability estimation. Testing can be used as a generic metric
as well. Correctness testing and reliability testing are two major areas of testing. Software
testing is a trade-off between budget, time and quality.[Software Testing. (1999). Pan:
Carnegie Mellon University.] More detail on software quality assurance.
In this unit we will focus on some topics that are particularly important to Moodle developers.
Black Box Testing
According to Wikipedia (2-14-08):
"Black box testing takes an external perspective of the test object to derive test cases. These
tests can be functional or non-functional, though usually functional. The test designer selects
valid and invalid input and determines the correct output. There is no knowledge of the test
object's internal structure.
This method of test design is applicable to all levels of software testing: unit, integration,
functional testing, system and acceptance. The higher the level, and hence the bigger and
more complex the box, the more one is forced to use black box testing to simplify. While this
method can uncover unimplemented parts of the specification, one cannot be sure that all
existent paths are tested."
Users might want to evaluate or compare new versions of Moodle before making a final
decision on upgrading. The "black box testing" of the new code base from an end user’s
perspective--identifying possible issues--can be valuable.
White Box Testing
According to Wikipedia (2-14-08):
"White box testing (a.k.a. clear box testing, glass box testing or structural testing) uses an
internal perspective of the system to design test cases based on internal structure. It requires
programming skills to identify all paths through the software. The tester chooses test case
inputs to exercise paths through the code and determines the appropriate outputs ... Since
the tests are based on the actual implementation, if the implementation changes, the tests
probably will need to also."
For example, if an important function in the Moodle quiz module changes, then most quiz test
cases probably need to be reviewed as well.
"While white box testing is applicable at the unit, integration and system levels of the
software testing process, it is typically applied to the unit. While it normally tests paths within
a unit, it can also test paths between units during integration, and between subsystems
during a system level test. Though this method of test design can uncover an overwhelming
number of test cases, it might not detect unimplemented parts of the specification or missing
requirements, but one can be sure that all paths through the test object are executed."
Regression Test
According to Wikipedia (2-14-08):
"Regression testing is any type of software testing which seeks to uncover regression bugs.
Regression bugs occur whenever software functionality that previously worked as desired,
stops working or no longer works in the same way that was previously planned. Typically
regression bugs occur as an unintended consequence of program changes.
Common methods of regression testing include re-running previously run tests and checking
whether previously fixed faults have re-emerged."
A typical example of using regression testing is to verify whether new bug fixes in Moodle
actually introduced other new bugs. Other than the 'manual' way of testing, you might find
using automated testing tools such as "Selenium IDE" with some pre-established test cases
would be very helpful to verify whether the test cases still behave the same way. "Selenium
IDE" will be explored in more detail later.
top
Unit Test
According to Wikipedia (2-14-08):
"In computer programming, unit testing is a procedure used to validate individual units of
source code are working properly. A unit is the smallest testable part of an application. In
procedural programming a unit may be an individual program, function, procedure, etc.,
while in object-oriented programming, the smallest unit is a method; which may belong to a
base/super class, abstract class or derived/child class."
Once unit testing has given you the confidence that each part works, then you should use
other forms of testing to ensure that the different parts work together properly.
Moodle has a built in unit test framework which is based on a SimpleTest framework. Later
we will discuss how to use this framework.
Refer to these helpful resources for additional information: “unit testing” in general; test
design techniques, Moodle's unit tests.
Moodle’s own “Unit tests” is a tool for Moodle developers to evaluate Moodle codes and is
found in the Administration block under Reports when logged in as a Moodle system
administrator.
Unit tests can be one of the first steps in a quality control process for developing or tweaking
Moodle code.
Selenium Cases
According to OpenQA (2-14-08):
"Selenim IDE is an Integrated Development Environment for Selenium tests. It is
implemented as a Firefox extension, and allows you to record, edit, and debug tests.
Selenium IDE includes the entire Selenium Core, allowing you to easily and quickly record
and play back tests in the actual environment that they will run.
Selenium IDE is not only a recording tool: it is a complete IDE. You can choose to use its
recording capability, or you may edit your scripts by hand. With autocomplete support and
the ability to move commands around quickly, Selenium IDE is the ideal environment for
creating Selenium tests no matter what style of tests you prefer.
Features of Selenium IDE are
Easy record and playback
Intelligent field selection will use IDs, names, or XPath as needed
Autocomplete for all common Selenium commands
Walk through tests
Debug and set breakpoints
Save tests as HTML, Ruby scripts, or any other format
Support for Selenium user-extensions.js file
Option to automatically assert the title of every page"
To use Selenium IDE for Moodle testing, you can record a sequence of interactions with your
Moodle site, and later play them back and see if they still work after you tweak some of the
Moodle codes.
There are some limitations applying Selenium IDE to Moodle:
Selenium will not wait for 'Continue' redirects to happen. When recording a sequence
of actions, you need to click on the continue links manually.
By default, it tends to record actions using ids, and in Moodle these sometimes
contain arbitrary database ids. For example, submitting a quiz question, it will record
clickAndWait resp94_submit. However, you can edit this to say
clickAndWait //input[@value='Submit'].
At other times, by default, it is not specific enough. For example, deleting a course, it
records //a[img/@alt='Delete'] which will just delete the first course
listed! Again, you can edit it to something like //a[img/@alt='Delete' and
../../td[1]/a='Selinium quiz test course'], which will delete
a named course.
It sometimes doesn't work with pop-up windows even though it should support them.
Additional information about how to use Selenium to design some automated tests for
Moodle, is available at Moodle's "Quiz and questions community testing day" and in the
discussion forum post by Tim Hunt, "Selinium [sic] for testing Moodle".
top
"To Do" List
As part of this Unit's activities, follow the instructions below to (1) run the basic "unit test"
tests, (2) write your own unit test code, and (3) create a Selenium case.
1. Run basic unit tests.
Use these steps to perform a basic Moodle “unit" test.
a. Log in with an admin account.
b. Go to the Site Administration block
c. Click on the Reports link near the bottom of the block on the lower right
corner.
d. Click on the Unit tests link
e. Click on the Run tests button. (You could select the options that you want
here, we will explain these options below).
f. Wait for the tests to complete.
Options for Running the Tests
o Show passes as well as fails. Normally, only details of the tests that have
failed are printed. Turning on this option shows details of all the successful
passes too.
o Show the search for test files. The tests to run are found automatically be
searching the codebase for files whose names match test*.php in directories
called simpletest. Turning on this option will print a list of the folders
searched and the test files found. This is sometimes useful for debugging but
is particularly useful when one of your test files has a syntax error. When this
happens, you sometimes just get a blank page with no error message.
Turning on the show search option lets you see which test file it was that
gave the error. If necessary, you can enable this option manually by adding
"showsearch=1" to the end of the URL.
o Run a thorough test (may be slow). If you turn on this option, then as well
as looking for files called test*.php, the search also looks for files called
slowtest*.php. To be useful, the full test run should find most bugs, but not
take too long to complete. So if you have very, very detailed tests of an area
of the code, it may be better to select a subset for everday testing, and only
use the more detailed tests when a bug is reported, or you are doing new
development in that area of the code. This option is most useful when
combined with the next option.
o Only run tests in [textfield]. Normally, tests from all parts of the codebase
are run. However, when you are just doing development of one part of the
code, this is a waste of time. You can type the name of a directory (for
example mod/quiz) or a particular test file (for example
lib/simpletest/testdatalib.php) and then only those tests will be run.
Pass: lib/simpletest/testdatalib.php ->
datalib_test ->
test_get_record -> False xxxxxxxxx get False at
[/var/www/html/tjh238/head/lib/simpletest/testdat
alib.php line
92]
Instead of typing a path into this box, there is an easier way. Whenever a
pass or fail is displayed, the name of the test file is printed. Each section of
the path name is a link to run only the tests in that folder or file.
top
2. Write Test Code
Continuing with the example "simplehtml" from Unit 7, write a unit test for the
function block_simplehtml_convert_unixtime in the file
/blocks/simplehtml/lib.php.
To get a better understanding of how to create codes for unit tests, browse through
these files:
[For testing GROUPS]
/group/simpletest/test_basicgrouplib.php (Unit tests for new Moodle Groups –
basicgrouplib.php and some functions in utillib.php)
/group/simpletest/test_groupinglib.php (Unit tests for new Moodle Groups – groupinglib.php)
Create a directory called /blocks/simplehtml/testlib and create a file in it named
test_lib.php. The actual content of this file should look like:
<?php
require_once(dirname(__FILE__) . '/../../config.php');
global $CFG;
require_once($CFG->libdir . '/simpletestlib.php');
require_once($CFG->dirroot .
'/group/lib/basicgrouplib.php');
require_once($CFG->dirroot . '/group/lib/utillib.php');
class basicgrouplib_test extends UnitTestCase {
var $courseid= 0;
var $userid = 0;
var $userid_2= 0;
var $groupid = 0;
function __construct() {
parent::UnitTestCase();
}
function test_block_simplehtml_convert_unixtime() {
xxxxx
}
}
?>
That is, you have a class called something_test, and in that class you have lots of methods
called test_something. Normally,there is one test method for each function to test, and you
may as well call the test method test_name_of_function_being_tested. In this example, this
method can be called test_block_simplehtml_convert_unixtime.
How to write test case documents
Moodle has a preliminary standard to build up test cases. These test cases basically are some
"scenarios" that should be run in Moodle before each release. Currently this test plan is far
from perfect, although more people in the Moodle community are starting to contribute more
test cases on the Moodle documentation wiki (http://docs.moodle.org).
The existing scenarios should be run in the downloaded Moodle Test Course. Here are some
general rules:
Test Case Naming conventions:
o [AAA] : Three characters that represent the block or module name
o [000] : Three digits that number the question
o [A] : Potential actor = S: student, T: teacher, A: admin
The testing plans are categorized by modules:
o Tests/Assignment
o Tests/Chat
o Tests/Choice
o Tests/Forum
o Tests/Quiz
o Tests/Resource
top
Using "simplehtml" as an example, following is a typical test case:
[Sim001TAS] : Adding Simplehtml block from the block pull-down menu________________________________________
a. Click the "Turn editing on" button on the top right corner window.
b. From the Blocks pull-down menu, find the "simplehtml" block on the list of blocks
available
c. Choose the "simplehtml" block from the menu
d. Does the "simplehtml" block display correctly? The default will show up on the right
hand side of the browser window. There should be no missing strings, etc.
More information about how to write a Moodle test case document is available at Moodle
Docs.
top
3. Try Selenium.
a. Read OpenQA's Using Selenium IDE and Recording a Test (note the movie
that illustrates the steps for the test near the top under the "View" tab).
b. Install Selenium IDE from Open QA's Selenium IDE Downloads page.
c. Download the Moodle Selenium example file and unzip it (say, in c:\xampp\
moodle\)
d. In Firefox, go to your local moodle installation (e.g,. http://localhost/moodle/)
e. Login as admin
f. Start Selenium IDE from the Firefox tools menu.
g. From the Selenium menu, select File-> Open and open the file
"Createquiz.selenium.html" from the unzipped file in Step 2.
h. In the list of commands, look at the sixth one from the end--where it says
"type newfile c:\Documents and Settings\TJH239\Desktop\Selenium tests\Test
question suite.xml." Change that file path to point to your copy of "Test
question suite.xml" from the unzipped file.
i. Click the green play button in the Selenium toolbar. The test script will
automatically:
create a new course
add a quiz to it
import 12 sample questions
add those questions to a quiz
j. Next, open 'Test matching - basic in quiz preview.selinium.html' and run it
(no editing required this time). This runs through one of the test questions a
few times.
k. Finally, open "Delete test course.selinium.html", and run it to remove the test
course and get back to where you started.
l. Review the "Test question suite.xml" to see what is does, try to tweak it a
little bit to understand how Selenium works.
4. Complete the three Assignments and submit them in the designated Assignment
areas.
a. [Test Case] Follow the Moodle test case convention to write a simple test
case (scenario) for testing Gradebook Plus version 2 (aka GBPv2).
Consider a focus on testing one of the basic features in GBPv2. For example,
adding a graded event, using the "edit grade" tab with out-of-bound values,
etc. Submit your test case as an online text document in the Assignment
area. Naming conventions and format for the Moodle test case must be
observed.
b. [Selenium] Design a Selenium case to automatically:
Use your local development Moodle installation (Moodle 1.8).
Login as Admin.
Select the Moodle Test Case Course that you installed before.
Click on "Grades" (gradebook).
Click on the button of "Download in Excel format" button
Manually check the content to see if everything works correctly.
Write a simple code snippet using Moodle’s "unit tests" framework to
test a particular function (you pick) in GBPv2. For example, the
function of "grade_get_category_weight()" or
"grade_get_grade_items()" in /grade/lib.php
c. [Moodle Unit Test] Write a simple code snippet using Moodle's "unit tests"
framework to test a particular function (you pick) in GBPv2. For example, the
function of grade_get_category_weight() or
grade_get_grade_items() in /grade/lib.php.
5. Share your thoughts on the discussion topics for this Unit.
Unit 9: Requirements DocumentsOverview | Unit 9 "To Do" List
External resources will open in new browser windows.
Requirements documents are the glue that holds communication between a programmer and
a user together. In this unit we will explain how to develop a requirements document that will
help to solidify the reason a project should be completed, reduce feature creep, assist in
quality assurance, as well as identify what functionality a programmer should be working to
create.
Throughout this unit we will be referring to the structure of a requirements document as
described in the PDF file, "Writing a Software Requirements Document." Please use this as a
reference and read it thoroughly. Also read through NASA's document, Writing Effective
Requirements Specifications, to get an idea of how to word a requirements document for the
best possible readability.
Why Write a Requirements Document?
"Products with the lowest defect counts also have the shortest schedules." M. Tim Jones in
Version Control for Linux: Overview of architectures, models, and examples.
A requirements document:
Is a starting point to ensure you do it right meaning you deliver what the customer
wants at a quality level that is acceptable.
Can be used as a loose "contract" defining what functionality will be delivered.
Is written such that everybody involved can understand the document including
customer, project manager, developer, and testers.
Assures the customer that the development team understands what it is that they
want.
Lists clearly features that must be present in the finished project. For example, it is a
written document of what the software will do.
Provides a clear starting point for testing functionality.
Is a clear starting point for creating user documentation.
Settles any disputes between the customer and the development team
Will list no more and no less than what is required.
Serves as a reference point to do a feature-freeze. That is, if the requested
functionality changes, then a new requirements document is created and the
customer must take part in this process to understand the impact of making changes
late in a project's life-cycle. This can also serve as a starting point for delivering
functionality in versions.
Does not focus on how the software will accomplish the tasks necessary. This is often
best left to the programmer who will be the most knowledgeable and capable of
making implementation decisions.
Should be tailored to the application. If the application is large or may be easily
misunderstood or misinterpreted then the requirements document will most likely
need to be more detailed. However you should write so that it is easily understood.
top
The User Interview
Before you can write a requirements document you must first determine the requirements.
One of the best ways of doing this is talking to a user or group of users, whether these users
are faculty, administrators, or students depends on the type of project. Interviewing the user
face to face or over the phone allows the programmer, project manager, and user to do the
following:
1. Come to a common understanding of the project requirements
2. Discuss important decisions about the features of the project
3. Discuss important decisions about the user interface for the project
4. Come to a common understanding of how long a project will take to complete
5. Identify which features are the most important
Below is a set of questions that should be useful as a starting point for most interviews a
developer will have with a user or set of users. Feel free to modify this with more specific
questions for the project, or add questions during the interview as they come to mind. The
first set of questions is more general that the group should answer, and the second set is
specific and should be asked of each user of the project or program.
General and Introductory Questions for the Entire User Group
1. What will this project help achieve for the organization?
2. Why are we doing the project now?
3. What will happen if we don't do the project at all?
4. Who will benefit from the project?
5. Do people who will benefit from the project consider it the most important
improvement that can be made at this time?
6. Should we do a different project instead?
7. When does the project need to be completed?
8. What are the most important parts of the project?
9. What features of the project could be postponed or cut if the timeline slips?
User Specific Questions
1. What is the current process you perform?
2. What part(s) of the process would you like to improve?
3. Who will be affected by the changes you would like?
4. Are there other systems that this change will need to interact with?
5. How does the user see their interaction with the current process?
6. How does the user see their interaction with the new process?
7. What options would the user like to be able to configure?
8. What terms doesn't the user understand?
9. Is there anything the user would like to happen when the project is ready to be rolled
out?
10. Who should be able to perform what actions within the system in relation to the new
project?
11. Are there any reports that the user needs?
12. What kinds of auditing requirements does the user have?
top
A Sample Interview
Project Idea
Faculty at Humboldt State University would like a way to print and record attendance from
Moodle. The department assistants would like to reduce the work of creating role sheets for
the faculty. Technical staff at Humboldt State University are in the exploration phase of
project development to determine the best way to meet the needs of the faculty and
department assistants.
General and Introductory Questions for the Entire User Group
1. What will this project help achieve for the organization? It will allow faculty to be self
sufficient when it comes to taking attendance instead of relying on department
assistance to create role sheets.
2. Why are we doing the project now? We are doing this project because fifteen faculty
and twenty-two department assistants have requested this modification as their top
priority over the last 6 months.
3. What will happen if we don't do the project at all? Things will continue as they are
now.
4. Who will benefit from the project? Faculty and department assistants.
5. Do people who will benefit from the project consider it the most important
improvement that can be made at this time? Yes absolutely.
6. Should we do a different project instead? No.
Faculty Specific Questions
1. What is the current process you perform? Request attendance sheet from the
department assistant
2. What part(s) of the process would you like to improve? I would like to be able to print
out attendance sheets 10 minutes before the lecture instead of having to request the
role sheet a week in advance.
3. Who will be affected by the changes you would like? Department assistants and
faculty.
4. Are there other systems that this change will need to interact with? No.
5. How does the user see their interaction with the current process? I see my
interactions as restricted. All the information I want is in Moodle but I am unable to
access it how I want to without going through a department assistant.
6. How does the user see their interaction with the new process? I see myself as less
confined and able to do my job better and in a more timely fashion.
7. What options would the user like to be able to configure?
o I would like to be able to configure which participants in the course are on the
roster in case I have people that I don't need to take attendance for.
o I would like to configure the date the role sheet is for so that I can print out
different one.
o I would like to be able to print out the role sheet for each time my class
meets by just entering in the dates my class meets.
8. What terms doesn't the user understand? Unknown at this time.
9. Is there anything the user would like to happen when the project is ready to be rolled
out?
o I would like to be notified that this project has been completed
o I would like to get some training on how to use this program properly.
10. Who should be able to perform what actions within the system in relation to the new
project? Only faculty should be able to print out the role sheet.
11. Are there any reports that the user needs? If I can enter attendance I would like to be
able to see a report of who has attended what classes.
12. What kinds of auditing requirements does the user have? None.
Department Assistant Specific Questions
1. What is the current process you perform?
a. Log into Moodle and locate the professor's course.
b. Copy all students on one page of the People block and paste them into a
spreadsheet.
c. Repeat step b for each page in the People block
d. Add a field for the date to the spreadsheet
e. Add a title for the course to the spreadsheet
f. Save the file
g. Print the spreadsheet
h. Place the roll sheet in the professor's box
i. Repeat steps a-h for all requests
2. What part(s) of the process would you like to improve? I would like to remove this as
my job function.
3. Who will be affected by the changes you would like? Faculty and department
assistants.
4. Are there other systems that this change will need to interact with? No.
5. How does the user see their interaction with the current process? I have to do a lot of
repetitive tasks, copying and pasting. I also have to print and notify the faculty when
their roll sheets are finished. I probably perform about 10 hours of work for each
faculty.
6. How does the user see their interaction with the new process? I don't see myself
interacting with the new process.
7. What terms doesn't the user understand? Unknown at this time
8. Is there anything the user would like to happen when the project is ready to be rolled
out? I would like to be notified when the project is complete and I would like to know
who to send faculty to get trained on how to use the block.
top
Requirements Document Structure
A software requirements document should not delve into implementation details. That is, the
document should focus on what the application should do and not how it accomplishes those
tasks. This provides for flexibility in implementation while still delivering solid expectations of
what the functionality the program will provide.
1. Application Overview. The Applications overview should be completed as a
collaborative effort between the programmer, user and project manager.
A. Objectives & Justifications
i. Explain why this project is being developed.
ii. Explain the need for the program or project.
iii. Explain why this is being done now rather than later.
B. Business Process
i. Explain the business processes that drive the need for this
application.
ii. Explain how the existing business process will change.
iii. Explain any other systems or processes that this application will be
dependent upon.
C. User Roles and responsibilities
i. Describe unique responsibilities and interactions each user/role in
Moodle will have to perform once the project is complete. For
example a site administrator will have to configure settings or a
student is able to do certain things.
ii. For the most part the general roles that need to be defined are
student, faculty/teacher and administrator.
D. Interactions with Other Systems
i. Explain how the system will interact with other systems. For example
Moodle will generate an excel file for a student system to use to
upload grades
ii. Define interactions with any and all external systems.
E. Replacement of Legacy Systems
i. Explain any legacy systems that this is going to replace
F. Production Rollout Considerations
i. Explain any considerations that will need to be taken into account
when this application goes into production.
G. Terminology
i. Define any terminology that a user might not completely understand
ii. Define all acronyms used within the requirements document or in
later communications about the project between users and
developers.
top
2. Functional Requirements. Functional requirements can be filled out by the project
manager and programmer with the aid of the user, but should always be informed by
the Application overview. This area of the requirements document is most important
to the programmer because it details all the information that is specific to
implementing the program.
A. Statement of functionality
i. Clearly state the required functionality of the program. Be careful to
state exactly what is required; no more and no less. This will be a
loosely binding contract between the customer and the development
team.
ii. In general for Moodle development you will want to break down the
functional requirements based on user roles. If your program is more
of a system-wide core feature then it may be better to list the
requirements based on function.
B. Security considerations
i. Explain any security issues that may need to be addressed as part of
your application.
ii. Explain what actions specific users will be allowed to do or what
actions they specifically cannot do.
C. Customization issues
i. List any specific customization considerations that may need to be
addressed as part of application deployment. Specifically address
what customizations (if any) the user will need to accomplish.
D. Reports
i. Describe any reports, logging, or system overview that the
application will need to provide.
E. Performance Requirements
i. List any specific performance requirements here. There must be
specific metrics and acceptable values listed, no vague or ambiguous
statements.
F. Usability
i. List any specific usability considerations or requirements here.
G. Scope
i. List each of the requirements in the Statement of function
requirements and in which phase of the project they are to be
completed by.
ii. Generally use a phased approach to list out each set of functional
requirements that will be used.
iii. Note when a feature or phase is optional.
3. Supplementary/Background Information/Appendixes. List any supplementary
documents, references or background information that may be necessary to
understand, implement, test, or use the application.
top
"To Do" List
1. Humboldt State University has some sample requirements documents on their Trac
system. Take a look at these two samples: a project to allow crosslisting of courses
and a project to streamline updating activity dates. Also review this sample template
for a requirements document.
2. Read Tanya Berezin's "Writing a Software Requirements Document" (PDF document -
Adobe Reader required). What is the difference between the outline above and the
requirements document structure proposed by Tanya Berezin in "Writing a Software
Requirements Document"?
3. Complete the requirements document writing assignment.
Based on the sample interview provided in this Unit's lesson, write up section 1.1
Objectives & Justifications and 1.2 Business Process of the requirements document.
Submit it in the designated Assignment area in this Unit's section. Be sure that your
document explains each of the important points listed in the Requirements
Documents structure.
Based on the sample interview provided in this Unit's lesson, write up section 2.1
Statement of Functionality of the requirements document. Submit it in the designated
Assignment area in this Unit's section. Be sure that your document explains each of
the important points listed in the Requirements Documents structure.
Think up a project idea that you would like to see implemented in Moodle. To get you
started, consider these ideas:
Easy Projects
o A block that displays a live feed from a web cam.
o A block that stores the date, time and location of when the course meets
Project of Medium Difficulty
o A block that serves as an online calculator with graphic, currency, and
accounting functions
Difficult Projects
o A block to search Google Scholar for publications
o A block to search Amazon for books
o A block that interacts with Google Talk for chatting while in Moodle
o A block that adds all students in a course as Friends in Facebook
o A block that adds all students in a course as Friends in MySpace
o A block that allows FTP access to a server
o A block that adds SSH access to a server
o A block that displays the local weathr from Google or weather.com
Using the sample interview format provided in this Unit, role-play the interview
process with yourself. Submit the answers to the interview questions and any other
questions you feel need to be asked to the Assignment area. Be sure to conduct an
interview from different user perspectives such as the faculty and student
perspective.
Using the answers to the interview questions create a complete requirements
document. Submit the requirements document in the designated Assignment area.
Be sure to explain all of the questions asked in each of the sections of the
Requirements Structure above, as well as provide a screen shot of a mocked up user
interface in an Appendix.
4. After completing the assigned readings and Assignment, choose from among the
following discussion topics and post your ideas.
o Compare and contrast the differences between HSU's requirements
document and the model requirements document outlined in this Unit's
lesson.
o What is the difference between the outline in this lesson and the
requirements document structure proposed by Tanya Berezin in "Writing a
Software Requirements Document"?
o What interview questions would you add to the set of standard interview
questions?
o What sections of the requirements document would you change? Or what
sections would you add?
5. Take the quiz. Two attempts are allowed.
GuUnit 10 - Programming a Moodle Block
Overview | Unit 10 "To Do" List
External resources open in new browser windows.
Over the last nine units you have progressed through the steps to create a Moodle block,
including
checking out code from a sourcecode repository
learning about some useful development tools
setting up Moodle on your computer
exploring useful Moodle libraries
reviewing general information about good coding practices
coding a block in Moodle
creating test cases and running Selenium scripts
writing a requirements document
In this unit you will use everything you've learned so far to create a block from a
requirements document, write test cases, participate in a code review, and finally, release
the block to the Moodle community!
When selecting projects for block development in this course, several factors must be
carefully considered. In some cases, the requirements documents developed in Unit 9 may
not yield the best opportunity for success for beginning Moodle programmers, or might meet
significant resistance when proposed to the Moodle community for reasons that could be
difficult to anticipate.
Seek advice from the course facilitator on whether to proceed with your Unit 9 project for full
block development. The Unit 10 Requirements Document provided below is intended to offer
a manageable task for successful completion of this course and should be used for Unit 10
unless specific encouragement is provided by the facilitator to continue with your Unit 9
project idea.
You may work in project teams if desired. However, unless all team members are at the same
institution, sharing the same CVS, there may be technical difficulties in managing edits to the
code. Alert your facilitator of the members of your team. When submitting your project, you
must document the contributions of each team member.
Post-Development Documentation
After completing the development of a block there are two types of information that the
Moodle user community needs in order to use your block:
1. Installation/Readme documentation
2. Help documentation on how to use the block
Installation/Readme Documentation
Installation documentation informs the system administrator of the steps needed to install
the block. This file, usually title INSTALL.txt, typically contains instructions on placing the
block into the blocks directory and then logging in to Moodle as an administrator and clicking
the "Notifications" link in the Site Administration block. If however, your block is more
complex than a simple block, like a cronjob, or the block modifies core Moodle code files (not
recommended), then the installation file will need to contain information about how these
files will be modified.
The readme file, usually named README.txt, contains documentation on who developed the
block, how to contact you with questions and any other information that is informative to the
user and speaks about yourself and the project.
A final optional file is the CHANGELOG file, which is intended to inform the user of the
changes that have been made to a block in each version. This file is optional on the first
release, but is recommended on each subsequent release. This file should contain all the
bugs that have been fixed in the current version, possibly pointing to specific ticket numbers
in a ticket tracking system.
Important tip: both the README and INSTALL files should be saved in a common format
across all platforms. Text files (.txt and .rtf) files are recommended.
Help Documentation
The final documentation required is Help documentation. This comes in the form of how-to
files, wikis, FAQs, and/or video. This should teach the user how to configure and use the
block. It is recommended that you have both a faculty and student guide for most blocks.
This also comes in the form of HTML files in Moodle. These files are associated with the blue
question-mark buttons on some forms. This button is printed using the helpbutton()
function in weblib.php
top
"To Do" List
Planning Block Development
1. Choose a project of your choice or choose from the list provided in Unit 9's "To Do"
List, item #3 to create a Requirements Document for this project as outlined in Unit
9.
2. Read the details provided at Moodle.org, Working with the Community, to familiarize
yourself with the process of sharing code with the Moodle community. Pay particular
attention to the section near the bottom of the page, "Consider asking or discussing
your proposal first."
3. Share information with the Moodle community about what you plan to develop in the
relevant discussion forum area at Moodle.org.
4. Document unit tests that are needed to test the block based on the requirements
document.
Creating the Block
5. Read this general resource, Writing Good Software Documentation, and consider how
it applies to your Moodle block project.
6. Write the block code based on the requirements document.
7. Write test cases testing each of the requirements from the requirements document.
8. Write Selenium test cases to test your block's functionality.
9. Compose your in-development documentation as well as post-development
documentation.
10. Attach your code in the designated Forum in this course as an attachment to a forum
post (zip your block directory first). Participate in a code review of at least two other
classmates' code with the facilitator. Post your feedback and review comments made
on your code. Consider which comments should be incorporated to improve your
code and make the changes.
11. After making the final edits to your code, submit your final zipped block directory in
the designated Assignment area. Be sure to include your post-development
documentation files and test cases within your zipped file.
top
Contribute the Code to the Moodle Community
Now that the block is complete and the zipped block directory is posted to the Assignment
are in this course, the next step is to release the block to the Moodle Community. Follow
steps 9-12 below (and optionally steps 13 and 14) to release your code to the Moodle
community.
Only one block project will be released to the community. Use the Choice in the final
section of this course's materials to cast your vote for the best block that should be shared.
Consider the following criteria in your vote:
code maintainability
consistency with Moodle coding guidelines
accessibility
usability
matching requirements document specifications
quality of test cases
documentation
The author(s) of the "winning" block will be assigned to complete steps 9-12 below (and
optionally steps 13 and 14) to complete the release.
9. Post the zip file to a publicly-accessible server to allow others to download the file.
10. Create a new entry for the block in the "Modules and Plug-ins" database
o Use a descriptive name for the block. Select a descriptive and unique name
to identify it.
o Describe what the block is intended to do
o Take a screen capture of the block in action on its local test site and post the
screen capture in the screen shot area
o Link the download for Moodle 1.8 to the server where you uploaded the file
o Enter your name as the maintainer
11. Create a new forum topic for the block in the Blocks discussion forum
(http://moodle.org/mod/forum/view.php?id=2121) with the following information
o What the project does
o Contributors
o Requirements document
o Test cases
o Any Selenium cases
o Link to the module and plugins entry
12. Link the "Modules and Plugins" entry to the forums topic.
13. Optional: Add your project to the Moodle Bug Tracker
o Login to tracker.moodle.org
o Click the "Components" link under the project "Non-core contributed module"
on the bottom left side
o Click "Add a project here"
o Click "Create new issue"
o Enter the information for the issue ticket.
14. Optional: Request a contrib directory created for your project in the Moodle CVS
contrib branch.
o Login to tracker.moodle.org
o Click the "Components" link under the project "Non-core contributed module"
on the bottom left side
o Click "Add a project here"
o Click "Create new issue"
o Enter the information for the issue ticket with the title and text requesting a
folder in the contrib block directory be made for your project.
15. Participate in the assigned discussion about managing code in a distributed
community.
idelines
The following guidelines are crucial reading for anyone wanting to contribute to the
Moodle code base:
← Coding guidelines have to be followed by all Moodle developers
← Moodle design goals spells out the basic design goals behind Moodle
← Interface guidelines aim to provide a common feel to the Moodle user
interface
← Moodle CVS for developers explains how to work with the Moodle code in
CVS
← Tracker explains the Moodle Tracker for keeping track of bugs, issues,
feature requests etc
← Working with the Community explains how to engage with the dev
community and discuss changes
← Unit tests explains how to run the unit tests, and how to write new test
cases.
← Development:Fast portable SQL shows SQL techniques that are fast,
efficient, and known to work on all supported DBs.
Documentation for core components
This section is for documentation of specific components of the existing core Moodle
code. Discussion of components that are under discussion or in development can be
found in the developer notes or on the roadmap.
The documents below give a general overview. For detailed function-by-function
documentation, see the phpDocumentor documentation that is automatically
generated from the comments in the code.
And don't forget that the most up-to-date and detailed description of how the code
works is the code itself, and you can browse the code online using PHPXref.
Core components that affect everything
← The database schema
← What happens when you require config.php
← lib/moodlelib.php
← lib/weblib.php for outputting stuff
← JavaScript function available on the client side
← Database abstraction layer @ v1.7
← Roles and Capabilities system @ v1.7 for controlling who can do what
← Forms library @ v1.8 for creating accessible and secure HTML forms that let
users edit things
← File API @ v2.0 for managing files stored by Moodle
Core libraries with a more specific uses
← Authentication API
← Cookieless Sessions
← Email processing
← Environment checking before install, check the user's server to ensure
Moodle will work there.
← Groups system
← Gradebook
← Moodle Network
← Question engine
← Stats package
← Migration to UTF-8 @ v1.6
← YUI JavaScript library - YUI was selected as the official AJAX library for
Moodle.
← lib/graphlib
← Admin settings
Modules included in the standard distribution
← Lesson Specification
← Quiz module
← SCORM module 1.5 schema
How you can contribute
Make a new plugin
The M in Moodle stands for modular, and the easiest, most maintainable way to add
new functionality to Moodle is by using one of the many plugin APIs. There are
many types of plugin you can write:
← Activity modules, see also Development:NEWMODULE Documentation (work
in progress)
← Admin reports
← Assignment types
← Authentication plugins
← Blocks
← Course formats
← Course reports
← Database fields
← Database presets
← Enrolment plugins
← Filters
← Gradebook plugins (1.9 onwards)
← Gradebook report
← Gradebook export
← Gradebook import
← Portfolio plugins (2.0 onwards)
← Question types
← Question import/export formats
← Quiz reports
← Repository plugins (2.0 onwards)
← Resource types
← Search engine adapters
General information that applies to all types of plugins
← Where to put language strings for your plugin
← Defining the database tables for your plugin
Please see the Guidelines for contributed code for an overview of how to contribute
to the Moodle code.
Sometimes it is not possible to write a proper plugin for what you want to do, in
which case you may have to resort to using the local customisations hook.
Change core code
Some types of change can only be made by editing the core Moodle code. Such
changes are much harder to maintain than plugins. If you want your core change to
be considered for inclusion in the official Moodle release, you need to create an
issue in the tracker, and attach your change as a patch. It is also a good idea to
discuss your ideas in the forums first. See
Development:Overview#Major_Development for more details.
Ways to contribute that do not involve PHP programming
← Create Moodle themes
← Translate Moodle into other languages
← Help document Moodle
← Join the testing effort, which involves participating in the bug tracker
Plans for the future
Ideas for and details of planned future features of Moodle are initially discussed on
the forums in the Using Moodle course at moodle.org. That developer discussions
are intermixed with user discussions in the same forums may seem strange at first
but is one of the reasons for the success of Moodle. It is important that both end-
users and developers discuss the future features together.
Once ideas begin to crystallize on the forums they can be summarized in this wiki,
either as part of the roadmap or in the form of developer notes. These pages then
form the basis for further discussion in the forums.
← Roadmap
← Developer notes
← Student projects
← Developer meetings
Resources
← Developer FAQ - frequently asked questions, especially useful for newcomers
to Moodle
← Finding your way into the Moodle code - also aimed at newcomers
← Moodle tracker - bug reports, feature requests and other tracked issues
← Firefox tracker search - How to setup a firefox quicksearch to easily
navigate to moodle bugs
← Firefox Search Plugins - Find tracked issues even more easily
← Unmerged files - changes on the stable branch in CVS that have not been
merged to HEAD
← Browse the code online:
← the code with a complete change history from CVS
← the code, with links generated by PHPXref
← Moodle PHP doc reference - compiled nightly from the comment attached to
each class and function in the code.
← Database Schema - for recent releases
← Development news and discussion section of Using Moodle course
← especially the General developer forum
← cool tricks you can use in the moodle.org forums
Tools
Some tools people use when working on Moodle code:
IDEs
← Setting up NetBeans for Moodle development - NetBeans for PHP is a great
out-of-the-box editor.
← Setting up Eclipse for Moodle development - Eclipse is a great editor to use
for php development, if you can work out how to set it up.
← Setting up Vim for Moodle development
Browser add-ons
← Firebug, see Development:Firebug.
← Web developer extension
← ViewSourceWith - The main goal is to view page source with external
applications, but you can do a lot of other things as well.
Miscellaneous
← Ctags - Using a tags file to navigate code
← W3C HTML validator - Moodle has built in support to make using it easier.
← Windows Installer - Windows Installer documentation for developer.
See also: Useful Development Tools forumin the Introduction to Moodle
Programming course