Friday, October 28, 2011

Converting M1.9 Plug-ins to M2 - Block Part 3 - Porting Code


This is part four of my series concerning porting Moodle 1.9 code to Moodle 2.

One of the problems I noticed with the M2 version of the block was that my configuration settings were missing. In 1.9, I could specify a twitter search string, the number of tweets to display and a refresh rate. When I click edit on the block now, those are missing. I'll start with that problem.

The base of this problem is simple: in Moodle 1.9, block instance configuration was handled by a file called "config_instance.html". In Moodle 2, this has changed. In Moodle 2, all blocks have a standard instance configuration to handle things like default page appearance and location. This configuration is always available. To add block-specific configuration elements, we need to include the "edit_form.php" file.
Note that the current documentation indicates that the function "instance_allow_config" needs to be present and needs to return "true" for the configuration form to be available. I believe this is an error in the documentation and is no longer true.
 So, I will take the settings specified in the "config_instance.html" and recode them into a new "edit_form.php" file, using the Moodle forms API. I end up with a file that looks like this:
<?php

class block_twitter_search_edit_form extends block_edit_form {
    protected function specific_definition($mform) {
        $mform->addElement('header', 'configheader', get_string('blocksettings', 'block'));

        $mform->addElement('text', 'config_search_string', get_string('searchterms', 'block_twitter_search'));
        $mform->setType('config_search_string', PARAM_MULTILANG);

        $mform->addElement('select', 'config_no_tweets', get_string('numoftweets', 'block_twitter_search'), range(0,20));

        $mform->addElement('text', 'config_polltime', get_string('polltime', 'block_twitter_search'));
        $mform->setType('config_polltime', PARAM_MULTILANG);
    }
}
This file ports the old HTML code into new Moodle formslib code. Other than changing the functions that generate the form elements, the biggest change is to the name of each form element. For this to work in Moodle 2, there needs to be a "config_" prefix added to each configuration element. Without this, the configuration variables will not save or load properly.

Once I've completed this addition, and deleted the old HTML file, I should be good to go. To check, I go to my block instance with editing turned on and click the "edit" icon. Now I see a new section at the top of the configuration page with my Twitter search settings, as shown below.


Now, we still have the issue that the tweets display doesn't look the same as it did in 1.9. There is no dividing line between the tweets. The simplest solution to this is really easy. In Moodle 1.9, a block could define its own CSS styles in a file called "styles.php". In Moodle 2, block-specific CSS is specified in a CSS file called "styles.css". In 1.9 you could specify PHP code with your CSS. In Moodle 2, you can only specify CSS.

In almost all cases, the 1.9 "styles.php" file never actually contained any PHP code, and was strictly CSS. In this block's case, that is also true. So the simplest solution to this problem is to just rename my "styles.php" file to "styles.css". Once I've done that, my display should look the same as it did in 1.9. And when I go look... Ummm... Hmmmm... It still looks wrong.

There's a good reason for this. In Moodle 2, as part of the new theme engine, CSS is cached. So, while I am now outputting new CSS with my block, Moodle is ignoring it, since it has already cached my block's CSS. There is an easy solution though. Moodle 2 allows us to enable a "Theme designer mode" which disables CSS caching. This can be found on the "Site administration / Appearance / Themes / Theme settings" page. Enabling this mode this will make my pages slower, but since this is a development site, I'm not going to worry about that. Its more important that I see my changes as I make them.

After enabling this mode, and going back to my page, I now see the CSS as I had defined it in my Twitter Search block.

There is more work I have to do to make things really M2'ish, plus there's still that display bug I keep seeing when the block refreshes. Next post, I'll track that down.

Thursday, October 27, 2011

Converting M1.9 Plug-ins to M2 - Block Part 2 - See What Happens

This is part three of my series concerning porting Moodle 1.9 code to Moodle 2.

Alright. Time to see what happens with my Twitter Search block in Moodle 2...

For my purposes, I have a Moodle 2.1.2+ (Build: 20111019) site for my development site. Yours may be slightly different, but as long as its a 2.1.x it shouldn't matter. And, make sure you have "Developer" level debugging on, set to display on the screen. It will make for easier troubleshooting. This can be found on the "Site administration / Development / Debugging" page.

So, the first thing I am going to try is to drop the existing block code onto the 2.1.2 development site. Who knows? Maybe we don't need to do anything and I'll end this series early.

I copy the "twitter_search" block directory into my "/blocks/" directory, visit the site "Notifications" screen, and... nothing. No message, no error. Hmmm.
(Actually, if you have debug messaging on, you will see some error messages at the top of the "Plugins overview" page.)

Really, this is not unexpected, since the entire Moodle plug-in system has been completely overhauled from 1.x. Essentially, our block does not have the necessary components to be installed. But, if I go to the "Site administration / Plugins / Plugins overview" page, and scroll down to the "Blocks" section, I can see near the bottom of that section (see image below) that Moodle does recognize that my block is present.


The entry for the Twitter Search block is there, but it has a broken language string, and isn't really installed, since there is no version and no "enabled"
setting. Also note that Moodle knows it is an "extension". That is, its not supplied standard with Moodle.

