Development Moodle
Development Moodle
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.
Development: before the new page name i.e. [[Development:New page name]]. If you are a developer, you probably want
namespace by typing 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
Concepts
Overview | 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.
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 servicesincluding Web pagesfully 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.
8.
Review this description of Object-oriented programming from Wikipedia. Read the first six Moodle Coding Guidelines as well as the Coding Style section. 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,
9.
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.
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.
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.
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.
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
Install XAMPP/MAMP/LAMPP
Follow the instructions below for your operating system to download and install XAMPP/MAMP/LAMPP:
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 .
ii. iii.
Select "utf8_general_ci" in the dropdown below in the related text field Click on the "Create" button immediately below the dropdown menu.
Download Eclipse Recommended (new Directory/Folder browser for Extraction and windows Installation will open) Eclipse for Windows Eclipse for Mac OS X Eclipse for Linux "Program Files" "Applications" Look for a package or rpm for your distribution.
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 o o WebAIM's WAVE Web Accessibility Tool Watchfire's WebXACT 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.
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.
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
commands are similar to SVN commands, some of them behave differently than their SVN counterparts.
o o o o o
svn update svn status svn commit svn add svn delete
Review the other commands in this chapter's section so that you understand how and when they are used. Remember that
Using CVS
CVS for Windows
a.
Find the Moodle directory in C:\XAMPP\htdocs.
: 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.
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.
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.
Developers that want to version control their own source code but don't care about Moodle's version control top
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
A group of developers who are in different locations but sharing a common code base
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.
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.
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)
1.
2. 3. 4.
Access Administration > Users > Permissions > Define roles. Click the tab "Allow role assignments". Click the checkbox where the teacher row and column intersect. 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.
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
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.
2. Create the Moodle test environment (empty course, test students, assign roles, restore test case course).
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.
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.
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.
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.
:pserver:[email protected]:/cvsroot /moodle
(for US-based developers, replace the "SERVER" with "us" ) iv. v. Under the "Module" field, type "contrib" to get contrib directory. Press the button: "OK" and everything should be downloaded. Move some of the language files into the language directory. For example, you need to copy the
vi.
\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.
/lang/en/help/*.html
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.
src="http://dev.moodle.org/file.php/2/pictures/Unit4screenshots/pluginsdow nloadUnit4.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
\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.
/lang/en/help/*.html
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. vi.
Click on the "Continue" button and then you are done! 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-toface" 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. ii. iii. iv. v. NONE: Do not show any errors or warnings MINIMAL: Show only fatal errors NORMAL: Show errors, warnings and notices ALL: Show all reasonable PHP debug messages 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 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
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);
define('MDL_PERFDB', true);
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 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.
Structure
Overview | 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 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.
3.
In each such module directory locates any function called module-name_cron in the lib.php file and runs it 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
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
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.
set_user_preferences(),
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.
top
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).
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->noreplyaddress: The email address to use for email that should not
receive a reply.
sesskey()
$USER->sesskey or $CFG->sesskey is
function allows the API to change and you will not
sesskey()
$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.
$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->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->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.
select fullname, shortname, cat.name from mdl_course, mdl_course_categories as cat where startdate > unix_timestamp('20070801 00:00:00') and
Name $COURSE id category sortorder password fullname shortname idnumber summary format showgrades modinfo newsitems teacher teachers student students Guest Startdate Enrolperiod Numsections Marker Maxbytes Showreports Visible
Default Value
"Moodle 1.8.x +" String "mdl18x" "" "test" "site" "1" NULL "3" "Teacher" "Teachers" "Student" "Students" "0" "0" "0" "0" "0" "0" "0" "1" String String String String String Undefined String String String String String String String String String String String String String
Hiddensections Groupmode
"0" "0"
String String String String String String String String String String String String String String String String String String String String
top
Groupmodeforce '0' Lang Theme Cost Currency Timecreated Timemodified Metacourse Requested "" "" "" "USD" "0" "1197679457" "0" "0"
Expirythreshold "0" Notifystudents Enrollable Enrolstartdate Enrolenddate Enroll Defaultrole "0" "1" "0" "0" "" "0"
$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->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-
Name $SITE Visible Timemodified Timecreated Theme Teachers Teacher Summary Students Student Startdate Sortorder Showreports Showgrades Shortname
Default Value
"1" "1182375379' "0" "" "teachers" "teacher" "test" "students" "student" "0" "1000" "0" "1" "moodle18p"
String String String String String String String String String String String String String String String String String String String String Undefined
Restrictmodules "0" Requested Password Numsections Notifystudents Newsitems Modinfo "0" "" '0' "0" "3" NULL
String String String String String String String String String String
"Moodle 1.8.x+" String "site" String String String String String String String String String String String
Expirythreshold "0" Expirynotify Enrolstartdate Enrolperiod Enrolenddate Enroll Defaultrole Currency Cost Category "0" "0" "0" "0" "" "0" "USD" "" "0"
Note: Other global variables such as $THEME, $db, $MCACHE, and $HTTPSPAGEREQUIRED are found in the /lib/setup.php.
(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.
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 object of the main admin user),
get_admin()
(returns $user
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: MDL11135 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).
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:
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:
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.
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(),
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:
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.
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:
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!
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');
'active', 'no');
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
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);
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 "mouseover" 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 just using
echo or print
it easier for other languages). Submit your snippet as a text file in the designated Assignment area. 6. 7. Share your comments on Moodle libraries in the designated discussion forum. Take the quiz. Two attempts are allowed.
8.
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.
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.
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
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.
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.
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.
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:
sesskey()
sesskey()
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.'" />';
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
confirm_sesskey()
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!
exposure of sensitive user information, or subtle hard to detect changes such as adding a few points to a graded assignment.
o o o
Strongly type user input - Where possible, the PARAM_TYPE's for the above three functions will approximate this method. top
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
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
addslashes()
PARAM_ALPHAEXT: the same contents as PARAM_ALPHA plus the chars in quotes: "/-_" allowed, suitable for
require()
PARAM_SEQUENCE: expects a sequence of numbers like 8 to 1, 5, 6, 4, 6, 8, 9. Numbers and commas only. top
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. 2. 3. 4. CAP_INHERIT CAP_ALLOW CAP_PREVENT 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. 2. 3. 4. 5. 6. 7. CONTEXT_SYSTEM CONTEXT_PERSONAL CONETXT_USER CONEXT_COURSECAT CONTEXT_COURSE CONTEXT_MODULE 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. 2. 3. 4. 5. Administrators Course Creators Teachers Students 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.
require_login()
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,
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
has_capability(). An application of
$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
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
addslashes(),
<?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. 7. Take the quiz. Two attempts are allowed. Add your thoughts to the discussion on accessibility.
Part B - Forms
1. Add a form using the Moodle forms library to insert information into the table
o o o o o o o o
2.
Define a new form. Display the new form. Add a header. Add access control. Add logging. Add form elements. Add state variables. Finalize the form.
o o
4. 5. 6.
4.
instance_delete() function
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:
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."
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.
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:
get_string()
7. 8.
HTML or plain text from a text area 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. 2. 3. 4. 5. 6. 7. 8. 9. blockid pagetitle displaytext format filename picture description displaypicture 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. 2. 3. 4. 5. 6. 7. 8. 9. Click the "New Field" link Change the Name to blockid Enter a Comment about the field Set the Type to int Enter a Length of 10 Set Unsigned to unsigned Set Not Null to not null Set Sequence to No Enter 0 for the Default
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. 2. 3. 4. 5. 6. 7. Click the "New Field" link Change the Name to pagetitle Enter a Comment about the field Set the Type to char Enter a Length of 25 Set Not Null to not null Click the Change button.
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. 2. 3. 4. 5. 6. 7. Click the "New Field" link Change the Name to displaytext Enter a Comment about the field Set the Type to text Enter a Length of big Set Not Null to not null Click the Change button.
format
The format field will contain the integer value that
represents the format the text was entered in. To add the format field: 1. 2. 3. 4. 5. 6. 7. 8. 9. Click the "New Field" link Change the Name to format Enter a Comment about the field Set the Type to int Enter a Length of 3 Set Unsigned to unsigned Set Not Null to not null Enter 0 for the Default Click the Change button.
filename
The filename field stores the name of a file the
instructor posts on the simplehtml page, which students can then download or view. To add the filename field: 1. 2. 3. 4. 5. 6. 7. Click the "New Field" link Change the Name to filename Enter a Comment about the field Set the Type to char Enter a Length of 255 Set Not Null to not null Click the Change button.
picture
The URL for the user's chosen picture is in a
predefined static variable that associates a number to a picture. This will allow the addition of more pictures later if necessary, or for changing the current pictures' URLs without
updating the database. Because only the number is stored the database field should be created as an int rather than a char. To add the picture field: 1. 2. 3. 4. 5. 6. 7. 8. 9. Click the "New Field" link Change the Name to picture Enter a Comment about the field Set the Type to int Enter a Length of 2 Set Unsigned to unsigned Set Not Null to not null Set Sequence to No Enter 0 for the Default
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. 2. 3. 4. 5. 6. Click the "New Field" link Change the Name to description Enter a Comment about the field Set the Type to text Enter a Length of big Set Not Null to not null
7.
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. 2. 3. 4. 5. 6. 7. 8. 9. Click the "New Field" link Change the Name to displaypicture Enter a Comment about the field Set the Type to int Enter a Length of 1 Set Unsigned to unsigned Set Not Null to not null Set Sequence to No Enter 0 for the Default
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. 2. 3. 4. 5. 6. 7. 8. 9. Click the "New Field" link Change the Name to displaydate Enter a Comment about the field Set the Type to int Enter a Length of 10 Set Unsigned to unsigned Set Not Null to not null Set Sequence to No 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).
Part B - Forms
1. Add a form using the Moodle forms library to insert information into the table
o o o o o o
Define a new form. Display the new form. Add a header. Add access control. Add logging. Add form elements.
o o
2.
o o
4. 5. 6.
4.
instance_delete() function
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.
<?php require_once("$CFG->libdir/formslib.php"); class simplehtml_form extends moodleform { function definition() { global $CFG;
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:
$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 member function is defined. Although this code is functional, we have skipped many important steps. Now we will add in the missing pieces.
display()
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
To have access to
$CFG
and
require_once('../../config.php');;
require_once('simplehtml_form.php'):
$courseid = required_param('courseid',PARAM_INT);
$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:
'<a href="'.$CFG->wwwroot.'/course/view.php?
print_header(strip_tags($site->fullname), $site->fullname,
id='.$courseid.'">'.$course->shortname. '</a> ->'.get_string('formtitle', 'block_simplehtml'), '', '<meta name="description" content="'. s(strip_tags($site->summary)) .'">', true, '', '')
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:
$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 insert_record() in simplehtml.php:
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.
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. 2.
simplehtml_form.php is created which defines the class used later to display our form. view.php is created which:
loads base moodle API and any necessary third party modules or non-base API files
o o o
loads the necessary course object and globals performs necessary access control loads our form and branches execution appropriately based on our form state
So the form class is defined and the form is displayed in a separate file. Adding elements to the form and finishing the processing of our form will wrap it up!
// add 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:
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:
$COURSE->id:
$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 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
<?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
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); }
// 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.
// 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.
simplehtml_form.php
$this->add_action_buttons();
Notice when calling because
view.php add:
$blockid as a required parameter in the form display file view.php. Add this $courseid = required_param('courseid',PARAM_INT);;
code after
lang/en_utf8/block_simplehtml.php.
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:
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
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
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:
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.
Part B - Forms
1. Add a form using the Moodle forms library to insert information into the table
o o o o o o o o
2.
Define a new form. Display the new form. Add a header. Add access control. Add logging. Add form elements. Add state variables. Finalize the form.
o o
4. 5. 6.
3.
Create the delete.php file Clean up all data associated with the block with the
4.
instance_delete() function
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.
3.
$this-
$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>'; }
Check for any required variables; id (references the simplehtml page id), courseid Verify the courseid given is a valid course Verify the user is logged in Verify thathte user has the appropriate permissions to view any output thescript may generate
5. 6. 7. 8.
Retrieve the database record for the simplehtml page requested Print the header for the page Display the information for the page requested 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');
// 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 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, '', '');
Moodle's translation system to substitute variables in proper locations after being translated. Consider one example from the above code.
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.
Important Tip
The function block_simplehtml_print_page uses
block_simplehtml_print_page() in lib.php
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:
1. 2.
Add the CSS to the theme's CSS files in the theme directory Create a styles.php file in the block and add the CSS there
needing to create multiple entries if the site is using more than one theme. Create
Display Text
Now the display text needs to be added to a box.
1. print_box() and 2.
a combination of
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
lib/filelib.php and is not a part of the core moodle API. So ensure you have access
to this file by calling
print_box_end()
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:
Part B - Forms
1. Add a form using the Moodle forms library to insert information into the table
o o o o o
Define a new form. Display the new form. Add a header. Add access control. Add logging.
o o o
2.
o o
4. 5. 6.
4.
instance_delete() function
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 on for the course. The
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 few adjustments to
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
view.php to
$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
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. 2. 3. Add a link to a new delete.php file Create the delete.php file Print a verification form to the screen in case the user made a mistake
4.
Use
and a confirmation.
$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
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).
'/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
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
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
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
Part B - Forms
1. Add a form using the Moodle forms library to insert information into the table
o o o o o o o o
2.
Define a new form. Display the new form. Add a header. Add access control. Add logging. Add form elements. Add state variables. Finalize the form.
o o
4. 5. 6.
4.
instance_delete() function
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. 2. View simplehtml page(s) which will be block/simplehtml:viewpages 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:
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 o o
Guest: prevent Student: allow Teacher: allow Editing teacher: allow Coursecreator: allow Admin: allow
block/simplehtml:managepages
o o o
Guest: prevent Student: prevent Teacher: prevent Editing teacher: allow Coursecreator: allow Admin: allow
'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 = 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.
has_capability()
function
found in lib/access.php. But first add the global variable $COURSE and $CFG to the function using:
$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 = ''; }
$this->content->footer = '';
with:
function get_content() { global $COURSE, $CFG; if ($this->content !== NULL) { return $this->content; }
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
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 nonexistent; it will be added with the necessary code in the next section. While constructing our link,
'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.
$canmanage to
determine access. Set this variable by verifying the user has the proper capability.
require_login($course);
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. Moodles 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
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 //a[img/@alt='Delete' and
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
a.
Log in with an admin account. Go to the Site Administration block Click on the Reports link near the bottom of the block on the lower right corner.
b. c. d. e.
f.
Click on the Unit tests link Click on the Run tests button. (You could select the options that you want here, we will explain these options below). Wait for the tests to complete.
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.
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.
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.
[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.
o o o
[AAA] : Three characters that represent the block or module name [000] : Three digits that number the question [A] : Potential actor = S: student, T: teacher, A: admin
o o o o o o
[Sim001TAS] : Adding Simplehtml block from the block pull-down menu ______________________________________ __
a. b. Click the "Turn editing on" button on the top right corner window. From the Blocks pull-down menu, find the "simplehtml" block on the list of blocks available c. d. Choose the "simplehtml" block from the menu 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.
b. 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). Install Selenium IDE from Open QA's Selenium IDE Downloads page. Download the Moodle Selenium example file and unzip it (say, in c:\xampp\moodle\)
c.
d.
e. f. g.
In Firefox, go to your local moodle installation (e.g,. http://localhost/moodle/) Login as admin Start Selenium IDE from the Firefox tools menu. 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:
j.
create a new course add a quiz to it import 12 sample questions add those questions to a quiz
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.
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 Moodles "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.
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
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.
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.
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.
4.
What will happen if we don't do the project at all? Things will continue as they are now. Who will benefit from the project? Faculty and department assistants. Do people who will benefit from the project consider it the most important improvement that can be made at this time? Yes absolutely.
5.
6.
5.
6.
7.
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. What options would the user like to be able to configure?
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.
I would like to configure the date the role sheet is for so that I can print out different one.
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. 9.
What terms doesn't the user understand? Unknown at this time. Is there anything the user would like to happen when the project is ready to be rolled out?
o o
I would like to be notified that this project has been completed 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.
a. b. c. d. e. f. g. h. i. 2.
3.
Log into Moodle and locate the professor's course. Copy all students on one page of the People block and paste them into a spreadsheet. Repeat step b for each page in the People block Add a field for the date to the spreadsheet Add a title for the course to the spreadsheet Save the file Print the spreadsheet Place the roll sheet in the professor's box Repeat steps a-h for all requests
What part(s) of the process would you like to improve? I would like to remove this as my job function. 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. 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.
5.
6.
7. 8.
How does the user see their interaction with the new process? I don't see myself interacting with the new process. What terms doesn't the user understand? Unknown at this time 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
1.
Application Overview. The Applications overview should be completed as a collaborative effort between the programmer, user and project manager. A. Objectives & Justifications i. ii. iii. Explain why this project is being developed. Explain the need for the program or project. 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. iii. Explain how the existing business process will change. 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. E. Define interactions with any and all external systems.
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. ii. Define any terminology that a user might not completely understand 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. 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. List any specific usability considerations or requirements here.
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
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 o
A block that displays a live feed from a web cam. A block that stores the date, time and location of when the course meets
Difficult Projects
o o o o o o o o
A block to search Google Scholar for publications A block to search Amazon for books A block that interacts with Google Talk for chatting while in Moodle A block that adds all students in a course as Friends in Facebook A block that adds all students in a course as Friends in MySpace A block that allows FTP access to a server A block that adds SSH access to a server 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.
Compare and contrast the differences between HSU's requirements document and the model requirements document outlined in this Unit's lesson.
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"?
What interview questions would you add to the set of standard interview questions?
What sections of the requirements document would you change? Or what sections would you add?
5.
GuUnit
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. 2. Installation/Readme documentation 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 function in weblib.php top
helpbutton()
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.
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 o
Describe what the block is intended to do 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 o
Link the download for Moodle 1.8 to the server where you uploaded the file 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 o o o o o
What the project does Contributors Requirements document Test cases Any Selenium cases Link to the module and plugins entry
12. Link the "Modules and Plugins" entry to the forums topic.
o o o
Click "Add a project here" Click "Create new issue" Enter the information for the issue ticket.
14. Optional: Request a contrib directory created for your project in the Moodle CVS
contrib branch.
o o
Login to tracker.moodle.org Click the "Components" link under the project "Non-core contributed module" on the bottom left side
o o o
Click "Add a project here" Click "Create new issue" 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.
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.
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.
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.
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