Now we have no choice but to start changing code...

Moodle has provided some documentation on how best to migrate 1.9 code to 2.x. The best place to start is here. None of this block specific though, so there is a lot of information. At Remote-Learber, we've kept our own wiki page documenting what we've learned and what we do as we've ported code. I'll use the lessons learned there to move forward.

I am just going to worry about the minimum amount of coding to get the block installed for now. So, to start with, I need a new file in my block directory called "version.php". This file will define the version of my block, and the required version of Moodle for the block to function. In 1.9, the version is defined in the block code itself, in the "init" function. For the twitter_search block, currently the version is "2010020201". I'll create a new version, "2011100101" for our 2.1 version. I'll create a new "version.php" file, give the block a new version, "2011100101", and remove the version code from the block "init" function.

My new "version.php" file now looks like this:
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.

$plugin->version =  2011100101;
$plugin->requires = 2010112400;
The next thing I need to do, to make the block show up properly on the plugins block screen, is change the language directory from "en_utf8" to "en". Moodle 2 has done away with the "utf8" suffix on the directory names, since all languages must be using utf8 strings.

I also need to make one more language string change - I need to change all occurrences of the string used for the block's "title" variable to "pluginname". In this case, the language string "blocktitle" was used, so I will change that. In Moodle 1.9, the "title" variable defined in the "init" function was used to display the block's name throughout the system. In Moodle 2, the "pluginname" language string defines this, and is a required setting.

If there are other language directories present, I will need to remove the "_utf8" portion from their names, and make the "pluginname" string change as well.

I make the language string change in two places - the language files, and the "init" function.

When I'm done, the "init" function code changes from:
function init() {
    $this->title   = get_string('blocktitle','block_twitter_search');
    $this->version = 2010020201;
}
to:
function init() {
    $this->title = get_string('pluginname','block_twitter_search');
}
That should be all I need for my block to install correctly. Revisiting my notification screen, I am prompted with a page that indicates my twitter search block is ready for an upgrade. Clicking "Upgrade" successfully installs it. I am most of the way there!

Now, just for fun, I'm going to add an instance of this block to my site's home page and see what happens. If you do the same, you will see that the block adds correctly and begins to display the twitter search tweets as it did on the 1.9 site (sort of). On my site, it correctly displayed ten tweets, but without the proper display layout. Shortly thereafter, it began to display the error:
Transaction id: 3
HTTP status: 404
Status code message: Not Found
And, when I went to edit the block configuration, none of my block's settings were there.

So, while it sort of works, I have some more work to do. I'll leave that for the next post.




Converting M1.9 Plug-ins to M2 - Block Part 1 - Know the 1.9 Code

Okay. So let's start my Twitter Search block code port.

Step one is straightforward. Get the block code for 1.9, install it on my 1.9 development site and make sure it works okay there.

Getting the code is easy. The developers have set it up on github for me. I go there, use one of the "download" buttons and unzip the "twitter_search" directory into my development site's "/blocks" directory. I know I've done it right because I see a "twitter_search" subdirectory containing files like "block_twitter_search.php" in my site's "/blocks" directory.

Next step is to complete the install by visiting the administration "Notifications" page. Doing this, I see this message:


twitter_search


Twitter Search tables have been set up correctly

The block is now available to add to my site and course pages.

Adding the block to my main page and clicking the edit icon in the block header, shows what it does. I can select a Twitter search string (defaults to "#moodle"), choose how many tweets I want to see at one time (defaults to "10") and select the refresh rate for the tweets (defaults to 30000 ms or 30 seconds). I changed my settings to display 5 tweets and left the rest alone.

Now that I have a good understanding of what the block does, I'll do a quick review of what's in the code.

A quick look at the directory, and I see that it has a "lang" directory and five main code files. There is no "db" directory so it isn't creating a data table or modifying the Moodle database in anyway. That'll make it easier to port, but I won't get to play with the M2 new database API's either. Oh well, next time.

Next, I want to do a look through of the code, for a number of reasons. I want to see if I understand it right away, I want to get a feel for how its been structured, I want to look for any obvious problems (security, performance, etc.) and I want to see if it has adhered to the Moodle development guidelines.

On my pass through the code, I see no obvious violations of the security guidelines, but there are some minor breaches of the Moodle coding style, primarily around line length and indent spacing. These are minor and I can fix them when I port to M2.

I also notice that this code uses two API's that I'm not very familiar with: CURL and DOM. I may need to familiarize myself with those as I migrate, particularly if there are changes in the way they work with Moodle 2.

So, looking at the code, what I believe is happening is this:
  1. Twitter's search URL is constructed with the search string we configured with the block.
  2. That URL is connected to using CURL, and the XML data returned is stored.
  3. The XML data is loaded into a DOM object for easier XML processing.
  4. The tweets we asked for are pulled from the DOM object using a known XML tag ('entry').
  5. The tweets are placed in the block output, one by one, again using known XML structure in the DOM object.
  6. The output is written to the block.
There is also a bunch of javascript that is placed in the output. Some of that it is in the main block script, and some is contained in a separate file (javascript.js). The javascript seems to be there to handle the automatic updating of the tweets in the block. And one other file called 'ajax_update.php' is used by the javascript to update those tweets in an "ajaxy" way.

Lastly, there is a CSS file ('styles.php') and an instance configuration HTML file ('config_instance.html').

I believe I am now comfortable enough with what is happening in this block to start the M2 port. In my next part, I will start the Moodle 2.1 migration of this code.

Tuesday, October 25, 2011

Converting M1.9 Plug-ins to M2

Now that we're well into Moodle 2 (M2), with the current stable release being 2.1.2, I thought it would be a good time to revisit converting legacy Moodle code to the new platform.

You may ask why I am doing this at such a late date? For four reasons:
  1. Many existing users of Moodle have not taken the plunge to M2 yet, but will be over the next several months.
  2. There aren't many complete guides to converting code out there, so it should prove to be a helpful exercise to document this as I do it.
  3. While I have converted a number of plug-ins to M2 in the past 1.5 years, I haven't done it recently.
  4. I miss touching code!
My goal here will be to take something existing in the community, that was useful in 1.9 (and earlier) but has not yet been ported to M2, and port the code while documenting my efforts here in this blog. As I go, I will use the resources in the community, and share them with you, so that we can all learn the best way to do this and learn the best places to find our information. (I will cheat a bit and use the documents we have created here at Remote-Learner used by our development team as well). I'm pretty sure we will also learn what not to do!

I will start with a popular block, posted at moodle.org, called "Twitter Search". This block allows you to display a block on a Moodle page that displays tweets from defined search tags. Each block can be configured to display different hash tags.

Over the next few days, I will begin the process of porting it to Moodle 2.1, and document my efforts here. When done, there will be a working M2 version of this block that can be used by the community.

After that, we'll try some other plug-ins. Post your suggestions here or to my twitter feed.

Friday, October 21, 2011

Pointed Questions for Pearson's OpenClass Moodle and ELIS

In a recent article, The Chronicle asked Pearson three tough questions about its OpenClass system. The importance of these questions have inspired me to answer them for Moodle and Remote-Learner's ELIS add-ons for Moodle.

Question 1: Will colleges be able to control how OpenClass Moodle/ELIS is upgraded and whether to accept new features?
Moodle provides an almost seamless upgrade process. Within a release family (e.g. 1.9, 2.1, etc.), feature changes are kept to an absolute minimum. Instead the focus is on performance improvements, bug fixes (if necessary) and security improvements. Jumping to another release family typically provides many new features and functions. As a Moodle owner, you choose when to upgrade, and Moodle typically supports earlier release families for many months after new release families come out.
Features within Moodle, outside of the standard offerings, are provided by many plug-in systems, making it quite simple for Moodle owners to add and remove new features they want at any time. Plug-ins are provided by a large, vibrant community increasing the usability of Moodle greatly. The control is in the hands of the Moodle owner.
At Remote-Learner, our subscription-based hosting and support services for Moodle and ELIS provide many additional plug-ins for Moodle that you can select to use when you want. Additionally, we support other requested add-ons that clear our review process (for security and performance) giving you ultimate flexibility and control.  
Question 2: What about ease of importing and exporting content? Will OpenClass Moodle/ELIS use industry standards for this? 
Moodle supports multiple content standards, to aid in content creation and management for your courses. SCORM, IMS and Common Cartridge are just a few. Additionally, with its repository management system, almost any repository source for content can be connected and imported into Moodle. Alfresco, Youtube, Google Docs, Flickr and Dropbox are just some of the examples that can be easily connected and used as content sources for your course construction. Moodle also now has Moodle Hubs, which allows courses to be shared and transported among multiple Moodle sites.
Remote-Learner's ELIS add-on to Moodle, further provides automated ways of creating courses in bulk from pre-defined templates, and from imports from already existing systems like Blackboard, WebCT and eCollege, as well as other HR and SIS systems. 
Question 3: Can OpenClass Moodle/ELIS be integrated into a college’s student information system simply, since those systems are key to instructors and usually governed by an institution’s security policies as well as federal privacy laws? 
Moodle provides multiple ways of integrating with school SIS and HR systems. These integrations include user authentication and single sign-on, user creation and modification and grade information exporting to name a few. Many standard systems are supported such as LDAP, CAS, Shibboleth and OpenID.
At Remote-Learner, we have extended these capabilities even further through our ELIS add-ons and specifically Integration Point (IP). IP allows for much more automated exchange of information between Moodle/ELIS and SIS/HR systems for user management, enrolment management, course management and completion/progress management. Data can be exchanged both ways through the use of IP.
 
While I'm sure Pearson's new LMS will do its best to meet these same flexibility requirements, Moodle has already done so. It is Open Source, very easy to set up and use and has many  experienced and skilled providers ready to offer you the services you need if you do not want to go it alone.
 
Moodle and ELIS are open source distributions, licensed under the GPL. Moodle can be found at http://www.moodle.org. ELIS can be found at http://github.com/remotelearner. For Moodle or ELIS service and support, please go to http://www.remote-learner.net.