diff --git a/admin/enrol.php b/admin/enrol.php
index 7ec956d..91af675 100644
--- a/admin/enrol.php
+++ b/admin/enrol.php
@@ -103,7 +103,7 @@
     }
     asort($table->data);
 
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
 
     echo "<div style=\"text-align:center\"><input type=\"submit\" value=\"".get_string("savechanges")."\" /></div>\n";
     echo "</div>";
diff --git a/admin/filters.php b/admin/filters.php
index 25023c1..aa7f4c6 100644
--- a/admin/filters.php
+++ b/admin/filters.php
@@ -218,7 +218,7 @@
         $table->rowclasses[] = 'dimmed_text';
     }
 
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
     echo '<p class="filtersettingnote">' . get_string('filterallwarning', 'filters') . '</p>';
     echo $OUTPUT->footer();
 
diff --git a/admin/mnet/access_control.php b/admin/mnet/access_control.php
index 3680365..353e43d 100644
--- a/admin/mnet/access_control.php
+++ b/admin/mnet/access_control.php
@@ -184,7 +184,7 @@ if (!$acl) {
 }
 
 if (!empty($table)) {
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
     echo '<p>&nbsp;</p>';
     $baseurl = new moodle_url('/admin/mnet/access_control.php', array('sort' => $sort, 'dir' => $dir, 'perpage' => $perpage));
     echo $OUTPUT->paging_bar($aclcount, $page, $perpage, $baseurl);
diff --git a/admin/mnet/peers.php b/admin/mnet/peers.php
index f61d5d9..25db689 100644
--- a/admin/mnet/peers.php
+++ b/admin/mnet/peers.php
@@ -218,7 +218,7 @@ $table->data = array(
         $registerrow
     ),
 );
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 // print the list of all hosts, with little action links and buttons
 $table = new html_table();
@@ -250,7 +250,7 @@ foreach($hosts as $host) {
         $OUTPUT->single_button(new moodle_url('/admin/mnet/delete.php', array('hostid' => $host->id)), get_string('delete'))
     );
 }
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 // finally, print the initial form to add a new host
 echo $OUTPUT->box_start();
diff --git a/admin/mnet/testclient.php b/admin/mnet/testclient.php
index 970d413..91f10bb 100644
--- a/admin/mnet/testclient.php
+++ b/admin/mnet/testclient.php
@@ -122,7 +122,7 @@ if (!empty($hostid) && array_key_exists($hostid, $hosts)) {
         );
 
     }
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
 
 
     $mnet_request->set_method('system/listMethods');
@@ -156,7 +156,7 @@ if (!empty($hostid) && array_key_exists($hostid, $hosts)) {
             html_writer::link($newurl, get_string('inspect', 'mnet'))
         );
     }
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
 
     if (isset($methodid) && array_key_exists($methodid-1, $methods)) {
         $method = $methods[$methodid-1];
@@ -194,7 +194,7 @@ if (!empty($hostid) && array_key_exists($hostid, $hosts)) {
             $signature['return']['description']
         );
 
-        echo $OUTPUT->table($table);
+        echo html_writer::table($table);
 
         $mnet_request->set_method('system/methodHelp');
         $mnet_request->add_param($method, 'string');
diff --git a/admin/report/configlog/index.php b/admin/report/configlog/index.php
index adf4874..b5929bd 100644
--- a/admin/report/configlog/index.php
+++ b/admin/report/configlog/index.php
@@ -104,6 +104,6 @@ foreach ($rs as $log) {
 }
 $rs->close();
 
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 echo $OUTPUT->footer();
diff --git a/admin/report/courseoverview/index.php b/admin/report/courseoverview/index.php
index 3a2b28b..bfaabc6 100644
--- a/admin/report/courseoverview/index.php
+++ b/admin/report/courseoverview/index.php
@@ -60,7 +60,7 @@
                            '<input type="text" name="numcourses" size="3" maxlength="2" value="'.$numcourses.'" />',
                            '<input type="submit" value="'.get_string('view').'" />') ;
 
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
     echo '</div>';
     echo '</form>';
 
@@ -117,7 +117,7 @@
                 }
                 $table->data[] = $a;
             }
-            echo $OUTPUT->table($table);
+            echo html_writer::table($table);
         }
     }
     echo $OUTPUT->footer();
diff --git a/admin/report/questioninstances/index.php b/admin/report/questioninstances/index.php
index 4eae3a8..3176a98 100644
--- a/admin/report/questioninstances/index.php
+++ b/admin/report/questioninstances/index.php
@@ -122,7 +122,7 @@ if ($requestedqtype) {
             $totalhidden);
 
     // Print it.
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
 }
 
 // Footer.
diff --git a/admin/report/security/index.php b/admin/report/security/index.php
index 249c04c..48ea8ad 100644
--- a/admin/report/security/index.php
+++ b/admin/report/security/index.php
@@ -92,7 +92,7 @@ if ($issue and ($result = $issue(true))) {
 
     $table->data[] = $row;
 
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
 
     echo $OUTPUT->box($result->details, 'generalbox boxwidthnormal boxaligncenter'); // TODO: add proper css
 
@@ -121,7 +121,7 @@ if ($issue and ($result = $issue(true))) {
 
         $table->data[] = $row;
     }
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
 }
 
 echo $OUTPUT->footer();
diff --git a/admin/roles/allow.php b/admin/roles/allow.php
index 99888c7..4ecd847 100755
--- a/admin/roles/allow.php
+++ b/admin/roles/allow.php
@@ -67,7 +67,7 @@ echo $OUTPUT->box($controller->get_intro_text());
 
 echo '<form action="' . $baseurl . '" method="post">';
 echo '<input type="hidden" name="sesskey" value="' . sesskey() . '" />';
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 echo '<div class="buttons"><input type="submit" name="submit" value="'.get_string('savechanges').'"/>';
 echo '</div></form>';
 
diff --git a/admin/roles/assign.php b/admin/roles/assign.php
index 6de7cd6..268788e 100755
--- a/admin/roles/assign.php
+++ b/admin/roles/assign.php
@@ -431,7 +431,7 @@
             $table->data[] = $row;
         }
 
-        echo $OUTPUT->table($table);
+        echo html_writer::table($table);
 
         if ($context->contextlevel > CONTEXT_USER) {
             echo '<div class="backlink"><a href="' . get_context_url($context) . '">' . get_string('backto', '', $contextname) . '</a></div>';
diff --git a/admin/roles/manage.php b/admin/roles/manage.php
index b2a5e23..cda0d53 100755
--- a/admin/roles/manage.php
+++ b/admin/roles/manage.php
@@ -256,7 +256,7 @@
 
         $table->data[] = $row;
     }
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
 
     echo $OUTPUT->container_start('buttons');
     echo $OUTPUT->single_button(new moodle_url($defineurl, array('action' => 'add')), get_string('addrole', 'role'), 'get');
diff --git a/admin/uploaduser.php b/admin/uploaduser.php
index d079ff3..b085ddc 100755
--- a/admin/uploaduser.php
+++ b/admin/uploaduser.php
@@ -854,7 +854,7 @@ foreach ($contents as $content) {
 
 $table = new html_table();
 $table->id = "uupreview";
-$table->set_classes = 'generaltable';
+$table->attributes['class'] = 'generaltable';
 $table->tablealign = 'center';
 $table->summary = get_string('uploaduserspreview', 'admin');
 $table->head = array();
@@ -887,7 +887,7 @@ if (in_array('error', $headings)) {
                     $value = get_string($content[$key]);
                 }
                 $cells->text = $value;
-                $cells->set_classes($errclass);
+                $cells->attributes['class'] = $errclass;
                 $rows->cells[] = $cells;
             }
             $countcontent++;
@@ -928,7 +928,7 @@ if (in_array('error', $headings)) {
         $countcontent++;
     }
 }
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 if ($haserror) {
 
diff --git a/admin/user.php b/admin/user.php
index b72ae4c..47e7fe4 100644
--- a/admin/user.php
+++ b/admin/user.php
@@ -298,7 +298,7 @@
         echo $OUTPUT->heading('<a href="'.$securewwwroot.'/user/editadvanced.php?id=-1">'.get_string('addnewuser').'</a>');
     }
     if (!empty($table)) {
-        echo $OUTPUT->table($table);
+        echo html_writer::table($table);
         echo $OUTPUT->paging_bar($usercount, $page, $perpage, $baseurl);
         if (has_capability('moodle/user:create', $sitecontext)) {
             echo $OUTPUT->heading('<a href="'.$securewwwroot.'/user/editadvanced.php?id=-1">'.get_string('addnewuser').'</a>');
diff --git a/admin/user/user_bulk_display.php b/admin/user/user_bulk_display.php
index 58c11b7..f7383a2 100755
--- a/admin/user/user_bulk_display.php
+++ b/admin/user/user_bulk_display.php
@@ -74,7 +74,7 @@ foreach($users as $user) {
 }
 
 echo $OUTPUT->heading("$usercount / $usertotal ".get_string('users'));
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 echo $OUTPUT->continue_button($return);
 
diff --git a/admin/user/user_bulk_enrol.php b/admin/user/user_bulk_enrol.php
index 48ab6f2..0d6cf65 100644
--- a/admin/user/user_bulk_enrol.php
+++ b/admin/user/user_bulk_enrol.php
@@ -125,7 +125,7 @@ foreach($users as $user)
     $table->data[] = $temparray;
 }
 echo $OUTPUT->heading("$usercount / $usertotal ".get_string('users'));
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 echo '<div class="continuebutton">';
 echo '<input type="submit" name="multienrolsubmit" value="save changes" />';
 echo '</div>';
diff --git a/admin/webservice/service_functions.php b/admin/webservice/service_functions.php
index 3d1f777..26eee6a 100644
--- a/admin/webservice/service_functions.php
+++ b/admin/webservice/service_functions.php
@@ -137,7 +137,7 @@ foreach ($functions as $function) {
     }
 }
 
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 
 // we can edit only custom functions, the build-in would be overridden after each upgrade
diff --git a/backup/backup_check.html b/backup/backup_check.html
index 64880be..3949dc8 100644
--- a/backup/backup_check.html
+++ b/backup/backup_check.html
@@ -199,7 +199,7 @@
                         }
                     }
                     $table->data = $modcheckbackup($id,$backupprefs->$var,$backupprefs->backup_unique_code,$instancestopass);
-                    echo $OUTPUT->table($table);
+                    echo html_writer::table($table);
                     echo "</td></tr>";
                 }
             }
@@ -219,7 +219,7 @@
             echo $user_options[$backupprefs->backup_users].'</b>';
             //Print info
             $table->data = user_check_backup($id,$backupprefs->backup_unique_code,$backupprefs->backup_users,$backupprefs->backup_messages, $backupprefs->backup_blogs);
-            echo $OUTPUT->table($table);
+            echo html_writer::table($table);
             echo "</td></tr>";
 
         }
@@ -231,7 +231,7 @@
             echo get_string("includelogentries").'</b>';
             //Print info
             $table->data = log_check_backup($id);
-            echo $OUTPUT->table($table);
+            echo html_writer::table($table);
             echo "</td></tr>";
         }
 
@@ -242,7 +242,7 @@
             echo get_string("includeuserfiles").'</b>';
             //Print info
             $table->data = user_files_check_backup($id,$backupprefs->backup_unique_code);
-            echo $OUTPUT->table($table);
+            echo html_writer::table($table);
             echo "</td></tr>";
         }
 
@@ -253,7 +253,7 @@
             echo get_string("includecoursefiles").'</b>';
             //Print info
             $table->data = course_files_check_backup($id,$backupprefs->backup_unique_code);
-            echo $OUTPUT->table($table);
+            echo html_writer::table($table);
             echo "</td></tr>";
         }
 
@@ -264,7 +264,7 @@
             echo get_string("includesitefiles").'</b>';
             //Print info
             $table->data = site_files_check_backup($id,$backupprefs->backup_unique_code);
-            echo $OUTPUT->table($table);
+            echo html_writer::table($table);
             echo "</td></tr>";
         }
 
@@ -275,7 +275,7 @@
             echo get_string("includeroleassignments").'</b>';
             //Print info
             $table->data = array(array(get_string('roles'), count($backupprefs->backuproleassignments)));
-            echo $OUTPUT->table($table);
+            echo html_writer::table($table);
             echo "</td></tr>";
         }
     }
diff --git a/backup/restorelib.php b/backup/restorelib.php
index d35114d..a96109e 100644
--- a/backup/restorelib.php
+++ b/backup/restorelib.php
@@ -533,7 +533,7 @@ define('RESTORE_GROUPS_GROUPINGS', 3);
             echo $OUTPUT->heading(get_string("backup").":");
             $table->data = $tab;
             //Print backup general info
-            echo $OUTPUT->table($table);
+            echo html_writer::table($table);
 
             if ($info->backup_backup_version <= 2005070500) {
                  echo $OUTPUT->notification(get_string('backupnonisowarning'));  // Message informing that this backup may not work!
@@ -643,7 +643,7 @@ define('RESTORE_GROUPS_GROUPINGS', 3);
             //Print title
             echo $OUTPUT->heading(get_string("backupdetails").":");
             //Print backup general info
-            echo $OUTPUT->table($table);
+            echo html_writer::table($table);
         } else {
             $status = false;
         }
@@ -672,7 +672,7 @@ define('RESTORE_GROUPS_GROUPINGS', 3);
             //Print title
             echo $OUTPUT->heading(get_string("course").":");
             //Print backup course header info
-            echo $OUTPUT->table($table);
+            echo html_writer::table($table);
         } else {
             $status = false;
         }
diff --git a/blog/external_blogs.php b/blog/external_blogs.php
index 7eb685c..058ef77 100644
--- a/blog/external_blogs.php
+++ b/blog/external_blogs.php
@@ -68,7 +68,7 @@ echo $OUTPUT->box_start('generalbox boxaligncenter');
 if (!empty($blogs)) {
     $table = new html_table();
     $table->cellpadding = 4;
-    $table->add_class('generaltable boxaligncenter');
+    $table->attributes['class'] = 'generaltable boxaligncenter';
     $table->head = array(get_string('name'), get_string('url'), get_string('timefetched', 'blog'), get_string('valid', 'blog'), get_string('actions'));
 
     foreach ($blogs as $blog) {
@@ -87,7 +87,7 @@ if (!empty($blogs)) {
 
         $table->data[] = new html_table_row(array($blog->name, $blog->url, userdate($blog->timefetched), $validicon, $editicon . $deleteicon));
     }
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
 }
 
 $newexternalurl = new moodle_url('/blog/external_blog_edit.php');
diff --git a/blog/locallib.php b/blog/locallib.php
index 0150d9d..ec62238 100644
--- a/blog/locallib.php
+++ b/blog/locallib.php
@@ -133,17 +133,17 @@ class blog_entry {
         // Start printing of the blog
         $table = new html_table();
         $table->cellspacing = 0;
-        $table->add_classes('forumpost blog_entry blog'. ($unassociatedentry ? 'draft' : $template['publishstate']));
+        $table->attributes['class'] = 'forumpost blog_entry blog'. ($unassociatedentry ? 'draft' : $template['publishstate']);
         $table->width = '100%';
 
         $picturecell = new html_table_cell();
-        $picturecell->add_classes('picture left');
+        $picturecell->attributes['class'] = 'picture left';
         $picturecell->text = $OUTPUT->user_picture($user);
 
         $table->head[] = $picturecell;
 
         $topiccell = new html_table_cell();
-        $topiccell->add_classes('topic starter');
+        $topiccell->attributes['class'] = 'topic starter';
         $topiccell->text = $OUTPUT->container($template['title'], 'subject');
         $topiccell->text .= $OUTPUT->container_start('author');
 
@@ -169,11 +169,11 @@ class blog_entry {
         $mainrow = new html_table_row();
 
         $leftsidecell = new html_table_cell();
-        $leftsidecell->add_classes('left side');
+        $leftsidecell->attributes['class'] = 'left side';
         $mainrow->cells[] = $leftsidecell;
 
         $contentcell = new html_table_cell();
-        $contentcell->add_class('content');
+        $contentcell->attributes['class'] = 'content';
 
         $attachedimages = $OUTPUT->container($this->print_attachments(), 'attachments');
 
@@ -299,9 +299,9 @@ class blog_entry {
         $table->data = array($mainrow);
 
         if ($return) {
-            return $OUTPUT->table($table);
+            return html_writer::table($table);
         } else {
-            echo $OUTPUT->table($table);
+            echo html_writer::table($table);
         }
     }
 
diff --git a/comment/locallib.php b/comment/locallib.php
index 1419438..f8397ea 100644
--- a/comment/locallib.php
+++ b/comment/locallib.php
@@ -119,7 +119,7 @@ class comment_manager {
             }
             $table->data[] = array($checkbox, $c->username, $c->content, $action);
         }
-        echo $OUTPUT->table($table);
+        echo html_writer::table($table);
         echo $OUTPUT->paging_bar($count, $page, $this->perpage, $CFG->wwwroot.'/comment/index.php');
     }
 
diff --git a/course/import/activities/mod.php b/course/import/activities/mod.php
index f1d0a59..58e0be9 100644
--- a/course/import/activities/mod.php
+++ b/course/import/activities/mod.php
@@ -95,6 +95,6 @@
         }
     }
     if (!empty($table)) {
-        echo $OUTPUT->table($table);
+        echo html_writer::table($table);
     }
 
diff --git a/course/lib.php b/course/lib.php
index 8475067..f23e7a1 100644
--- a/course/lib.php
+++ b/course/lib.php
@@ -419,7 +419,7 @@ function print_log($course, $user=0, $date=0, $order="l.time ASC", $page=0, $per
         $table->data[] = $row;
     }
 
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
     echo $OUTPUT->paging_bar($totalcount, $page, $perpage, "$url&perpage=$perpage");
 }
 
diff --git a/course/pending.php b/course/pending.php
index b2c3eda..71f2801 100644
--- a/course/pending.php
+++ b/course/pending.php
@@ -99,7 +99,7 @@ if (empty($pending)) {
 
 /// Build a table of all the requests.
     $table = new html_table();
-    $table->add_class('pendingcourserequests generaltable');
+    $table->attributes['class'] = 'pendingcourserequests generaltable';
     $table->align = array('center', 'center', 'center', 'center', 'center', 'center', 'center');
     $table->head = array('&nbsp;', get_string('shortname'), get_string('fullname'),
             get_string('requestedby'), get_string('summary'), get_string('requestreason'), get_string('action'));
@@ -135,7 +135,7 @@ if (empty($pending)) {
     }
 
 /// Display the table.
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
 
 /// Message about name collisions, if necessary.
     if (!empty($collision)) {
@@ -145,4 +145,4 @@ if (empty($pending)) {
 
 /// Finish off the page.
 echo $OUTPUT->single_button($CFG->wwwroot . '/course/index.php', get_string('backtocourselisting'));
-echo $OUTPUT->footer();
\ No newline at end of file
+echo $OUTPUT->footer();
diff --git a/course/report/outline/index.php b/course/report/outline/index.php
index 5d74e1a..d9e893e 100644
--- a/course/report/outline/index.php
+++ b/course/report/outline/index.php
@@ -47,7 +47,7 @@
     echo $OUTPUT->container(get_string('computedfromlogs', 'admin', userdate($logstart)), 'loginfo');
 
     $outlinetable = new html_table();
-    $outlinetable->add_class('generaltable boxaligncenter');
+    $outlinetable->attributes['class'] = 'generaltable boxaligncenter';
     $outlinetable->cellpadding = 5;
     $outlinetable->id = 'outlinetable';
     $outlinetable->head = array($stractivity, $strviews);
@@ -82,7 +82,7 @@
             }
             if ($prevsecctionnum != $sectionnum) {
                 $sectionrow = new html_table_row();
-                $sectionrow->add_class('section');
+                $sectionrow->attributes['class'] = 'section';
                 $sectioncell = new html_table_cell();
                 $sectioncell->colspan = count($outlinetable->head);
 
@@ -105,7 +105,7 @@
 
             $reportrow = new html_table_row();
             $activitycell = new html_table_cell();
-            $activitycell->add_class('activity');
+            $activitycell->attributes['class'] = 'activity';
 
             $activityicon = $OUTPUT->pix_icon('icon', $modulename, $cm->modname, array('class'=>'icon'));
 
@@ -119,7 +119,7 @@
             $reportrow->cells[] = $activitycell;
 
             $numviewscell = new html_table_cell();
-            $numviewscell->add_class('numviews');
+            $numviewscell->attributes['class'] = 'numviews';
 
             if (!empty($views[$cm->id]->numviews)) {
                 $numviewscell->text = $views[$cm->id]->numviews;
@@ -131,7 +131,7 @@
 
             if ($CFG->useblogassociations) {
                 $blogcell = new html_table_cell();
-                $blogcell->add_class('blog');
+                $blogcell->attributes['class'] = 'blog';
                 if ($blogcount = blog_get_associated_count($course->id, $cm->id)) {
                     $blogcell->text = html_writer::link('/blog/index.php?modid='.$cm->id, $blogcount);
                 } else {
@@ -142,7 +142,7 @@
 
             if ($showlastaccess) {
                 $lastaccesscell = new html_table_cell();
-                $lastaccesscell->add_class('lastaccess');
+                $lastaccesscell->attributes['class'] = 'lastaccess';
 
                 if (isset($views[$cm->id]->lasttime)) {
                     $timeago = format_time(time() - $views[$cm->id]->lasttime);
@@ -153,7 +153,7 @@
             $outlinetable->data[] = $reportrow;
         }
     }
-    echo $OUTPUT->table($outlinetable);
+    echo html_writer::table($outlinetable);
 
     echo $OUTPUT->footer();
 
diff --git a/course/report/stats/report.php b/course/report/stats/report.php
index dfdfeef..65962dd 100644
--- a/course/report/stats/report.php
+++ b/course/report/stats/report.php
@@ -67,7 +67,7 @@
         .'<div>'."\n"
         .'<input type="hidden" name="mode" value="'.$mode.'" />'."\n";
 
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
 
     echo '</div>';
     echo '</form>';
@@ -221,7 +221,7 @@
                 $lastrecord[] = $lastlink;
                 $table->data[] = $lastrecord;
             }
-            echo $OUTPUT->table($table);
+            echo html_writer::table($table);
         }
     }
 
diff --git a/course/reset.php b/course/reset.php
index fd8dc8f..cd0a66b 100755
--- a/course/reset.php
+++ b/course/reset.php
@@ -87,7 +87,7 @@ if ($mform->is_cancelled()) {
         $table->align = array('left', 'left', 'left');
         $table->width = '80%';
         $table->data  = $data;
-        echo $OUTPUT->table($table);
+        echo html_writer::table($table);
 
         echo $OUTPUT->continue_button('view.php?id='.$course->id);  // Back to course page
         echo $OUTPUT->footer();
diff --git a/course/resources.php b/course/resources.php
index 1cf3fc7..db1f4b1 100644
--- a/course/resources.php
+++ b/course/resources.php
@@ -89,7 +89,7 @@ if (!$cms) {
 }
 
 $table = new html_table();
-$table->set_classes(array('generaltable', 'mod_index'));
+$table->attributes['class'] = 'generaltable mod_index';
 
 if ($course->format == 'weeks') {
     $table->head  = array ($strweek, $strname, $strintro);
@@ -137,6 +137,6 @@ foreach ($cms as $cm) {
         format_module_intro('resource', $resource, $cm->id));
 }
 
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 echo $OUTPUT->footer();
diff --git a/course/user.php b/course/user.php
index 6e00c98..414bac2 100644
--- a/course/user.php
+++ b/course/user.php
@@ -256,7 +256,7 @@ switch ($mode) {
             $a[] = $stat->line3;
             $table->data[] = $a;
         }
-        echo $OUTPUT->table($table);
+        echo html_writer::table($table);
         break;
 
     case "outline" :
diff --git a/enrol/authorize/locallib.php b/enrol/authorize/locallib.php
index 5355a69..a9620e0 100644
--- a/enrol/authorize/locallib.php
+++ b/enrol/authorize/locallib.php
@@ -323,7 +323,7 @@ function authorize_print_order($orderid)
         }
         $table->data[] = array("<b>$strs->confirm:</b>", get_string('captureyes', 'enrol_authorize') . '<br />' .
                                authorize_print_action_button($orderid, ORDER_CAPTURE, 0, true, false, $strs->no));
-        echo $OUTPUT->table($table);
+        echo html_writer::table($table);
     }
     elseif (ORDER_REFUND == $do && in_array(ORDER_REFUND, $statusandactions->actions)) {
         $refunded = 0.0;
@@ -378,7 +378,7 @@ function authorize_print_order($orderid)
                      get_string('canbecredit', 'enrol_authorize', $a) . '<br />';
         $table->data[] = array("<b>$strs->confirm:</b>",
                                authorize_print_action_button($orderid, ORDER_REFUND, 0, true, $authstrs->unenrolstudent, $strs->no, $extrahtml));
-        echo $OUTPUT->table($table);
+        echo html_writer::table($table);
     }
     elseif (ORDER_DELETE == $do && in_array(ORDER_DELETE, $statusandactions->actions)) {
         if ($confirm && confirm_sesskey()) {
@@ -390,7 +390,7 @@ function authorize_print_order($orderid)
         }
         $table->data[] = array("<b>$strs->confirm:</b>",
                                authorize_print_action_button($orderid, ORDER_DELETE, 0, true, $authstrs->unenrolstudent,$strs->no));
-        echo $OUTPUT->table($table);
+        echo html_writer::table($table);
     }
     elseif (ORDER_VOID == $do) { // special case: cancel original or refunded transaction?
         $suborderid = optional_param('suborder', 0, PARAM_INT);
@@ -412,7 +412,7 @@ function authorize_print_order($orderid)
             }
             $table->data[] = array("<b>$strs->confirm:</b>", get_string('voidyes', 'enrol_authorize') . '<br />' .
                                    authorize_print_action_button($orderid, ORDER_VOID, 0, true, false, $strs->no));
-            echo $OUTPUT->table($table);
+            echo html_writer::table($table);
         }
         elseif (!empty($suborderid)) { // cancel refunded
             $sql = "SELECT r.*, e.courseid, e.paymentmethod
@@ -453,12 +453,12 @@ function authorize_print_order($orderid)
                 $a->amount = $suborder->amount;
                 $table->data[] = array("<b>$strs->confirm:</b>", get_string('subvoidyes', 'enrol_authorize', $a) . '<br />' .
                                        authorize_print_action_button($orderid, ORDER_VOID, $suborderid, true, $authstrs->unenrolstudent, $strs->no));
-                echo $OUTPUT->table($table);
+                echo html_writer::table($table);
             }
         }
     }
     else {
-        echo $OUTPUT->table($table);
+        echo html_writer::table($table);
 
         if ($settled) { // show refunds.
             $t2 = new html_table();
@@ -505,7 +505,7 @@ function authorize_print_order($orderid)
                 $t2->data[] = array('','',get_string('noreturns', 'enrol_authorize'),'','');
             }
             echo "<h4>" . get_string('returns', 'enrol_authorize') . "</h4>\n";
-            echo $OUTPUT->table($t2);
+            echo html_writer::table($t2);
         }
     }
 
diff --git a/filter/manage.php b/filter/manage.php
index 0ebfbdb..af34d4b 100644
--- a/filter/manage.php
+++ b/filter/manage.php
@@ -199,7 +199,7 @@ if (empty($availablefilters)) {
         $table->data[] = $row;
     }
 
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
     echo '<div class="buttons">' . "\n";
     echo '<input type="submit" name="savechanges" value="' . get_string('savechanges') . '" />';
     echo "\n</div>\n";
diff --git a/grade/edit/letter/index.php b/grade/edit/letter/index.php
index 3327fb4..5f92278 100644
--- a/grade/edit/letter/index.php
+++ b/grade/edit/letter/index.php
@@ -70,6 +70,6 @@ $table->align = array('left', 'left', 'left');
 $table->width = '30%';
 $table->data  = $data;
 $table->tablealign  = 'center';
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 echo $OUTPUT->footer();
diff --git a/grade/edit/outcome/index.php b/grade/edit/outcome/index.php
index 55d54f7..2cee964 100644
--- a/grade/edit/outcome/index.php
+++ b/grade/edit/outcome/index.php
@@ -181,7 +181,7 @@ if ($courseid and $outcomes = grade_outcome::fetch_all_local($courseid)) {
     $table->align = array('left', 'left', 'left', 'center', 'center');
     $table->width = '90%';
     $table->data  = $data;
-    $return .= $OUTPUT->table($table);
+    $return .= html_writer::table($table);
     $outcomes_tables[] = $return;
 }
 
@@ -233,7 +233,7 @@ if ($outcomes = grade_outcome::fetch_all_global()) {
     $table->align = array('left', 'left', 'left', 'center', 'center', 'center');
     $table->width = '90%';
     $table->data  = $data;
-    $return .= $OUTPUT->table($table);
+    $return .= html_writer::table($table);
     $outcomes_tables[] = $return;
 }
 
diff --git a/grade/edit/scale/index.php b/grade/edit/scale/index.php
index 99e8f74..8a1e12a 100644
--- a/grade/edit/scale/index.php
+++ b/grade/edit/scale/index.php
@@ -158,9 +158,9 @@ if ($courseid) {
 }
 
 echo $OUTPUT->heading($strcustomscales, 3, 'main');
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 echo $OUTPUT->heading($strstandardscale, 3, 'main');
-echo $OUTPUT->table($table2);
+echo html_writer::table($table2);
 echo $OUTPUT->container_start('buttons');
 echo $OUTPUT->single_button(new moodle_url('edit.php', array('courseid'=>$courseid)), $srtcreatenewscale);
 echo $OUTPUT->container_end();
diff --git a/grade/edit/tree/index.php b/grade/edit/tree/index.php
index b595dbb..4ce042c 100644
--- a/grade/edit/tree/index.php
+++ b/grade/edit/tree/index.php
@@ -309,7 +309,7 @@ echo '<form id="gradetreeform" method="post" action="'.$returnurl.'">';
 echo '<div>';
 echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
 
-echo $OUTPUT->table($grade_edit_tree->table);
+echo html_writer::table($grade_edit_tree->table);
 
 echo '<div id="gradetreesubmit">';
 if (!$moving) {
diff --git a/grade/edit/tree/lib.php b/grade/edit/tree/lib.php
index e0f94b7..8e6fd4a 100755
--- a/grade/edit/tree/lib.php
+++ b/grade/edit/tree/lib.php
@@ -84,7 +84,7 @@ class grade_edit_tree {
         $this->table = new html_table();
         $this->table->id = "grade_edit_tree_table";
         $this->table->cellpadding = 5;
-        $this->table->add_classes(array('generaltable', $mode));
+        $this->table->attributes['class'] = 'generaltable ' . $mode;
         $this->table->style = $widthstyle;
 
         foreach ($this->columns as $column) {
@@ -161,7 +161,7 @@ class grade_edit_tree {
             // do not diplay children
             $cell = new html_table_cell();
             $cell->colspan = 12;
-            $cell->add_classes(array($element['type'], 'moving'));
+            $cell->attributes['class'] = $element['type'] . ' moving';
             $cell->text = $object->name.' ('.get_string('move').')';
             return array(new html_table_row(array($cell)));
         }
@@ -278,16 +278,16 @@ class grade_edit_tree {
             }
 
             $row = new html_table_row();
-            $row->add_classes(array($courseclass, 'category', $dimmed));
+            $row->attributes['class'] = $courseclass . ' category ' . $dimmed;
             foreach ($rowclasses as $class) {
-                $row->add_class($class);
+                $row->attributes['class'] .= ' ' . $class;
             }
 
             $headercell = new html_table_cell();
             $headercell->header = true;
             $headercell->scope = 'row';
-            $headercell->title = $object->stripped_name;
-            $headercell->add_classes(array('cell', 'rowspan', $levelclass));
+            $headercell->attributes['title'] = $object->stripped_name;
+            $headercell->attributes['class'] = 'cell rowspan ' . $levelclass;
             $headercell->rowspan = $row_count+1+$row_count_offset;
             $row->cells[] = $headercell;
 
@@ -304,7 +304,7 @@ class grade_edit_tree {
             // Print a coloured row to show the end of the category accross the table
             $endcell = new html_table_cell();
             $endcell->colspan = (19 - $level);
-            $endcell->add_classes(array('colspan', $levelclass));
+            $endcell->attributes['class'] = 'colspan ' . $levelclass;
 
             $returnrows[] = new html_table_row(array($endcell));;
 
@@ -321,9 +321,9 @@ class grade_edit_tree {
 
             $dimmed = ($item->is_hidden()) ? "dimmed_text" : "";
             $gradeitemrow = new html_table_row();
-            $gradeitemrow->add_classes(array($categoryitemclass, 'item', $dimmed));
+            $gradeitemrow->attributes['class'] = $categoryitemclass . ' item ' . $dimmed;
             foreach ($rowclasses as $class) {
-                $gradeitemrow->add_class($class);
+                $gradeitemrow->attributes['class'] .= ' ' . $class;
             }
 
             foreach ($this->columns as $column) {
@@ -518,13 +518,13 @@ abstract class grade_edit_tree_column {
         $this->headercell = new html_table_cell();
         $this->headercell->header = true;
         $this->headercell->style = 'whitespace: normal;';
-        $this->headercell->add_class('header');
+        $this->headercell->attributes['class'] = 'header';
 
         $this->categorycell = new html_table_cell();
-        $this->categorycell->add_class('cell');
+        $this->categorycell->attributes['class']  = 'cell';
 
         $this->itemcell = new html_table_cell();
-        $this->itemcell->add_class('cell');
+        $this->itemcell->attributes['class'] = 'cell';
     }
 }
 
@@ -573,7 +573,7 @@ class grade_edit_tree_column_name extends grade_edit_tree_column {
 
     public function get_header_cell() {
         $headercell = clone($this->headercell);
-        $headercell->add_class('name');
+        $headercell->attributes['class'] .= ' name';
         $headercell->colspan = $this->deepest_level + 1;
         $headercell->text = get_string('name');
         return $headercell;
@@ -585,7 +585,7 @@ class grade_edit_tree_column_name extends grade_edit_tree_column {
             throw new Exception('Array key (name or level) missing from 3rd param of grade_edit_tree_column_name::get_category_cell($category, $levelclass, $params)');
         }
         $categorycell = clone($this->categorycell);
-        $categorycell->add_classes(array('name', $levelclass));
+        $categorycell->attributes['class'] .= ' name ' . $levelclass;
         $categorycell->colspan = ($this->deepest_level +1) - $params['level'];
         $categorycell->text = $OUTPUT->heading($params['name'], 4);
         return $categorycell;
@@ -601,7 +601,7 @@ class grade_edit_tree_column_name extends grade_edit_tree_column {
         $name = $params['name'];
 
         $itemcell = clone($this->itemcell);
-        $itemcell->add_class('name');
+        $itemcell->attributes['class'] .= ' name';
         $itemcell->colspan = ($this->deepest_level + 1) - $params['level'];
         $itemcell->text = $name;
         return $itemcell;
@@ -659,7 +659,7 @@ class grade_edit_tree_column_aggregation extends grade_edit_tree_column_category
         }
 
         $categorycell = clone($this->categorycell);
-        $categorycell->add_class($levelclass);
+        $categorycell->attributes['class'] .= ' ' . $levelclass;
         $categorycell->text = $aggregation;
         return $categorycell;
 
@@ -684,7 +684,7 @@ class grade_edit_tree_column_extracredit extends grade_edit_tree_column {
     public function get_category_cell($category, $levelclass, $params) {
         $item = $category->get_grade_item();
         $categorycell = clone($this->categorycell);
-        $categorycell->add_class($levelclass);
+        $categorycell->attributes['class'] .= ' ' . $levelclass;
         $categorycell->text = grade_edit_tree::get_weight_input($item, 'extra');
         return $categorycell;
     }
@@ -727,7 +727,7 @@ class grade_edit_tree_column_weight extends grade_edit_tree_column {
 
         $item = $category->get_grade_item();
         $categorycell = clone($this->categorycell);
-        $categorycell->add_class($levelclass);
+        $categorycell->attributes['class']  .= ' ' . $levelclass;
         $categorycell->text = grade_edit_tree::get_weight_input($item, 'weight');
         return $categorycell;
     }
@@ -766,7 +766,7 @@ class grade_edit_tree_column_range extends grade_edit_tree_column {
 
     public function get_category_cell($category, $levelclass, $params) {
         $categorycell = clone($this->categorycell);
-        $categorycell->add_classes(array('range', $levelclass));
+        $categorycell->attributes['class'] .= ' range ' . $levelclass;
         $categorycell->text = ' - ';
         return $categorycell;
     }
@@ -828,7 +828,7 @@ class grade_edit_tree_column_aggregateonlygraded extends grade_edit_tree_column_
         }
 
         $categorycell = clone($this->categorycell);
-        $categorycell->add_class($levelclass);
+        $categorycell->attributes['class'] .= ' ' . $levelclass;
         $categorycell->text = $hidden.$aggregateonlygraded;
         return $categorycell;
     }
@@ -865,7 +865,7 @@ class grade_edit_tree_column_aggregatesubcats extends grade_edit_tree_column_cat
         }
 
         $categorycell = clone($this->categorycell);
-        $categorycell->add_class($levelclass);
+        $categorycell->attributes['class'] .= ' ' . $levelclass;
         $categorycell->text = $hidden.$aggregatesubcats;
         return $categorycell;
 
@@ -903,7 +903,7 @@ class grade_edit_tree_column_aggregateoutcomes extends grade_edit_tree_column_ca
         }
 
         $categorycell = clone($this->categorycell);
-        $categorycell->add_class($levelclass);
+        $categorycell->attributes['class'] .= ' ' . $levelclass;
         $categorycell->text = $hidden.$aggregateoutcomes;
         return $categorycell;
     }
@@ -945,7 +945,7 @@ class grade_edit_tree_column_droplow extends grade_edit_tree_column_category {
         }
 
         $categorycell = clone($this->categorycell);
-        $categorycell->add_class($levelclass);
+        $categorycell->attributes['class']  .= ' ' . $levelclass;
         $categorycell->text = $droplow;
         return $categorycell;
     }
@@ -978,7 +978,7 @@ class grade_edit_tree_column_keephigh extends grade_edit_tree_column_category {
         }
 
         $categorycell = clone($this->categorycell);
-        $categorycell->add_class($levelclass);
+        $categorycell->attributes['class'] .= ' ' . $levelclass;
         $categorycell->text = $keephigh;
         return $categorycell;
     }
@@ -1005,7 +1005,7 @@ class grade_edit_tree_column_multfactor extends grade_edit_tree_column {
 
     public function get_category_cell($category, $levelclass, $params) {
         $categorycell = clone($this->categorycell);
-        $categorycell->add_class($levelclass);
+        $categorycell->attributes['class'] .= ' ' . $levelclass;
         $categorycell->text = ' - ';
         return $categorycell;
     }
@@ -1046,7 +1046,7 @@ class grade_edit_tree_column_plusfactor extends grade_edit_tree_column {
 
     public function get_category_cell($category, $levelclass, $params) {
         $categorycell = clone($this->categorycell);
-        $categorycell->add_class($levelclass);
+        $categorycell->attributes['class'] .= ' ' . $levelclass;
         $categorycell->text = ' - ';
         return $categorycell;
 
@@ -1086,7 +1086,7 @@ class grade_edit_tree_column_actions extends grade_edit_tree_column {
 
     public function get_header_cell() {
         $headercell = clone($this->headercell);
-        $headercell->add_class('actions');
+        $headercell->attributes['class'] .= ' actions';
         $headercell->text = get_string('actions');
         return $headercell;
     }
@@ -1098,7 +1098,7 @@ class grade_edit_tree_column_actions extends grade_edit_tree_column {
         }
 
         $categorycell = clone($this->categorycell);
-        $categorycell->add_class($levelclass);
+        $categorycell->attributes['class'] .= ' ' . $levelclass;
         $categorycell->text = $params['actions'];
         return $categorycell;
     }
@@ -1108,7 +1108,7 @@ class grade_edit_tree_column_actions extends grade_edit_tree_column {
             throw new Exception('Array key (actions) missing from 2nd param of grade_edit_tree_column_actions::get_item_cell($item, $params)');
         }
         $itemcell = clone($this->itemcell);
-        $itemcell->add_class('actions');
+        $itemcell->attributes['class'] .= ' actions';
         $itemcell->text = $params['actions'];
         return $itemcell;
     }
@@ -1122,7 +1122,7 @@ class grade_edit_tree_column_select extends grade_edit_tree_column {
 
     public function get_header_cell() {
         $headercell = clone($this->headercell);
-        $headercell->add_class('selection');
+        $headercell->attributes['class'] .= ' selection';
         $headercell->text = get_string('select');
         return $headercell;
     }
@@ -1136,7 +1136,7 @@ class grade_edit_tree_column_select extends grade_edit_tree_column {
         $selectnone = new action_link(new moodle_url('#'), get_string('none'), new component_action('click', 'togglecheckboxes', array('eid' => $params['eid'], 'check' => false)));
 
         $categorycell = clone($this->categorycell);
-        $categorycell->add_classes(array('last', $levelclass));
+        $categorycell->attributes['class'] .= ' last ' . $levelclass;
         $categorycell->style .= 'text-align: center;';
         $categorycell->text = $OUTPUT->render($selectall) . '<br />' . $OUTPUT->render($selectnone);
         return $categorycell;
diff --git a/grade/export/keymanager.php b/grade/export/keymanager.php
index c678e9b..b6d7314 100644
--- a/grade/export/keymanager.php
+++ b/grade/export/keymanager.php
@@ -74,7 +74,7 @@ $table->size  = array('50%', '30%', '10%', '10%');
 $table->align = array('left', 'left', 'left', 'center');
 $table->width = '90%';
 $table->data  = $data;
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 echo $OUTPUT->container_start('buttons mdl-align');
 echo $OUTPUT->single_button(new moodle_url('key.php', array('courseid'=>$course->id)), get_string('newuserkey', 'userkey'));
diff --git a/grade/import/keymanager.php b/grade/import/keymanager.php
index 07fb12c..7d469f6 100644
--- a/grade/import/keymanager.php
+++ b/grade/import/keymanager.php
@@ -71,7 +71,7 @@ $table->size  = array('50%', '30%', '10%', '10%');
 $table->align = array('left', 'left', 'left', 'center');
 $table->width = '90%';
 $table->data  = $data;
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 echo $OUTPUT->container_start('buttons mdl-align');
 echo $OUTPUT->single_button(new moodle_url('key.php', array('courseid'=>$course->id)), get_string('newuserkey', 'userkey'));
diff --git a/grade/report/grader/lib.php b/grade/report/grader/lib.php
index a7e5378..dfedc46 100644
--- a/grade/report/grader/lib.php
+++ b/grade/report/grader/lib.php
@@ -545,7 +545,7 @@ class grade_report_grader extends grade_report {
 
         for ($i = 0; $i < $levels; $i++) {
             $fillercell = new html_table_cell();
-            $fillercell->add_classes(array('fixedcolumn', 'cell', 'topleft'));
+            $fillercell->attributes['class'] = 'fixedcolumn cell topleft';
             $fillercell->text = ' ';
             $fillercell->colspan = $colspan;
             $row = new html_table_row(array($fillercell));
@@ -553,10 +553,10 @@ class grade_report_grader extends grade_report {
         }
 
         $headerrow = new html_table_row();
-        $headerrow->add_class('heading');
+        $headerrow->attributes['class'] = 'heading';
 
         $studentheader = new html_table_cell();
-        $studentheader->add_classes(array('header'));
+        $studentheader->attributes['class'] = 'header';
         $studentheader->scope = 'col';
         $studentheader->header = true;
         $studentheader->id = 'studentheader';
@@ -572,7 +572,7 @@ class grade_report_grader extends grade_report {
             $sortidnumberlink = html_writer::link(new moodle_url($this->baseurl, array('sortitemid'=>'idnumber')), get_string('idnumber'));
 
             $idnumberheader = new html_table_cell();
-            $idnumberheader->add_classes(array('header', 'useridnumber'));
+            $idnumberheader->attributes['class'] = 'header useridnumber';
             $idnumberheader->scope = 'col';
             $idnumberheader->header = true;
             $idnumberheader->text = $arrows['idnumber'];
@@ -589,10 +589,10 @@ class grade_report_grader extends grade_report {
         foreach ($this->users as $userid => $user) {
             $userrow = new html_table_row();
             $userrow->id = 'fixed_user_'.$userid;
-            $userrow->add_classes(array('r'.$this->rowcount++, $rowclasses[$this->rowcount % 2]));
+            $userrow->attributes['class'] = 'r'.$this->rowcount++ . $rowclasses[$this->rowcount % 2];
 
             $usercell = new html_table_cell();
-            $usercell->add_classes(array('user'));
+            $usercell->attributes['class'] = 'user';
             $usercell->header = true;
             $usercell->scope = 'row';
 
@@ -606,7 +606,7 @@ class grade_report_grader extends grade_report {
 
             if (has_capability('gradereport/'.$CFG->grade_profilereport.':view', $this->context)) {
                 $userreportcell = new html_table_cell();
-                $userreportcell->add_class('userreport');
+                $userreportcell->attributes['class'] = 'userreport';
                 $userreportcell->header = true;
                 $a->user = fullname($user);
                 $strgradesforuser = get_string('gradesforuser', 'grades', $a);
@@ -617,7 +617,7 @@ class grade_report_grader extends grade_report {
 
             if ($showuseridnumber) {
                 $idnumbercell = new html_table_cell();
-                $idnumbercell->add_classes(array('header', 'useridnumber'));
+                $idnumbercell->attributes['class'] = 'header useridnumber';
                 $idnumbercell->header = true;
                 $idnumbercell->scope = 'row';
                 $userrow->cells[] = $idnumbercell;
@@ -666,7 +666,7 @@ class grade_report_grader extends grade_report {
             }
 
             $headingrow = new html_table_row();
-            $headingrow->add_class('heading_name_row');
+            $headingrow->attributes['class'] = 'heading_name_row';
 
             foreach ($row as $columnkey => $element) {
                 $sortlink = clone($this->baseurl);
@@ -696,7 +696,7 @@ class grade_report_grader extends grade_report {
 // Element is a filler
                 if ($type == 'filler' or $type == 'fillerfirst' or $type == 'fillerlast') {
                     $fillercell = new html_table_cell();
-                    $fillercell->add_classes(array($type, $catlevel));
+                    $fillercell->attributes['class'] = $type . ' ' . $catlevel;
                     $fillercell->colspan = $colspan;
                     $fillercell->text = '&nbsp;';
                     $fillercell->header = true;
@@ -706,7 +706,7 @@ class grade_report_grader extends grade_report {
 // Element is a category
                 else if ($type == 'category') {
                     $categorycell = new html_table_cell();
-                    $categorycell->add_classes(array('category', $catlevel));
+                    $categorycell->attributes['class'] = 'category ' . $catlevel;
                     $categorycell->colspan = $colspan;
                     $categorycell->text = shorten_text($element['object']->get_name());
                     $categorycell->text .= $this->get_collapsing_icon($element);
@@ -738,10 +738,10 @@ class grade_report_grader extends grade_report {
                     $headerlink = $this->gtree->get_element_header($element, true, $this->get_pref('showactivityicons'), false);
 
                     $itemcell = new html_table_cell();
-                    $itemcell->add_classes(array($type, $catlevel, 'highlightable'));
+                    $itemcell->attributes['class'] = $type . ' ' . $catlevel . 'highlightable';
 
                     if ($element['object']->is_hidden()) {
-                        $itemcell->add_class('hidden');
+                        $itemcell->attributes['class'] .= ' hidden';
                     }
 
                     $itemcell->colspan = $colspan;
@@ -751,7 +751,6 @@ class grade_report_grader extends grade_report {
 
                     $headingrow->cells[] = $itemcell;
                 }
-                
             }
             $rows[] = $headingrow;
         }
@@ -798,7 +797,7 @@ class grade_report_grader extends grade_report {
 
             $itemrow = new html_table_row();
             $itemrow->id = 'user_'.$userid;
-            $itemrow->add_class($rowclasses[$this->rowcount % 2]);
+            $itemrow->attributes['class'] = $rowclasses[$this->rowcount % 2];
 
             $jsarguments['users'][$userid] = fullname($user);
 
@@ -838,19 +837,19 @@ class grade_report_grader extends grade_report {
                 $eid = $this->gtree->get_grade_eid($grade);
                 $element = array('eid'=>$eid, 'object'=>$grade, 'type'=>'grade');
 
-                $itemcell->add_class('grade');
+                $itemcell->attributes['class'] .= ' grade';
                 if ($item->is_category_item()) {
-                    $itemcell->add_class('cat');
+                    $itemcell->attributes['class'] .= ' cat';
                 }
                 if ($item->is_course_item()) {
-                    $itemcell->add_class('course');
+                    $itemcell->attributes['class'] .= ' course';
                 }
                 if ($grade->is_overridden()) {
-                    $itemcell->add_class('overridden');
+                    $itemcell->attributes['class'] .= ' overridden';
                 }
 
                 if ($grade->is_excluded()) {
-                    // $itemcell->add_class('excluded');
+                    // $itemcell->attributes['class'] .= ' excluded';
                 }
 
                 if (!empty($grade->feedback)) {
@@ -950,9 +949,9 @@ class grade_report_grader extends grade_report {
                     $gradedisplaytype = $item->get_displaytype();
 
                     if ($item->scaleid && !empty($scalesarray[$item->scaleid])) {
-                        $itemcell->add_class('grade_type_scale');
+                        $itemcell->attributes['class'] .= ' grade_type_scale';
                     } else if ($item->gradetype != GRADE_TYPE_TEXT) {
-                        $itemcell->add_class('grade_type_text');
+                        $itemcell->attributes['class'] .= ' grade_type_text';
                     }
 
                     if ($item->needsupdate) {
@@ -1020,20 +1019,17 @@ class grade_report_grader extends grade_report {
         if ($fixedstudents) {
             $fixedcolumntable = new html_table();
             $fixedcolumntable->id = 'fixed_column';
-            $fixedcolumntable->add_class('fixed_grades_column');
-            $fixedcolumntable->bodyclasses = 'leftbody';
             $fixedcolumntable->data = $leftrows;
-            $html .= $OUTPUT->container($OUTPUT->table($fixedcolumntable), 'left_scroller');
+            $html .= $OUTPUT->container(html_writer::table($fixedcolumntable), 'left_scroller');
 
             $righttable = new html_table();
             $righttable->id = 'user-grades';
-            $righttable->bodyclasses = array('righttest');
             $righttable->data = $rightrows;
 
-            $html .= $OUTPUT->container($OUTPUT->table($righttable), 'right_scroller');
+            $html .= $OUTPUT->container(html_writer::table($righttable), 'right_scroller');
         } else {
             $fulltable = new html_table();
-            $fulltable->add_classes(array('gradestable', 'flexible', 'boxaligncenter', 'generaltable'));
+            $fulltable->attributes['class'] = 'gradestable flexible boxaligncenter generaltable';
             $fulltable->id = 'user-grades';
 
             // Extract rows from each side (left and right) and collate them into one row each
@@ -1041,7 +1037,7 @@ class grade_report_grader extends grade_report {
                 $row->cells = array_merge($row->cells, $rightrows[$key]->cells);
                 $fulltable->data[] = $row;
             }
-            $html .= $OUTPUT->table($fulltable);
+            $html .= html_writer::table($fulltable);
         }
         return $OUTPUT->container($html, 'gradeparent');
     }
@@ -1058,9 +1054,9 @@ class grade_report_grader extends grade_report {
 
         if ($USER->gradeediting[$this->courseid]) {
             $controlsrow = new html_table_row();
-            $controlsrow->add_class('controls');
+            $controlsrow->attributes['class'] = 'controls';
             $controlscell = new html_table_cell();
-            $controlscell->add_classes(array('header', 'controls'));
+            $controlscell->attributes['class'] = 'header controls';
             $controlscell->colspan = $colspan;
             $controlscell->text = $this->get_lang_string('controls','grades');
 
@@ -1081,9 +1077,9 @@ class grade_report_grader extends grade_report {
 
         if ($this->get_pref('showranges')) {
             $rangerow = new html_table_row();
-            $rangerow->add_classes(array('range', 'r'.$this->rowcount++));
+            $rangerow->attributes['class'] = 'range r'.$this->rowcount++;
             $rangecell = new html_table_cell();
-            $rangecell->add_classes(array('header', 'range'));
+            $rangecell->attributes['class'] = 'header range';
             $rangecell->colspan = $colspan;
             $rangecell->header = true;
             $rangecell->scope = 'row';
@@ -1116,9 +1112,9 @@ class grade_report_grader extends grade_report {
         if ($groupavg) {
             if ($showaveragesgroup) {
                 $groupavgrow = new html_table_row();
-                $groupavgrow->add_classes(array('groupavg', 'r'.$this->rowcount++));
+                $groupavgrow->attributes['class'] = 'groupavg r'.$this->rowcount++;
                 $groupavgcell = new html_table_cell();
-                $groupavgcell->add_classes(array('header', 'range'));
+                $groupavgcell->attributes['class'] = 'header range';
                 $groupavgcell->colspan = $colspan;
                 $groupavgcell->header = true;
                 $groupavgcell->scope = 'row';
@@ -1131,9 +1127,9 @@ class grade_report_grader extends grade_report {
 
             if ($showaverages) {
                 $avgrow = new html_table_row();
-                $avgrow->add_classes(array('avg', 'r'.$this->rowcount++));
+                $avgrow->attributes['class'] = 'avg r'.$this->rowcount++;
                 $avgcell = new html_table_cell();
-                $avgcell->add_classes(array('header', 'range'));
+                $avgcell->attributes['class'] = 'header range';
                 $avgcell->colspan = $colspan;
                 $avgcell->header = true;
                 $avgcell->scope = 'row';
@@ -1155,7 +1151,7 @@ class grade_report_grader extends grade_report {
         global $USER;
         if ($USER->gradeediting[$this->courseid]) {
             $iconsrow = new html_table_row();
-            $iconsrow->add_class('controls');
+            $iconsrow->attributes['class'] = 'controls';
 
             $showuseridnumber = $this->get_pref('showuseridnumber');
 
@@ -1166,7 +1162,7 @@ class grade_report_grader extends grade_report {
                 $eid = $this->gtree->get_item_eid($item);
                 $element = $this->gtree->locate_element($eid);
                 $itemcell = new html_table_cell();
-                $itemcell->add_classes(array('controls', 'icons'));
+                $itemcell->attributes['class'] = 'controls icons';
                 $itemcell->text = $this->get_icons($element);
                 $iconsrow->cells[] = $itemcell;
             }
@@ -1187,13 +1183,13 @@ class grade_report_grader extends grade_report {
             $rangesdisplaytype   = $this->get_pref('rangesdisplaytype');
             $rangesdecimalpoints = $this->get_pref('rangesdecimalpoints');
             $rangerow = new html_table_row();
-            $rangerow->add_classes(array('heading', 'range'));
+            $rangerow->attributes['class'] = 'heading range';
 
             foreach ($this->gtree->items as $itemid=>$unused) {
                 $item =& $this->gtree->items[$itemid];
                 $itemcell = new html_table_cell();
                 $itemcell->header = true;
-                $itemcell->add_classes(array('header', 'range'));
+                $itemcell->attributes['class'] .= ' header range';
 
                 $hidden = '';
                 if ($item->is_hidden()) {
@@ -1301,7 +1297,7 @@ class grade_report_grader extends grade_report {
             $ungradedcounts = $DB->get_records_sql($SQL, $params);
 
             $avgrow = new html_table_row();
-            $avgrow->add_class('avg');
+            $avgrow->attributes['class'] = 'avg';
 
             foreach ($this->gtree->items as $itemid=>$unused) {
                 $item =& $this->gtree->items[$itemid];
diff --git a/grade/report/grader/styles.css b/grade/report/grader/styles.css
index 441cb05..27f34b8 100644
--- a/grade/report/grader/styles.css
+++ b/grade/report/grader/styles.css
@@ -435,7 +435,7 @@ font-size:100%;
 padding:0;
 }
 
-.grade-report-grader .righttest td select {
+.grade-report-grader .right_scroller td select {
 font-size:86%;
 padding:0;
 }
@@ -615,4 +615,4 @@ position:absolute;
 
 .ie6 .excludedfloater {
 font-size:7px;
-}
\ No newline at end of file
+}
diff --git a/group/autogroup.php b/group/autogroup.php
index 3e2e66b..34057dc 100644
--- a/group/autogroup.php
+++ b/group/autogroup.php
@@ -171,7 +171,7 @@ if ($editform->is_cancelled()) {
             $table->data[] = $line;
         }
 
-        $preview .= $OUTPUT->table($table);
+        $preview .= html_writer::table($table);
 
     } else {
         $grouping = null;
diff --git a/group/groupings.php b/group/groupings.php
index 5eeea45..4208955 100644
--- a/group/groupings.php
+++ b/group/groupings.php
@@ -98,7 +98,7 @@ $table->size  = array('30%', '50%', '10%', '10%');
 $table->align = array('left', 'left', 'center', 'center');
 $table->width = '90%';
 $table->data  = $data;
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 echo $OUTPUT->container_start('buttons');
 echo $OUTPUT->single_button(new moodle_url('grouping.php', array('courseid'=>$courseid)), $srtnewgrouping);
diff --git a/group/overview.php b/group/overview.php
index ad8e5c5..a9e8d2d 100644
--- a/group/overview.php
+++ b/group/overview.php
@@ -207,7 +207,7 @@ foreach ($members as $gpgid=>$groupdata) {
             echo $OUTPUT->box(format_text($description, $groupings[$gpgid]->descriptionformat, $options), 'generalbox boxwidthnarrow boxaligncenter');
         }
     }
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
     $printed = true;
 }
 
diff --git a/lib/adminlib.php b/lib/adminlib.php
index 6e9126c..b5814f9 100644
--- a/lib/adminlib.php
+++ b/lib/adminlib.php
@@ -4836,7 +4836,7 @@ class admin_setting_manageauths extends admin_setting {
             // add a row to the table
             $table->data[] =array($displayname, $hideshow, $updown, $settings);
         }
-        $return .= $OUTPUT->table($table);
+        $return .= html_writer::table($table);
         $return .= get_string('configauthenticationplugins', 'admin').'<br />'.get_string('tablenosave', 'filters');
         $return .= $OUTPUT->box_end();
         return highlight($query, $return);
@@ -5001,7 +5001,7 @@ class admin_setting_manageeditors extends admin_setting {
             // add a row to the table
             $table->data[] =array($displayname, $hideshow, $updown, $settings);
         }
-        $return .= $OUTPUT->table($table);
+        $return .= html_writer::table($table);
         $return .= get_string('configeditorplugins', 'editor').'<br />'.get_string('tablenosave', 'admin');
         $return .= $OUTPUT->box_end();
         return highlight($query, $return);
@@ -5177,7 +5177,7 @@ class admin_setting_manageportfolio extends admin_setting {
             }
         }
 
-        $output .= $OUTPUT->table($table);
+        $output .= html_writer::table($table);
 
         $instancehtml = '<br /><br />' . get_string('addnewportfolio', 'portfolio') . ': <br /><br />';
         $addable = 0;
@@ -6072,7 +6072,7 @@ class admin_setting_managerepository extends admin_setting {
                 $alreadyplugins[] = $i->get_typename();
             }
         }
-        $output .= $OUTPUT->table($table);
+        $output .= html_writer::table($table);
         $instancehtml = '<div><h3>';
         $instancehtml .= get_string('addplugin', 'repository');
         $instancehtml .= '</h3><ul>';
@@ -6228,7 +6228,7 @@ class admin_setting_manageexternalservices extends admin_setting {
                 // add a row to the table
                 $table->data[] = array($displayname, $plugin, $functions, $users, $edit);
             }
-            $return .= $OUTPUT->table($table);
+            $return .= html_writer::table($table);
         }
 
         // Custom services
@@ -6270,7 +6270,7 @@ class admin_setting_manageexternalservices extends admin_setting {
             $table->data[] = array($displayname, $delete, $functions, $users, $edit);
         }
         // add new custom service option
-        $return .= $OUTPUT->table($table);
+        $return .= html_writer::table($table);
 
         $return .= '<br />';
         // add a token to the table
@@ -6443,7 +6443,7 @@ class admin_setting_webservicesoverview extends admin_setting {
         $row[2] = get_string('testwithtestclientdescription', 'webservice');
         $table->data[] = $row;
 
-        $return .= $OUTPUT->table($table);
+        $return .= html_writer::table($table);
 
     /// Users as clients with token
         $return .= "<br/><br/><br/>";
@@ -6519,7 +6519,7 @@ class admin_setting_webservicesoverview extends admin_setting {
         $row[2] = get_string('testauserwithtestclientdescription', 'webservice');
         $table->data[] = $row;
 
-        $return .= $OUTPUT->table($table);
+        $return .= html_writer::table($table);
 
         return highlight($query, $return);
     }
@@ -6667,7 +6667,7 @@ class admin_setting_managewebserviceprotocols extends admin_setting {
             // add a row to the table
             $table->data[] = array($displayname, $version, $hideshow, $uninstall, $settings);
         }
-        $return .= $OUTPUT->table($table);
+        $return .= html_writer::table($table);
         $return .= get_string('configwebserviceplugins', 'webservice');
         $return .= $OUTPUT->box_end();
 
@@ -6783,7 +6783,7 @@ class admin_setting_managewebservicetokens extends admin_setting {
                 $table->data[] = array($token->token, $useratag, $token->name, '', $iprestriction, $validuntil, $delete);
             }
 
-            $return .= $OUTPUT->table($table);
+            $return .= html_writer::table($table);
             $return .= get_string('httpswarning', 'webservice');
         } else {
             $return .= get_string('notoken', 'webservice');
diff --git a/lib/deprecatedlib.php b/lib/deprecatedlib.php
index f3b82ae..9accb24 100644
--- a/lib/deprecatedlib.php
+++ b/lib/deprecatedlib.php
@@ -2400,7 +2400,7 @@ function blocks_move_block($page, &$instance, $destpos, $destweight=NULL, $pinne
 function print_table($table, $return=false) {
     global $OUTPUT;
     // TODO MDL-19755 turn debugging on once we migrate the current core code to use the new API
-    debugging('print_table() has been deprecated. Please change your code to use $OUTPUT->table().');
+    debugging('print_table() has been deprecated. Please change your code to use html_writer::table().');
     $newtable = new html_table();
     foreach ($table as $property => $value) {
         if (property_exists($newtable, $property)) {
@@ -2408,13 +2408,13 @@ function print_table($table, $return=false) {
         }
     }
     if (isset($table->class)) {
-        $newtable->set_classes($table->class);
+        $newtable->attributes['class'] = $table->class;
     }
     if (isset($table->rowclass) && is_array($table->rowclass)) {
         debugging('rowclass[] has been deprecated for html_table and should be replaced by rowclasses[]. please fix the code.');
         $newtable->rowclasses = $table->rowclass;
     }
-    $output = $OUTPUT->table($newtable);
+    $output = html_writer::table($newtable);
     if ($return) {
         return $output;
     } else {
diff --git a/lib/environmentlib.php b/lib/environmentlib.php
index 3c8e7c5..98c914d 100644
--- a/lib/environmentlib.php
+++ b/lib/environmentlib.php
@@ -173,8 +173,7 @@ function print_moodle_environment($result, $environment_results) {
     $servertable->align = array ('center', 'center', 'left', 'center');
     $servertable->wrap  = array ('nowrap', '', '', 'nowrap');
     $servertable->size  = array ('10', 10, '100%', '10');
-    $servertable->width = '90%';
-    $servertable->add_class('environmenttable generaltable');
+    $servertable->attributes['class'] = 'environmenttable generaltable';
 
     $serverdata = array('ok'=>array(), 'warn'=>array(), 'error'=>array());
 
@@ -183,8 +182,7 @@ function print_moodle_environment($result, $environment_results) {
     $othertable->align = array ('center', 'left', 'center');
     $othertable->wrap  = array ('', '', 'nowrap');
     $othertable->size  = array (10, '100%', '10');
-    $othertable->width = '90%';
-    $othertable->add_class('environmenttable generaltable');
+    $othertable->attributes['class'] = 'environmenttable generaltable';
 
     $otherdata = array('ok'=>array(), 'warn'=>array(), 'error'=>array());
 
@@ -309,10 +307,10 @@ function print_moodle_environment($result, $environment_results) {
 
 /// Print table
     echo $OUTPUT->heading(get_string('serverchecks', 'admin'));
-    echo $OUTPUT->table($servertable);
+    echo html_writer::table($servertable);
     if (count($othertable->data)){
         echo $OUTPUT->heading(get_string('customcheck', 'admin'));
-        echo $OUTPUT->table($othertable);
+        echo html_writer::table($othertable);
     }
 
 /// Finally, if any error has happened, print the summary box
diff --git a/lib/outputcomponents.php b/lib/outputcomponents.php
index 5a602ad..aed1ec5 100644
--- a/lib/outputcomponents.php
+++ b/lib/outputcomponents.php
@@ -604,7 +604,6 @@ class action_link implements renderable {
     }
 }
 
-
 // ==== HTML writer and helper classes, will be probably moved elsewhere ======
 
 /**
@@ -969,6 +968,216 @@ class html_writer {
             return '';
         }
     }
+
+    /**
+     * Renders HTML table
+     *
+     * This method may modify the passed instance by adding some default properties if they are not set yet.
+     * If this is not what you want, you should make a full clone of your data before passing them to this
+     * method. In most cases this is not an issue at all so we do not clone by default for performance
+     * and memory consumption reasons.
+     *
+     * @param html_table $table data to be rendered
+     * @return string HTML code
+     */
+    public static function table(html_table $table) {
+        // prepare table data and populate missing properties with reasonable defaults
+        if (!empty($table->align)) {
+            foreach ($table->align as $key => $aa) {
+                if ($aa) {
+                    $table->align[$key] = 'text-align:'. fix_align_rtl($aa) .';';  // Fix for RTL languages
+                } else {
+                    $table->align[$key] = null;
+                }
+            }
+        }
+        if (!empty($table->size)) {
+            foreach ($table->size as $key => $ss) {
+                if ($ss) {
+                    $table->size[$key] = 'width:'. $ss .';';
+                } else {
+                    $table->size[$key] = null;
+                }
+            }
+        }
+        if (!empty($table->wrap)) {
+            foreach ($table->wrap as $key => $ww) {
+                if ($ww) {
+                    $table->wrap[$key] = 'white-space:nowrap;';
+                } else {
+                    $table->wrap[$key] = '';
+                }
+            }
+        }
+        if (!empty($table->head)) {
+            foreach ($table->head as $key => $val) {
+                if (!isset($table->align[$key])) {
+                    $table->align[$key] = null;
+                }
+                if (!isset($table->size[$key])) {
+                    $table->size[$key] = null;
+                }
+                if (!isset($table->wrap[$key])) {
+                    $table->wrap[$key] = null;
+                }
+
+            }
+        }
+        if (empty($table->attributes['class'])) {
+            $table->attributes['class'] = 'generaltable';
+        }
+        if (!empty($table->tablealign)) {
+            $table->attributes['class'] .= ' boxalign' . $table->tablealign;
+        }
+
+        // explicitly assigned properties override those defined via $table->attributes
+        $attributes = array_merge($table->attributes, array(
+                'id'            => $table->id,
+                'width'         => $table->width,
+                'summary'       => $table->summary,
+                'cellpadding'   => $table->cellpadding,
+                'cellspacing'   => $table->cellspacing,
+            ));
+        $output = html_writer::start_tag('table', $attributes) . "\n";
+
+        $countcols = 0;
+
+        if (!empty($table->head)) {
+            $countcols = count($table->head);
+            $output .= html_writer::start_tag('thead', array()) . "\n";
+            $output .= html_writer::start_tag('tr', array()) . "\n";
+            $keys = array_keys($table->head);
+            $lastkey = end($keys);
+
+            foreach ($table->head as $key => $heading) {
+                // Convert plain string headings into html_table_cell objects
+                if (!($heading instanceof html_table_cell)) {
+                    $headingtext = $heading;
+                    $heading = new html_table_cell();
+                    $heading->text = $headingtext;
+                    $heading->header = true;
+                }
+
+                if ($heading->header !== false) {
+                    $heading->header = true;
+                }
+
+                $heading->attributes['class'] .= ' header c' . $key;
+                if (isset($table->headspan[$key]) && $table->headspan[$key] > 1) {
+                    $heading->colspan = $table->headspan[$key];
+                    $countcols += $table->headspan[$key] - 1;
+                }
+
+                if ($key == $lastkey) {
+                    $heading->attributes['class'] .= ' lastcol';
+                }
+                if (isset($table->colclasses[$key])) {
+                    $heading->attributes['class'] .= ' ' . $table->colclasses[$key];
+                }
+
+                $attributes = array_merge($heading->attributes, array(
+                        'style'     => $table->align[$key] . $table->size[$key] . $heading->style,
+                        'scope'     => $heading->scope,
+                        'colspan'   => $heading->colspan,
+                    ));
+
+                $tagtype = 'td';
+                if ($heading->header === true) {
+                    $tagtype = 'th';
+                }
+                $output .= html_writer::tag($tagtype, $heading->text, $attributes) . "\n";
+            }
+            $output .= html_writer::end_tag('tr') . "\n";
+            $output .= html_writer::end_tag('thead') . "\n";
+
+            if (empty($table->data)) {
+                // For valid XHTML strict every table must contain either a valid tr
+                // or a valid tbody... both of which must contain a valid td
+                $output .= html_writer::start_tag('tbody', array('class' => 'empty'));
+                $output .= html_writer::tag('tr', html_writer::tag('td', '', array('colspan'=>count($table->head))));
+                $output .= html_writer::end_tag('tbody');
+            }
+        }
+
+        if (!empty($table->data)) {
+            $oddeven    = 1;
+            $keys       = array_keys($table->data);
+            $lastrowkey = end($keys);
+            $output .= html_writer::start_tag('tbody', array());
+
+            foreach ($table->data as $key => $row) {
+                if (($row === 'hr') && ($countcols)) {
+                    $output .= html_writer::tag('td', html_writer::tag('div', '', array('class' => 'tabledivider')), array('colspan' => $countcols));
+                } else {
+                    // Convert array rows to html_table_rows and cell strings to html_table_cell objects
+                    if (!($row instanceof html_table_row)) {
+                        $newrow = new html_table_row();
+
+                        foreach ($row as $unused => $item) {
+                            $cell = new html_table_cell();
+                            $cell->text = $item;
+                            $newrow->cells[] = $cell;
+                        }
+                        $row = $newrow;
+                    }
+
+                    $oddeven = $oddeven ? 0 : 1;
+                    if (isset($table->rowclasses[$key])) {
+                        $row->attributes['class'] .= ' ' . $table->rowclasses[$key];
+                    }
+
+                    $row->attributes['class'] .= ' r' . $oddeven;
+                    if ($key == $lastrowkey) {
+                        $row->attributes['class'] .= ' lastrow';
+                    }
+
+                    $output .= html_writer::start_tag('tr', array('class' => $row->attributes['class'], 'style' => $row->style, 'id' => $row->id)) . "\n";
+                    $keys2 = array_keys($row->cells);
+                    $lastkey = end($keys2);
+
+                    foreach ($row->cells as $key => $cell) {
+                        if (!($cell instanceof html_table_cell)) {
+                            $mycell = new html_table_cell();
+                            $mycell->text = $cell;
+                            $cell = $mycell;
+                        }
+
+                        if (isset($table->colclasses[$key])) {
+                            $cell->attributes['class'] .= ' ' . $table->colclasses[$key];
+                        }
+
+                        $cell->attributes['class'] .= ' cell c' . $key;
+                        if ($key == $lastkey) {
+                            $cell->attributes['class'] .= ' lastcol';
+                        }
+                        $tdstyle = '';
+                        $tdstyle .= isset($table->align[$key]) ? $table->align[$key] : '';
+                        $tdstyle .= isset($table->size[$key]) ? $table->size[$key] : '';
+                        $tdstyle .= isset($table->wrap[$key]) ? $table->wrap[$key] : '';
+                        $tdattributes = array_merge($cell->attributes, array(
+                                'style' => $tdstyle . $cell->style,
+                                'colspan' => $cell->colspan,
+                                'rowspan' => $cell->rowspan,
+                                'id' => $cell->id,
+                                'abbr' => $cell->abbr,
+                                'scope' => $cell->scope,
+                            ));
+                        $tagtype = 'td';
+                        if ($cell->header === true) {
+                            $tagtype = 'th';
+                        }
+                        $output .= html_writer::tag($tagtype, $cell->text, $tdattributes) . "\n";
+                    }
+                }
+                $output .= html_writer::end_tag('tr') . "\n";
+            }
+            $output .= html_writer::end_tag('tbody') . "\n";
+        }
+        $output .= html_writer::end_tag('table') . "\n";
+
+        return $output;
+    }
+
 }
 
 // ==== JS writer and helper classes, will be probably moved elsewhere ======
@@ -1093,126 +1302,31 @@ class js_writer {
     }
 }
 
-
-// ===============================================================================================
-// TODO: Following HTML components still need some refactoring
-
 /**
- * Base class for classes representing HTML elements.
+ * Holds all the information required to render a <table> by {@see core_renderer::table()}
  *
- * Handles the id and class attributes.
+ * Example of usage:
+ * $t = new html_table();
+ * ... // set various properties of the object $t as described below
+ * echo html_writer::table($t);
  *
- * @copyright 2009 Tim Hunt
+ * @copyright 2009 David Mudrak <david.mudrak@gmail.com>
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  * @since     Moodle 2.0
  */
-class html_component {
+class html_table {
     /**
-     * @var string value to use for the id attribute of this HTML tag.
+     * @var string value to use for the id attribute of the table
      */
     public $id = null;
     /**
-     * @var string $alt value to use for the alt attribute of this HTML tag.
-     */
-    public $alt = null;
-    /**
-     * @var string $style value to use for the style attribute of this HTML tag.
+     * @var string $style value to use for the style attribute of the table
      */
     public $style = null;
     /**
-     * @var array class names to add to this HTML element.
-     */
-    public $classes = array();
-    /**
-     * @var string $title The title attributes applicable to any XHTML element
-     */
-    public $title = null;
-    /**
-     * An optional array of component_action objects handling the action part of this component.
-     * @var array $actions
-     */
-    protected $actions = array();
-
-    /**
-     * Ensure some class names are an array.
-     * @param mixed $classes either an array of class names or a space-separated
-     *      string containing class names.
-     * @return array the class names as an array.
-     */
-    public static function clean_classes($classes) {
-        if (empty($classes)) {
-            return array();
-        } else if (is_array($classes)) {
-            return $classes;
-        } else {
-            return explode(' ', trim($classes));
-        }
-    }
-
-    /**
-     * Set the class name array.
-     * @param mixed $classes either an array of class names or a space-separated
-     *      string containing class names.
-     * @return void
-     */
-    public function set_classes($classes) {
-        $this->classes = self::clean_classes($classes);
-    }
-
-    /**
-     * Add a class name to the class names array.
-     * @param string $class the new class name to add.
-     * @return void
-     */
-    public function add_class($class) {
-        $this->classes[] = $class;
-    }
-
-    /**
-     * Add a whole lot of class names to the class names array.
-     * @param mixed $classes either an array of class names or a space-separated
-     *      string containing class names.
-     * @return void
+     * @var array attributes of HTML attributes for the <table> element
      */
-    public function add_classes($classes) {
-        $this->classes = array_merge($this->classes, self::clean_classes($classes));
-    }
-
-    /**
-     * Get the class names as a string.
-     * @return string the class names as a space-separated string. Ready to be put in the class="" attribute.
-     */
-    public function get_classes_string() {
-        return implode(' ', $this->classes);
-    }
-
-    /**
-     * Perform any cleanup or final processing that should be done before an
-     * instance of this class is output. This method is supposed to be called
-     * only from renderers.
-     * @return void
-     */
-    public function prepare() {
-        $this->classes = array_unique(self::clean_classes($this->classes));
-    }
-}
-
-
-/**
- * Holds all the information required to render a <table> by
- * {@see core_renderer::table()} or by an overridden version of that
- * method in a subclass.
- *
- * Example of usage:
- * $t = new html_table();
- * ... // set various properties of the object $t as described below
- * echo $OUTPUT->table($t);
- *
- * @copyright 2009 David Mudrak <david.mudrak@gmail.com>
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- * @since     Moodle 2.0
- */
-class html_table extends html_component {
+    public $attributes = array();
     /**
      * For more control over the rendering of the headers, an array of html_table_cell objects
      * can be passed instead of an array of strings.
@@ -1287,7 +1401,7 @@ class html_table extends html_component {
      */
     public $data;
     /**
-     * @var string width of the table, percentage of the page preferred. Defaults to 80% of the page width.
+     * @var string width of the table, percentage of the page preferred. Defaults to 80%
      * @deprecated since Moodle 2.0. Styling should be in the CSS.
      */
     public $width = null;
@@ -1331,82 +1445,12 @@ class html_table extends html_component {
      * @var string description of the contents for screen readers.
      */
     public $summary;
-    /**
-     * @var bool true causes the contents of the heading cells to be rotated 90 degrees.
-     */
-    public $rotateheaders = false;
-    /**
-     * @var array $headclasses Array of CSS classes to apply to the table's thead.
-     */
-    public $headclasses = array();
-    /**
-     * @var array $bodyclasses Array of CSS classes to apply to the table's tbody.
-     */
-    public $bodyclasses = array();
-    /**
-     * @var array $footclasses Array of CSS classes to apply to the table's tfoot.
-     */
-    public $footclasses = array();
-
 
     /**
-     * @see html_component::prepare()
-     * @return void
+     * Constructor
      */
-    public function prepare() {
-        if (!empty($this->align)) {
-            foreach ($this->align as $key => $aa) {
-                if ($aa) {
-                    $this->align[$key] = 'text-align:'. fix_align_rtl($aa) .';';  // Fix for RTL languages
-                } else {
-                    $this->align[$key] = null;
-                }
-            }
-        }
-        if (!empty($this->size)) {
-            foreach ($this->size as $key => $ss) {
-                if ($ss) {
-                    $this->size[$key] = 'width:'. $ss .';';
-                } else {
-                    $this->size[$key] = null;
-                }
-            }
-        }
-        if (!empty($this->wrap)) {
-            foreach ($this->wrap as $key => $ww) {
-                if ($ww) {
-                    $this->wrap[$key] = 'white-space:nowrap;';
-                } else {
-                    $this->wrap[$key] = '';
-                }
-            }
-        }
-        if (!empty($this->head)) {
-            foreach ($this->head as $key => $val) {
-                if (!isset($this->align[$key])) {
-                    $this->align[$key] = null;
-                }
-                if (!isset($this->size[$key])) {
-                    $this->size[$key] = null;
-                }
-                if (!isset($this->wrap[$key])) {
-                    $this->wrap[$key] = null;
-                }
-
-            }
-        }
-        if (empty($this->classes)) { // must be done before align
-            $this->set_classes(array('generaltable'));
-        }
-        if (!empty($this->tablealign)) {
-            $this->add_class('boxalign' . $this->tablealign);
-        }
-        if (!empty($this->rotateheaders)) {
-            $this->add_class('rotateheaders');
-        } else {
-            $this->rotateheaders = false; // Makes life easier later.
-        }
-        parent::prepare();
+    public function __construct() {
+        $this->attributes['class'] = '';
     }
 }
 
@@ -1418,25 +1462,30 @@ class html_table extends html_component {
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  * @since     Moodle 2.0
  */
-class html_table_row extends html_component {
+class html_table_row {
+    /**
+     * @var string value to use for the id attribute of the row
+     */
+    public $id = null;
     /**
      * @var array $cells Array of html_table_cell objects
      */
     public $cells = array();
-
     /**
-     * @see lib/html_component#prepare()
-     * @return void
+     * @var string $style value to use for the style attribute of the table row
      */
-    public function prepare() {
-        parent::prepare();
-    }
+    public $style = null;
+    /**
+     * @var array attributes of additional HTML attributes for the <tr> element
+     */
+    public $attributes = array();
 
     /**
      * Constructor
      * @param array $cells
      */
     public function __construct(array $cells=null) {
+        $this->attributes['class'] = '';
         $cells = (array)$cells;
         foreach ($cells as $cell) {
             if ($cell instanceof html_table_cell) {
@@ -1456,7 +1505,11 @@ class html_table_row extends html_component {
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  * @since     Moodle 2.0
  */
-class html_table_cell extends html_component {
+class html_table_cell {
+    /**
+     * @var string value to use for the id attribute of the cell
+     */
+    public $id = null;
     /**
      * @var string $text The contents of the cell
      */
@@ -1481,20 +1534,29 @@ class html_table_cell extends html_component {
      * @var boolean $header Whether or not this cell is a header cell
      */
     public $header = null;
+    /**
+     * @var string $style value to use for the style attribute of the table cell
+     */
+    public $style = null;
+    /**
+     * @var array attributes of additional HTML attributes for the <tr> element
+     */
+    public $attributes = array();
 
     /**
+     * XXX TODO DONOTCOMMIT
      * @see lib/html_component#prepare()
      * @return void
-     */
     public function prepare() {
         if ($this->header && empty($this->scope)) {
             $this->scope = 'col';
         }
-        parent::prepare();
     }
+     */
 
     public function __construct($text = null) {
         $this->text = $text;
+        $this->attributes['class'] = '';
     }
 }
 
@@ -1574,7 +1636,6 @@ class paging_bar implements renderable {
     }
 
     /**
-     * @see lib/html_component#prepare()
      * @return void
      */
     public function prepare(renderer_base $output, moodle_page $page, $target) {
diff --git a/lib/outputrenderers.php b/lib/outputrenderers.php
index 36159a8..2e5175a 100644
--- a/lib/outputrenderers.php
+++ b/lib/outputrenderers.php
@@ -1801,173 +1801,6 @@ END;
     }
 
     /**
-     * Render a HTML table
-     *
-     * @param object $table {@link html_table} instance containing all the information needed
-     * @return string the HTML to output.
-     */
-    public function table(html_table $table) {
-        $table = clone($table);
-        $table->prepare($this, $this->page, $this->target);
-        $attributes = array(
-                'id'            => $table->id,
-                'width'         => $table->width,
-                'summary'       => $table->summary,
-                'cellpadding'   => $table->cellpadding,
-                'cellspacing'   => $table->cellspacing,
-                'class'         => $table->get_classes_string());
-        $output = html_writer::start_tag('table', $attributes) . "\n";
-
-        $countcols = 0;
-
-        if (!empty($table->head)) {
-            $countcols = count($table->head);
-            $output .= html_writer::start_tag('thead', $table->headclasses) . "\n";
-            $output .= html_writer::start_tag('tr', array()) . "\n";
-            $keys = array_keys($table->head);
-            $lastkey = end($keys);
-
-            foreach ($table->head as $key => $heading) {
-                // Convert plain string headings into html_table_cell objects
-                if (!($heading instanceof html_table_cell)) {
-                    $headingtext = $heading;
-                    $heading = new html_table_cell();
-                    $heading->text = $headingtext;
-                    $heading->header = true;
-                }
-
-                if ($heading->header !== false) {
-                    $heading->header = true;
-                }
-
-                $heading->add_classes(array('header', 'c' . $key));
-                if (isset($table->headspan[$key]) && $table->headspan[$key] > 1) {
-                    $heading->colspan = $table->headspan[$key];
-                    $countcols += $table->headspan[$key] - 1;
-                }
-
-                if ($key == $lastkey) {
-                    $heading->add_class('lastcol');
-                }
-                if (isset($table->colclasses[$key])) {
-                    $heading->add_class($table->colclasses[$key]);
-                }
-                if ($table->rotateheaders) {
-                    // we need to wrap the heading content
-                    $heading->text = html_writer::tag('span', $heading->text);
-                }
-
-                $attributes = array(
-                        'style'     => $table->align[$key] . $table->size[$key] . $heading->style,
-                        'class'     => $heading->get_classes_string(),
-                        'scope'     => $heading->scope,
-                        'colspan'   => $heading->colspan);
-
-                $tagtype = 'td';
-                if ($heading->header === true) {
-                    $tagtype = 'th';
-                }
-                $output .= html_writer::tag($tagtype, $heading->text, $attributes) . "\n";
-            }
-            $output .= html_writer::end_tag('tr') . "\n";
-            $output .= html_writer::end_tag('thead') . "\n";
-
-            if (empty($table->data)) {
-                // For valid XHTML strict every table must contain either a valid tr
-                // or a valid tbody... both of which must contain a valid td
-                $output .= html_writer::start_tag('tbody', array('class' => renderer_base::prepare_classes($table->bodyclasses).' empty'));
-                $output .= html_writer::tag('tr', html_writer::tag('td', '', array('colspan'=>count($table->head))));
-                $output .= html_writer::end_tag('tbody');
-            }
-        }
-
-        if (!empty($table->data)) {
-            $oddeven    = 1;
-            $keys       = array_keys($table->data);
-            $lastrowkey = end($keys);
-            $output .= html_writer::start_tag('tbody', array('class' => renderer_base::prepare_classes($table->bodyclasses))) . "\n";
-
-            foreach ($table->data as $key => $row) {
-                if (($row === 'hr') && ($countcols)) {
-                    $output .= html_writer::tag('td', html_writer::tag('div', '', array('class' => 'tabledivider')), array('colspan' => $countcols)) . "\n";
-                } else {
-                    // Convert array rows to html_table_rows and cell strings to html_table_cell objects
-                    if (!($row instanceof html_table_row)) {
-                        $newrow = new html_table_row();
-
-                        foreach ($row as $unused => $item) {
-                            $cell = new html_table_cell();
-                            $cell->text = $item;
-                            $newrow->cells[] = $cell;
-                        }
-                        $row = $newrow;
-                    }
-
-                    $oddeven = $oddeven ? 0 : 1;
-                    if (isset($table->rowclasses[$key])) {
-                        $row->add_classes(array_unique(html_component::clean_classes($table->rowclasses[$key])));
-                    }
-
-                    $row->add_class('r' . $oddeven);
-                    if ($key == $lastrowkey) {
-                        $row->add_class('lastrow');
-                    }
-
-                    $output .= html_writer::start_tag('tr', array('class' => $row->get_classes_string(), 'style' => $row->style, 'id' => $row->id)) . "\n";
-                    $keys2 = array_keys($row->cells);
-                    $lastkey = end($keys2);
-
-                    foreach ($row->cells as $key => $cell) {
-                        if (!($cell instanceof html_table_cell)) {
-                            $mycell = new html_table_cell();
-                            $mycell->text = $cell;
-                            $cell = $mycell;
-                        }
-
-                        if (isset($table->colclasses[$key])) {
-                            $cell->add_classes(array_unique(html_component::clean_classes($table->colclasses[$key])));
-                        }
-
-                        $cell->add_classes('cell');
-                        $cell->add_classes('c' . $key);
-                        if ($key == $lastkey) {
-                            $cell->add_classes('lastcol');
-                        }
-                        $tdstyle = '';
-                        $tdstyle .= isset($table->align[$key]) ? $table->align[$key] : '';
-                        $tdstyle .= isset($table->size[$key]) ? $table->size[$key] : '';
-                        $tdstyle .= isset($table->wrap[$key]) ? $table->wrap[$key] : '';
-                        $tdattributes = array(
-                                'style' => $tdstyle . $cell->style,
-                                'colspan' => $cell->colspan,
-                                'rowspan' => $cell->rowspan,
-                                'id' => $cell->id,
-                                'class' => $cell->get_classes_string(),
-                                'abbr' => $cell->abbr,
-                                'scope' => $cell->scope,
-                                'title' => $cell->title);
-                        $tagtype = 'td';
-                        if ($cell->header === true) {
-                            $tagtype = 'th';
-                        }
-                        $output .= html_writer::tag($tagtype, $cell->text, $tdattributes) . "\n";
-                    }
-                }
-                $output .= html_writer::end_tag('tr') . "\n";
-            }
-            $output .= html_writer::end_tag('tbody') . "\n";
-        }
-        $output .= html_writer::end_tag('table') . "\n";
-
-        if ($table->rotateheaders && can_use_rotated_text()) {
-            $this->page->requires->yui2_lib('event');
-            $this->page->requires->js('/course/report/progress/textrotate.js');
-        }
-
-        return $output;
-    }
-
-    /**
      * Output the place a skip link goes to.
      * @param string $id The target name from the corresponding $PAGE->requires->skip_link_to($target) call.
      * @return string the HTML to output.
diff --git a/lib/portfolio/exporter.php b/lib/portfolio/exporter.php
index 99c6b7c..3af9296 100644
--- a/lib/portfolio/exporter.php
+++ b/lib/portfolio/exporter.php
@@ -423,7 +423,7 @@ class portfolio_exporter {
         foreach ($mainsummary as $string => $value) {
             $table->data[] = array($string, $value);
         }
-        echo $OUTPUT->table($table);
+        echo html_writer::table($table);
         echo $OUTPUT->confirm($strconfirm, $yesurl, $nourl);
         echo $OUTPUT->box_end();
         echo $OUTPUT->footer();
diff --git a/lib/portfoliolib.php b/lib/portfoliolib.php
index 828158c..1dda06e 100644
--- a/lib/portfoliolib.php
+++ b/lib/portfoliolib.php
@@ -894,7 +894,7 @@ function portfolio_report_insane($insane, $instances=false, $return=false) {
         }
         $table->data[] = array($name, get_string($reason, 'portfolio_' . $plugin));
     }
-    $output .= $OUTPUT->table($table);
+    $output .= html_writer::table($table);
     $output .= '<br /><br /><br />';
 
     if ($return) {
diff --git a/lib/questionlib.php b/lib/questionlib.php
index 82c14c0..efb0224 100644
--- a/lib/questionlib.php
+++ b/lib/questionlib.php
@@ -672,7 +672,7 @@ function question_delete_course($course, $feedback=true) {
             $table = new html_table();
             $table->head = array(get_string('category','quiz'), get_string('action'));
             $table->data = $feedbackdata;
-            echo $OUTPUT->table($table);
+            echo html_writer::table($table);
         }
     }
     return true;
@@ -738,7 +738,7 @@ function question_delete_course_category($category, $newcategory, $feedback=true
             $table = new html_table();
             $table->head = array(get_string('questioncategory','question'), get_string('action'));
             $table->data = $feedbackdata;
-            echo $OUTPUT->table($table);
+            echo html_writer::table($table);
         }
 
     } else {
@@ -835,7 +835,7 @@ function question_delete_activity($cm, $feedback=true) {
             $table = new html_table();
             $table->head = array(get_string('category','quiz'), get_string('action'));
             $table->data = $feedbackdata;
-            echo $OUTPUT->table($table);
+            echo html_writer::table($table);
         }
     }
     return true;
diff --git a/lib/simpletestcoveragelib.php b/lib/simpletestcoveragelib.php
index db9e9b5..ee19a0c 100644
--- a/lib/simpletestcoveragelib.php
+++ b/lib/simpletestcoveragelib.php
@@ -433,7 +433,7 @@ class moodle_coverage_reporter extends HtmlCoverageReporter {
                 $table = new html_table();
                 $table->align = array('right', 'left');
                 $table->tablealign = 'center';
-                $table->add_class('codecoveragetable');
+                $table->attributes['class'] = 'codecoveragetable';
                 $table->id = 'codecoveragetable_' . $type;
                 $table->rowclasses = array('label', 'value');
                 $table->data = array(
@@ -450,7 +450,7 @@ class moodle_coverage_reporter extends HtmlCoverageReporter {
                 $result .= $OUTPUT->heading($data->title, 3, 'main codecoverageheading');
                 $result .= $OUTPUT->heading('<a href="' . $url . '" onclick="javascript:window.open(' . "'" . $url . "'" . ');return false;"' .
                                    ' title="">' . get_string('codecoveragecompletereport', 'simpletest') . '</a>', 4, 'main codecoveragelink');
-                $result .= $OUTPUT->table($table);
+                $result .= html_writer::table($table);
 
                 return $OUTPUT->box($result, 'generalbox boxwidthwide boxaligncenter codecoveragebox', '', true);
             }
diff --git a/mod/assignment/index.php b/mod/assignment/index.php
index 939cd88..eb391dc 100644
--- a/mod/assignment/index.php
+++ b/mod/assignment/index.php
@@ -118,6 +118,6 @@ foreach ($modinfo->instances['assignment'] as $cm) {
 
 echo "<br />";
 
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 echo $OUTPUT->footer();
\ No newline at end of file
diff --git a/mod/chat/gui_ajax/index.php b/mod/chat/gui_ajax/index.php
index 67cd8c4..a034123 100644
--- a/mod/chat/gui_ajax/index.php
+++ b/mod/chat/gui_ajax/index.php
@@ -79,7 +79,7 @@ $table->data = array(
         '<a id="choosetheme" href="###">'.get_string('themes').' ▶</a>'
     )
 );
-echo $OUTPUT->box($OUTPUT->table($table), '', 'chat-input-area');
+echo $OUTPUT->box(html_writer::table($table), '', 'chat-input-area');
 echo $OUTPUT->box('', '', 'chat-notify');
 echo $OUTPUT->footer();
 
diff --git a/mod/chat/gui_header_js/users.php b/mod/chat/gui_header_js/users.php
index 1b36979..8dec6be 100644
--- a/mod/chat/gui_header_js/users.php
+++ b/mod/chat/gui_header_js/users.php
@@ -106,7 +106,7 @@ foreach ($chatusers as $chatuser) {
 ob_start();
 echo $OUTPUT->header();
 echo html_writer::tag('div', html_writer::tag('a', 'Refresh link', array('href'=>$refreshurl, 'id'=>'refreshLink')), array('style'=>'display:none')); //TODO: localize
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 echo $OUTPUT->footer();
 
 //
diff --git a/mod/chat/index.php b/mod/chat/index.php
index 72a8751..2a773c1 100644
--- a/mod/chat/index.php
+++ b/mod/chat/index.php
@@ -83,7 +83,7 @@ foreach ($chats as $chat) {
 
 echo '<br />';
 
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 /// Finish the page
 
diff --git a/mod/choice/index.php b/mod/choice/index.php
index a3712f0..e391759 100644
--- a/mod/choice/index.php
+++ b/mod/choice/index.php
@@ -94,7 +94,7 @@
         }
     }
     echo "<br />";
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
 
     echo $OUTPUT->footer();
 
diff --git a/mod/data/field.php b/mod/data/field.php
index bcc6a2e..c22b6d9 100755
--- a/mod/data/field.php
+++ b/mod/data/field.php
@@ -298,7 +298,7 @@ if (($mode == 'new') && (!empty($newtype)) && confirm_sesskey()) {          ///
                 );
             }
         }
-        echo $OUTPUT->table($table);
+        echo html_writer::table($table);
     }
 
 
diff --git a/mod/data/index.php b/mod/data/index.php
index 3d2b2fb..21327a3 100755
--- a/mod/data/index.php
+++ b/mod/data/index.php
@@ -141,6 +141,6 @@ foreach ($datas as $data) {
 }
 
 echo "<br />";
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 echo $OUTPUT->footer();
 
diff --git a/mod/feedback/index.php b/mod/feedback/index.php
index ddb1ce2..a5b2ae6 100644
--- a/mod/feedback/index.php
+++ b/mod/feedback/index.php
@@ -108,7 +108,7 @@ foreach ($feedbacks as $feedback) {
 
 echo "<br />";
 
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 /// Finish the page
 
diff --git a/mod/folder/index.php b/mod/folder/index.php
index b3633d5..6e5a418 100644
--- a/mod/folder/index.php
+++ b/mod/folder/index.php
@@ -54,7 +54,7 @@ if (!$folders = get_all_instances_in_course('folder', $course)) {
 }
 
 $table = new html_table();
-$table->set_classes(array('generaltable', 'mod_index'));
+$table->attributes['class'] = 'generaltable mod_index';
 
 if ($course->format == 'weeks') {
     $table->head  = array ($strweek, $strname, $strintro);
@@ -93,6 +93,6 @@ foreach ($folders as $folder) {
         format_module_intro('folder', $folder, $cm->id));
 }
 
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 echo $OUTPUT->footer();
diff --git a/mod/forum/index.php b/mod/forum/index.php
index 3581736..965a2a6 100644
--- a/mod/forum/index.php
+++ b/mod/forum/index.php
@@ -421,12 +421,12 @@ if (!isguestuser()) {
 
 if ($generalforums) {
     echo $OUTPUT->heading(get_string('generalforums', 'forum'));
-    echo $OUTPUT->table($generaltable);
+    echo html_writer::table($generaltable);
 }
 
 if ($learningforums) {
     echo $OUTPUT->heading(get_string('learningforums', 'forum'));
-    echo $OUTPUT->table($learningtable);
+    echo html_writer::table($learningtable);
 }
 
 echo $OUTPUT->footer();
diff --git a/mod/forum/renderer.php b/mod/forum/renderer.php
index 8053d18..3463504 100644
--- a/mod/forum/renderer.php
+++ b/mod/forum/renderer.php
@@ -51,22 +51,22 @@ class mod_forum_renderer extends plugin_renderer_base {
 
         $existingcell = new html_table_cell();
         $existingcell->text = $existinguc->display(true);
-        $existingcell->set_classes(array('existing'));
+        $existingcell->attributes['class'] = 'existing';
         $actioncell = new html_table_cell();
         $actioncell->text  = html_writer::start_tag('div', array());
         $actioncell->text .= html_writer::empty_tag('input', array('type'=>'submit', 'name'=>'subscribe', 'value'=>$this->page->theme->larrow.' '.get_string('add'), 'class'=>'actionbutton'));
         $actioncell->text .= html_writer::empty_tag('br', array());
         $actioncell->text .= html_writer::empty_tag('input', array('type'=>'submit', 'name'=>'unsubscribe', 'value'=>$this->page->theme->rarrow.' '.get_string('remove'), 'class'=>'actionbutton'));
         $actioncell->text .= html_writer::end_tag('div', array());
-        $actioncell->set_classes(array('actions'));
+        $actioncell->attributes['class'] = 'actions';
         $potentialcell = new html_table_cell();
         $potentialcell->text = $potentialuc->display(true);
-        $potentialcell->set_classes(array('potential'));
+        $potentialcell->attributes['class'] = 'potential';
 
         $table = new html_table();
-        $table->set_classes(array('subscribertable','boxaligncenter'));
+        $table->attributes['class'] = 'subscribertable boxaligncenter';
         $table->data = array(new html_table_row(array($existingcell, $actioncell, $potentialcell)));
-        $output .= $this->output->table($table);
+        $output .= html_writer::table($table);
 
         $output .= html_writer::end_tag('form');
         return $output;
@@ -95,7 +95,7 @@ class mod_forum_renderer extends plugin_renderer_base {
             foreach ($users as $user) {
                 $table->data[] = array($this->output->user_picture($user, array('courseid'=>$course->id)), fullname($user), $user->email);
             }
-            $output .= $this->output->table($table);
+            $output .= html_writer::table($table);
         }
         return $output;
     }
@@ -116,4 +116,4 @@ class mod_forum_renderer extends plugin_renderer_base {
     }
 
 
-}
\ No newline at end of file
+}
diff --git a/mod/glossary/index.php b/mod/glossary/index.php
index 58d69eb..a517b67 100644
--- a/mod/glossary/index.php
+++ b/mod/glossary/index.php
@@ -128,7 +128,7 @@ foreach ($glossarys as $glossary) {
 
 echo "<br />";
 
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 /// Finish the page
 
diff --git a/mod/hotpot/index.php b/mod/hotpot/index.php
index 7a37cdf..a44c5fd 100644
--- a/mod/hotpot/index.php
+++ b/mod/hotpot/index.php
@@ -399,7 +399,7 @@
 
     echo "<br />";
 
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
 
     // Finish the page
     echo $OUTPUT->footer();
diff --git a/mod/imscp/index.php b/mod/imscp/index.php
index 122fb0e..c6e59dd 100644
--- a/mod/imscp/index.php
+++ b/mod/imscp/index.php
@@ -54,7 +54,7 @@ if (!$imscps = get_all_instances_in_course('imscp', $course)) {
 }
 
 $table = new html_table();
-$table->set_classes(array('generaltable', 'mod_index'));
+$table->attributes['class'] = 'generaltable mod_index';
 
 if ($course->format == 'weeks') {
     $table->head  = array ($strweek, $strname, $strintro);
@@ -93,6 +93,6 @@ foreach ($imscps as $imscp) {
         format_module_intro('imscp', $imscp, $cm->id));
 }
 
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 echo $OUTPUT->footer();
diff --git a/mod/lesson/essay.php b/mod/lesson/essay.php
index 7090259..3c54fe7 100644
--- a/mod/lesson/essay.php
+++ b/mod/lesson/essay.php
@@ -296,7 +296,7 @@ switch ($mode) {
         // Setup table
         $table = new html_table();
         $table->head = array(get_string('name'), get_string('essays', 'lesson'), get_string('email', 'lesson'));
-        $table->set_classes(array('standardtable', 'generaltable'));
+        $table->attributes['class'] = 'standardtable generaltable';
         $table->align = array('left', 'left', 'left');
         $table->wrap = array('nowrap', 'nowrap', '');
 
@@ -356,7 +356,7 @@ switch ($mode) {
 
         $table->data[] = array(' ', ' ', $emailalllink);
 
-        echo $OUTPUT->table($table);
+        echo html_writer::table($table);
         break;
     case 'grade':
         // Grading form
diff --git a/mod/lesson/highscores.php b/mod/lesson/highscores.php
index bf87a87..cfaadf6 100644
--- a/mod/lesson/highscores.php
+++ b/mod/lesson/highscores.php
@@ -208,7 +208,7 @@ switch ($mode) {
                     break;
                 }
             }
-            echo $OUTPUT->table($table);
+            echo html_writer::table($table);
         }
 
         if (!has_capability('mod/lesson:manage', $context)) {  // teachers don't need the links
diff --git a/mod/lesson/index.php b/mod/lesson/index.php
index 452e3f5..6f87d2b 100644
--- a/mod/lesson/index.php
+++ b/mod/lesson/index.php
@@ -116,5 +116,5 @@ foreach ($lessons as $lesson) {
         $table->data[] = array ($link, $lesson->grade, $due);
     }
 }
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 echo $OUTPUT->footer();
\ No newline at end of file
diff --git a/mod/lesson/lib.php b/mod/lesson/lib.php
index e576a93..af8a0ed 100644
--- a/mod/lesson/lib.php
+++ b/mod/lesson/lib.php
@@ -235,7 +235,7 @@ function lesson_user_complete($course, $user, $mod, $lesson) {
         if ($npages) {
                 $table->data[] = array($retry + 1, $npages, $ncorrect, userdate($timeseen));
         }
-        echo $OUTPUT->table($table);
+        echo html_writer::table($table);
         echo $OUTPUT->box_end();
     }
 
diff --git a/mod/lesson/renderer.php b/mod/lesson/renderer.php
index d0cd48e..d8f28d3 100644
--- a/mod/lesson/renderer.php
+++ b/mod/lesson/renderer.php
@@ -228,7 +228,7 @@ class mod_lesson_renderer extends plugin_renderer_base {
             $pageid = $page->nextpageid;
         }
 
-        return $this->output->table($table);
+        return html_writter::table($table);
     }
 
     /**
@@ -292,7 +292,7 @@ class mod_lesson_renderer extends plugin_renderer_base {
 
             $pagetable = $page->display_answers($pagetable);
 
-            $content .= $this->output->table($pagetable);
+            $content .= html_writer::table($pagetable);
 
             if ($canedit) {
                 $content .= $this->add_page_links($lesson, $pageid);
@@ -539,16 +539,16 @@ class mod_lesson_renderer extends plugin_renderer_base {
         if ($progress != 0) {  // some browsers do not repsect the 0 width.
             $cells[0] = new html_table_cell();
             $cells[0]->style = 'width:'.$progress.'%';
-            $cells[0]->set_classes('progress_bar_completed');
+            $cells[0]->attributes['class'] = 'progress_bar_completed';
             $cells[0]->text = ' ';
         }
         $cells[] = '<div class="progress_bar_token"></div>';
 
         $table = new html_table();
-        $table->set_classes(array('progress_bar_table', 'center'));
+        $table->attributes['class'] = 'progress_bar_table';
         $table->data = array(new html_table_row($cells));
 
-        return $this->output->box($this->output->table($table), 'progress_bar');
+        return $this->output->box(html_writer::table($table), 'progress_bar');
     }
 
     /**
@@ -599,4 +599,4 @@ class mod_lesson_renderer extends plugin_renderer_base {
         $output .= $this->output->box_end();
         return $output;
     }
-}
\ No newline at end of file
+}
diff --git a/mod/lesson/report.php b/mod/lesson/report.php
index d1a6c49..f7120b6 100644
--- a/mod/lesson/report.php
+++ b/mod/lesson/report.php
@@ -221,10 +221,10 @@ if ($action == 'reportoverview') {
 
     // set up the table object
     $table->head = array(get_string('name'), get_string('attempts', 'lesson'), get_string('highscore', 'lesson'));
-    $table->align = array("center", "left", "left");
-    $table->wrap = array("nowrap", "nowrap", "nowrap");
-    $table->set_classes(array('standardtable', 'generaltable'));
-    $table->size = array("*", "70%", "*");
+    $table->align = array('center', 'left', 'left');
+    $table->wrap = array('nowrap', 'nowrap', 'nowrap');
+    $table->attributes['class'] = 'standardtable generaltable';
+    $table->size = array(null, '70%', null);
 
     // print out the $studentdata array
     // going through each student that has attempted the lesson, so, each student should have something to be displayed
@@ -299,7 +299,7 @@ if ($action == 'reportoverview') {
                <input type=\"hidden\" name=\"sesskey\" value=\"".sesskey()."\" />\n
                <input type=\"hidden\" name=\"id\" value=\"$cm->id\" />\n";
     }
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
     if (has_capability('mod/lesson:edit', $context)) {
         $checklinks  = '<a href="javascript: checkall();">'.get_string('selectall').'</a> / ';
         $checklinks .= '<a href="javascript: checknone();">'.get_string('deselectall').'</a>';
@@ -344,12 +344,12 @@ if ($action == 'reportoverview') {
     $stattable->head = array(get_string('averagescore', 'lesson'), get_string('averagetime', 'lesson'),
                             get_string('highscore', 'lesson'), get_string('lowscore', 'lesson'),
                             get_string('hightime', 'lesson'), get_string('lowtime', 'lesson'));
-    $stattable->align = array("center", "center", "center", "center", "center", "center");
-    $stattable->wrap = array("nowrap", "nowrap", "nowrap", "nowrap", "nowrap", "nowrap");
-    $stattable->set_classes(array('standardtable', 'generaltable'));
+    $stattable->align = array('center', 'center', 'center', 'center', 'center', 'center');
+    $stattable->wrap = array('nowrap', 'nowrap', 'nowrap', 'nowrap', 'nowrap', 'nowrap');
+    $stattable->attributes['class'] = 'standardtable generaltable';
     $stattable->data[] = array($avescore.'%', $avetime, $highscore.'%', $lowscore.'%', $hightime, $lowtime);
 
-    echo $OUTPUT->table($stattable);
+    echo html_writer::table($stattable);
 } else if ($action == 'reportdetail') {
     /**************************************************************************
     this action is for a student detailed view and for the general detailed view
@@ -475,8 +475,8 @@ if ($action == 'reportoverview') {
         echo $OUTPUT->heading(get_string('attempt', 'lesson', $try+1));
 
         $table->head = array();
-        $table->align = array("right", "left");
-        $table->set_classes(array('compacttable', 'generaltable'));
+        $table->align = array('right', 'left');
+        $table->attributes['class'] = 'compacttable generaltable';
 
         $params = array("lessonid"=>$lesson->id, "userid"=>$userid);
         if (!$grades = $DB->get_records_select("lesson_grades", "lessonid = :lessonid and userid = :userid", $params, "completed", "*", $try, 1)) {
@@ -509,16 +509,16 @@ if ($action == 'reportoverview') {
             $table->data[] = array(get_string('rawgrade', 'lesson').':', $gradeinfo->earned.'/'.$gradeinfo->total);
             $table->data[] = array(get_string("grade", "lesson").":", $grade."%");
         }
-        echo $OUTPUT->table($table);
+        echo html_writer::table($table);
 
         // Don't want this class for later tables
-        $table->set_classes(array());
+        $table->attributes['class'] = '';
     }
 
 
-    $table->align = array("left", "left");
-    $table->size = array("70%", "*");
-    $table->set_classes(array('compacttable', 'generaltable'));
+    $table->align = array('left', 'left');
+    $table->size = array('70%', null);
+    $table->attributes['class'] = 'compacttable generaltable';
 
     foreach ($answerpages as $page) {
         unset($table->data);
@@ -554,7 +554,7 @@ if ($action == 'reportoverview') {
         } else {
             $table->data[] = array(0, " ");
         }
-        echo $OUTPUT->table($table);
+        echo html_writer::table($table);
     }
 } else {
     print_error('unknowaction');
diff --git a/mod/page/index.php b/mod/page/index.php
index 3d4b51a..391e63b 100644
--- a/mod/page/index.php
+++ b/mod/page/index.php
@@ -54,7 +54,7 @@ if (!$pages = get_all_instances_in_course('page', $course)) {
 }
 
 $table = new html_table();
-$table->set_classes(array('generaltable', 'mod_index'));
+$table->attributes['class'] = 'generaltable mod_index';
 
 if ($course->format == 'weeks') {
     $table->head  = array ($strweek, $strname, $strintro);
@@ -94,6 +94,6 @@ foreach ($pages as $page) {
         format_module_intro('page', $page, $cm->id));
 }
 
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 echo $OUTPUT->footer();
diff --git a/mod/quiz/index.php b/mod/quiz/index.php
index 206ed01..1327404 100644
--- a/mod/quiz/index.php
+++ b/mod/quiz/index.php
@@ -166,7 +166,7 @@
 
 // Display the table.
     echo '<br />';
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
 
 // Finish the page
     echo $OUTPUT->footer();
diff --git a/mod/quiz/overrides.php b/mod/quiz/overrides.php
index b595b49..c2c081f 100644
--- a/mod/quiz/overrides.php
+++ b/mod/quiz/overrides.php
@@ -199,7 +199,7 @@ foreach ($overrides as $override) {
 
 echo html_writer::start_tag('div', array('id' => 'quizoverrides'));
 if (count($table->data)) {
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
 }
 
 echo html_writer::start_tag('div', array('class' => 'buttons'));
diff --git a/mod/quiz/report/statistics/report.php b/mod/quiz/report/statistics/report.php
index ec076da..7778ed3 100644
--- a/mod/quiz/report/statistics/report.php
+++ b/mod/quiz/report/statistics/report.php
@@ -195,7 +195,7 @@ class quiz_statistics_report extends quiz_default_report {
             $questioninfotable = new html_table();
             $questioninfotable->align = array('center', 'center');
             $questioninfotable->width = '60%';
-            $questioninfotable->add_class('generaltable titlesleft');
+            $questioninfotable->attributes['class'] = 'generaltable titlesleft';
 
             $questioninfotable->data = array();
             $questioninfotable->data[] = array(get_string('modulename', 'quiz'), $quiz->name);
@@ -206,7 +206,7 @@ class quiz_statistics_report extends quiz_default_report {
             $questionstatstable = new html_table();
             $questionstatstable->align = array('center', 'center');
             $questionstatstable->width = '60%';
-            $questionstatstable->add_class('generaltable titlesleft');
+            $questionstatstable->attributes['class'] = 'generaltable titlesleft';
 
             unset($datumfromtable['number']);
             unset($datumfromtable['icon']);
@@ -225,12 +225,12 @@ class quiz_statistics_report extends quiz_default_report {
                 $questionstatstable->data[] = array($labels[$item], $value);
             }
             echo $OUTPUT->heading(get_string('questioninformation', 'quiz_statistics'));
-            echo $OUTPUT->table($questioninfotable);
+            echo html_writer::table($questioninfotable);
 
             echo $OUTPUT->box(format_text($question->questiontext, $question->questiontextformat).$actions, 'boxaligncenter generalbox boxwidthnormal mdl-align');
 
             echo $OUTPUT->heading(get_string('questionstatistics', 'quiz_statistics'));
-            echo $OUTPUT->table($questionstatstable);
+            echo html_writer::table($questionstatstable);
 
         } else {
             $this->qtable->export_class_instance($this->table->export_class_instance());
@@ -422,7 +422,7 @@ class quiz_statistics_report extends quiz_default_report {
             $quizinformationtablehtml .= $OUTPUT->help_icon('tableexportformats', get_string('tableexportformats', 'table'));
             $quizinformationtablehtml .= '</div></form>';
         }
-        $quizinformationtablehtml .= $OUTPUT->table($quizinformationtable);
+        $quizinformationtablehtml .= html_writer::table($quizinformationtable);
         if (!$this->table->is_downloading()){
             echo $quizinformationtablehtml;
         } elseif ($everything) {
diff --git a/mod/quiz/summary.php b/mod/quiz/summary.php
index 3e39c00..1c5fbac 100644
--- a/mod/quiz/summary.php
+++ b/mod/quiz/summary.php
@@ -77,7 +77,7 @@ echo $OUTPUT->heading($title);
 
 /// Prepare the summary table header
 $table = new html_table();
-$table->add_class('generaltable quizsummaryofattempt boxaligncenter');
+$table->attributes['class'] = 'generaltable quizsummaryofattempt boxaligncenter';
 $table->head = array(get_string('question', 'quiz'), get_string('status', 'quiz'));
 $table->align = array('left', 'left');
 $table->size = array('', '');
@@ -109,7 +109,7 @@ foreach ($attemptobj->get_question_iterator() as $number => $question) {
 }
 
 /// Print the summary table.
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 /// countdown timer
 echo $attemptobj->get_timer_html();
diff --git a/mod/quiz/view.php b/mod/quiz/view.php
index 8e77cbd..dc03895 100644
--- a/mod/quiz/view.php
+++ b/mod/quiz/view.php
@@ -181,7 +181,7 @@
 
         // Prepare table header
         $table = new html_table();
-        $table->set_classes('generaltable quizattemptsummary');
+        $table->attributes['class'] = 'generaltable quizattemptsummary';
         $table->head = array();
         $table->align = array();
         $table->size = array();
@@ -298,7 +298,7 @@
                 $table->data[$attempt->attempt] = $row;
             }
         } // End of loop over attempts.
-        echo $OUTPUT->table($table);
+        echo html_writer::table($table);
     }
 
 /// Print information about the student's best score for this quiz if possible.
diff --git a/mod/resource/index.php b/mod/resource/index.php
index 121b5ef..fe937b9 100644
--- a/mod/resource/index.php
+++ b/mod/resource/index.php
@@ -54,7 +54,7 @@ if (!$resources = get_all_instances_in_course('resource', $course)) {
 }
 
 $table = new html_table();
-$table->set_classes(array('generaltable', 'mod_index'));
+$table->attributes['class'] = 'generaltable mod_index';
 
 if ($course->format == 'weeks') {
     $table->head  = array ($strweek, $strname, $strintro);
@@ -100,6 +100,6 @@ foreach ($resources as $resource) {
         format_module_intro('resource', $resource, $cm->id));
 }
 
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 echo $OUTPUT->footer();
diff --git a/mod/scorm/index.php b/mod/scorm/index.php
index 0e6fbb2..6731c66 100755
--- a/mod/scorm/index.php
+++ b/mod/scorm/index.php
@@ -96,7 +96,7 @@
 
     echo "<br />";
 
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
 
     echo $OUTPUT->footer();
 
diff --git a/mod/scorm/report.php b/mod/scorm/report.php
index 36fe6d7..4911106 100755
--- a/mod/scorm/report.php
+++ b/mod/scorm/report.php
@@ -198,7 +198,7 @@
                 if (has_capability('mod/scorm:deleteresponses',$contextmodule)) {
                     echo '<form id="attemptsform" method="post" action="'.$FULLSCRIPT.'" onsubmit="var menu = document.getElementById(\'menuaction\'); return (menu.options[menu.selectedIndex].value == \'delete\' ? \''.addslashes_js(get_string('deleteattemptcheck','quiz')).'\' : true);">';
                     echo '<input type="hidden" name="id" value="'.$id.'">';
-                    echo $OUTPUT->table($table);
+                    echo html_writer::table($table);
                     echo '<a href="javascript:select_all_in(\'DIV\',null,\'scormtablecontainer\');">'.get_string('selectall', 'quiz').'</a> / ';
                     echo '<a href="javascript:deselect_all_in(\'DIV\',null,\'scormtablecontainer\');">'.get_string('selectnone', 'quiz').'</a> ';
                     echo '&nbsp;&nbsp;';
@@ -210,7 +210,7 @@
                     echo '<input type="submit" value="'.get_string('go').'" /></div></noscript>';
                     echo '</form>';
                 } else {
-                    echo $OUTPUT->table($table);
+                    echo html_writer::table($table);
                 }
                 echo '</div>';
             } else {
@@ -272,7 +272,7 @@
                             }
                             $table->data[] = $row;
                         }
-                        echo $OUTPUT->table($table);
+                        echo html_writer::table($table);
                     }
                 }
             } else {
@@ -347,7 +347,7 @@
             }
             if ($existelements) {
                 echo '<h3>'.get_string('general','scorm').'</h3>';
-                echo $OUTPUT->table($table);
+                echo html_writer::table($table);
             }
 
             // Print Interactions data
@@ -389,7 +389,7 @@
             }
             if ($existinteraction) {
                 echo '<h3>'.get_string('interactions','scorm').'</h3>';
-                echo $OUTPUT->table($table);
+                echo html_writer::table($table);
             }
 
             // Print Objectives data
@@ -433,7 +433,7 @@
             }
             if ($existobjective) {
                 echo '<h3>'.get_string('objectives','scorm').'</h3>';
-                echo $OUTPUT->table($table);
+                echo html_writer::table($table);
             }
             $table = new html_table();
             $table->head = array(get_string('element','scorm'), get_string('value','scorm'));
@@ -461,7 +461,7 @@
             }
             if ($existelements) {
                 echo '<h3>'.get_string('othertracks','scorm').'</h3>';
-                echo $OUTPUT->table($table);
+                echo html_writer::table($table);
             }
             echo $OUTPUT->box_end();
         } else {
diff --git a/mod/survey/index.php b/mod/survey/index.php
index e601fed..8083a66 100644
--- a/mod/survey/index.php
+++ b/mod/survey/index.php
@@ -80,7 +80,7 @@
     }
 
     echo "<br />";
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
     echo $OUTPUT->footer();
 
 
diff --git a/mod/survey/lib.php b/mod/survey/lib.php
index 36ae54e..3675006 100644
--- a/mod/survey/lib.php
+++ b/mod/survey/lib.php
@@ -191,7 +191,7 @@ function survey_user_complete($course, $user, $mod, $survey) {
                 }
                 $table->data[] = array("<b>$questiontext</b>", $answertext);
             }
-            echo $OUTPUT->table($table);
+            echo html_writer::table($table);
 
         } else {
 
@@ -475,7 +475,7 @@ function survey_print_all_responses($cmid, $results, $courseid) {
                userdate($a->time));
     }
 
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
 }
 
 /**
diff --git a/mod/survey/report.php b/mod/survey/report.php
index 18078fe..6cf6e5f 100644
--- a/mod/survey/report.php
+++ b/mod/survey/report.php
@@ -302,7 +302,7 @@
 
                     $table->data[] = array($contents);
 
-                    echo $OUTPUT->table($table);
+                    echo html_writer::table($table);
 
                     echo $OUTPUT->spacer(array('height'=>30)); // should be done with CSS instead
                 }
@@ -354,7 +354,7 @@
             }
         }
 
-        echo $OUTPUT->table($table);
+        echo html_writer::table($table);
 
         break;
 
@@ -440,7 +440,7 @@
                      $table->head = array(get_string($question->text, "survey"));
                      $table->align = array ("left");
                      $table->data[] = array(s($answer->answer1)); // no html here, just plain text
-                     echo $OUTPUT->table($table);
+                     echo html_writer::table($table);
                      echo $OUTPUT->spacer(30);
                  }
              }
diff --git a/mod/survey/view.php b/mod/survey/view.php
index e70bb30..9fb517a 100644
--- a/mod/survey/view.php
+++ b/mod/survey/view.php
@@ -115,7 +115,7 @@
                         $table->head = array(get_string($question->text, "survey"));
                         $table->align = array ("left");
                         $table->data[] = array(s($answer->answer1));//no html here, just plain text
-                        echo $OUTPUT->table($table);
+                        echo html_writer::table($table);
                         echo $OUTPUT->spacer(clone($spacer)) . '<br />';
                     }
                 }
diff --git a/mod/url/index.php b/mod/url/index.php
index 7f054f2..ed1774e 100644
--- a/mod/url/index.php
+++ b/mod/url/index.php
@@ -54,7 +54,7 @@ if (!$urls = get_all_instances_in_course('url', $course)) {
 }
 
 $table = new html_table();
-$table->set_classes(array('generaltable', 'mod_index'));
+$table->attributes['class'] = 'generaltable mod_index';
 
 if ($course->format == 'weeks') {
     $table->head  = array ($strweek, $strname, $strintro);
@@ -100,6 +100,6 @@ foreach ($urls as $url) {
         format_module_intro('url', $url, $cm->id));
 }
 
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 echo $OUTPUT->footer();
diff --git a/mod/wiki/index.php b/mod/wiki/index.php
index 222db90..c5fdf3c 100644
--- a/mod/wiki/index.php
+++ b/mod/wiki/index.php
@@ -101,7 +101,7 @@
 
     echo "<br />";
 
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
 
 /// Finish the page
 
diff --git a/mod/wiki/removepages.html b/mod/wiki/removepages.html
index 676509d..c76125a 100644
--- a/mod/wiki/removepages.html
+++ b/mod/wiki/removepages.html
@@ -14,7 +14,7 @@
 <input type="hidden" name="wikipage" value="<?php print $wikipage?>" />
 <?php
   $remove_table=wiki_admin_remove_list($form->listall);
-  echo $OUTPUT->table($remove_table);
+  echo html_writer::table($remove_table);
 ?>
 <div class="boxaligncenter">
 <?php
diff --git a/mod/wiki/setpageflags.html b/mod/wiki/setpageflags.html
index d0626c1..f26502a 100644
--- a/mod/wiki/setpageflags.html
+++ b/mod/wiki/setpageflags.html
@@ -11,7 +11,7 @@
 <input type="hidden" name="wikipage" value="<?php print $wikipage?>" />
 <?php
   $pageflags_table=wiki_admin_setpageflags_list($pageflagstatus);
-  echo $OUTPUT->table($pageflags_table);
+  echo html_writer::table($pageflags_table);
 ?>
 <br />
 <div class="boxaligncenter">
diff --git a/mod/wiki/strippages.html b/mod/wiki/strippages.html
index ba3e450..483f580 100644
--- a/mod/wiki/strippages.html
+++ b/mod/wiki/strippages.html
@@ -11,7 +11,7 @@
 <input type="hidden" name="wikipage" value="<?php print $wikipage?>" />
 <?php
   $strip_table=wiki_admin_strip_list($form->pagestostrip, $form->version, $err);
-  echo $OUTPUT->table($strip_table);
+  echo html_writer::table($strip_table);
 ?>
 <div class="boxaligncenter">
 <?php
diff --git a/mod/workshop/allocation/manual/renderer.php b/mod/workshop/allocation/manual/renderer.php
index a2da4d2..ab04d19 100644
--- a/mod/workshop/allocation/manual/renderer.php
+++ b/mod/workshop/allocation/manual/renderer.php
@@ -54,7 +54,7 @@ class workshopallocation_manual_renderer extends plugin_renderer_base  {
         $reviewers  =  array_map('fullname', $reviewers);
 
         $table              = new html_table();
-        $table->set_classes('allocations');
+        $table->attributes['class'] = 'allocations';
         $table->head        = array(get_string('participantreviewedby', 'workshop'),
                                     get_string('participant', 'workshop'),
                                     get_string('participantrevierof', 'workshop'));
@@ -77,7 +77,7 @@ class workshopallocation_manual_renderer extends plugin_renderer_base  {
             $table->data[] = $row;
         }
 
-        return $this->output->container($this->output->table($table), 'manual-allocator');
+        return $this->output->container(html_writer::table($table), 'manual-allocator');
     }
 
     /**
diff --git a/mod/workshop/renderer.php b/mod/workshop/renderer.php
index 905d30d..e09524d 100644
--- a/mod/workshop/renderer.php
+++ b/mod/workshop/renderer.php
@@ -362,11 +362,11 @@ class mod_workshop_renderer extends plugin_renderer_base {
             throw new coding_exception('you must provide the prepared user plan to be rendered');
         }
         $table = new html_table();
-        $table->set_classes('userplan');
+        $table->attributes['class'] = 'userplan';
         $table->head = array();
         $table->colclasses = array();
         $row = new html_table_row();
-        $row->set_classes('phasetasks');
+        $row->attributes['class'] = 'phasetasks';
         foreach ($plan as $phasecode => $phase) {
             $title = html_writer::tag('span', $phase->title);
             $actions = '';
@@ -394,7 +394,7 @@ class mod_workshop_renderer extends plugin_renderer_base {
         }
         $table->data = array($row);
 
-        return $this->output->table($table);
+        return html_writer::table($table);
     }
 
     /**
@@ -450,7 +450,7 @@ class mod_workshop_renderer extends plugin_renderer_base {
         }
 
         $table = new html_table();
-        $table->set_classes('grading-report');
+        $table->attributes['class'] = 'grading-report';
 
         $sortbyfirstname = $this->sortable_heading(get_string('firstname'), 'firstname', $options->sortby, $options->sorthow);
         $sortbylastname = $this->sortable_heading(get_string('lastname'), 'lastname', $options->sortby, $options->sorthow);
@@ -509,7 +509,7 @@ class mod_workshop_renderer extends plugin_renderer_base {
                     $cell = new html_table_cell();
                     $cell->text = $this->grading_report_participant($participant, $userinfo);
                     $cell->rowspan = $numoftrs;
-                    $cell->add_class('participant');
+                    $cell->attributes['class'] = 'participant';
                     $row->cells[] = $cell;
                 }
                 // column #2 - submission - spans over all rows
@@ -517,7 +517,7 @@ class mod_workshop_renderer extends plugin_renderer_base {
                     $cell = new html_table_cell();
                     $cell->text = $this->grading_report_submission($participant);
                     $cell->rowspan = $numoftrs;
-                    $cell->add_class('submission');
+                    $cell->attributes['class'] = 'submission';
                     $row->cells[] = $cell;
                 }
                 // column #3 - received grades
@@ -528,11 +528,11 @@ class mod_workshop_renderer extends plugin_renderer_base {
                     $cell->text = $this->grading_report_assessment($assessment, $options->showreviewernames, $userinfo,
                             get_string('gradereceivedfrom', 'workshop'));
                     $cell->rowspan = $spanreceived;
-                    $cell->add_class('receivedgrade');
+                    $cell->attributes['class'] = 'receivedgrade';
                     if (is_null($assessment) or is_null($assessment->grade)) {
-                        $cell->add_class('null');
+                        $cell->attributes['class'] .= ' null';
                     } else {
-                        $cell->add_class('notnull');
+                        $cell->attributes['class'] .= ' notnull';
                     }
                     $row->cells[] = $cell;
                 }
@@ -541,7 +541,7 @@ class mod_workshop_renderer extends plugin_renderer_base {
                     $cell = new html_table_cell();
                     $cell->text = $this->grading_report_grade($participant->submissiongrade, $participant->submissiongradeover);
                     $cell->rowspan = $numoftrs;
-                    $cell->add_class('submissiongrade');
+                    $cell->attributes['class'] = 'submissiongrade';
                     $row->cells[] = $cell;
                 }
                 // column #5 - given grades
@@ -552,11 +552,11 @@ class mod_workshop_renderer extends plugin_renderer_base {
                     $cell->text = $this->grading_report_assessment($assessment, $options->showauthornames, $userinfo,
                             get_string('gradegivento', 'workshop'));
                     $cell->rowspan = $spangiven;
-                    $cell->add_class('givengrade');
+                    $cell->attributes['class'] = 'givengrade';
                     if (is_null($assessment) or is_null($assessment->grade)) {
-                        $cell->add_class('null');
+                        $cell->attributes['class'] .= ' null';
                     } else {
-                        $cell->add_class('notnull');
+                        $cell->attributes['class'] .= ' notnull';
                     }
                     $row->cells[] = $cell;
                 }
@@ -565,7 +565,7 @@ class mod_workshop_renderer extends plugin_renderer_base {
                     $cell = new html_table_cell();
                     $cell->text = $this->grading_report_grade($participant->gradinggrade);
                     $cell->rowspan = $numoftrs;
-                    $cell->add_class('gradinggrade');
+                    $cell->attributes['class'] = 'gradinggrade';
                     $row->cells[] = $cell;
                 }
 
@@ -573,7 +573,7 @@ class mod_workshop_renderer extends plugin_renderer_base {
             }
         }
 
-        return $this->output->table($table);
+        return html_writer::table($table);
     }
 
     /**
diff --git a/question/type/questiontype.php b/question/type/questiontype.php
index e7ccc4d..796f4b6 100644
--- a/question/type/questiontype.php
+++ b/question/type/questiontype.php
@@ -1144,7 +1144,7 @@ class default_questiontype {
             }
             $table->data[] = $data;
         }
-        return $OUTPUT->table($table);
+        return html_writer::table($table);
     }
 
     /**
diff --git a/repository/lib.php b/repository/lib.php
index e60f6a0..2add7b8 100644
--- a/repository/lib.php
+++ b/repository/lib.php
@@ -1083,7 +1083,7 @@ abstract class repository {
                 $alreadyplugins[] = $i->name;
             }
         }
-        $output .= $OUTPUT->table($table);
+        $output .= html_writer::table($table);
         $instancehtml = '<div>';
         $addable = 0;
 
diff --git a/search/stats.php b/search/stats.php
index 3942fa8..2700b59 100644
--- a/search/stats.php
+++ b/search/stats.php
@@ -105,7 +105,7 @@ require_once($CFG->dirroot.'/search/lib.php');
             }
         }
 
-        echo $OUTPUT->table($admin_table);
+        echo html_writer::table($admin_table);
         echo $OUTPUT->spacer(array('height'=>20, 'br'=>true)); // should be done with CSS instead
         echo $OUTPUT->heading($solutionsstr);
 
@@ -120,7 +120,7 @@ require_once($CFG->dirroot.'/search/lib.php');
         $admin_table->data[] = array($runindexerteststr, '<a href="tests/index.php" target="_blank">tests/index.php</a>');
         $admin_table->data[] = array($runindexerstr, '<a href="indexersplash.php" target="_blank">indexersplash.php</a>');
 
-        echo $OUTPUT->table($admin_table);
+        echo html_writer::table($admin_table);
         echo $OUTPUT->spacer($spacer) . '<br />';
     }
 
@@ -161,7 +161,7 @@ require_once($CFG->dirroot.'/search/lib.php');
     }
 
     echo $OUTPUT->heading($databasestatestr);
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
 
     echo $OUTPUT->box_end();
     echo $OUTPUT->box_end();
diff --git a/theme/index.php b/theme/index.php
index 3a00b4a..f6f75f0 100644
--- a/theme/index.php
+++ b/theme/index.php
@@ -106,7 +106,7 @@ foreach ($themes as $themename => $themedir) {
     }
 }
 
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 
 echo $OUTPUT->footer();
 
diff --git a/user/addnote.php b/user/addnote.php
index 9ec1f2a..7e4f782 100644
--- a/user/addnote.php
+++ b/user/addnote.php
@@ -116,7 +116,7 @@ foreach ($users as $k => $v) {
         $checkbox
     );
 }
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 echo '<div style="width:100%;text-align:center;"><input type="submit" value="' . get_string('savechanges'). '" /></div></form>';
 echo $OUTPUT->footer();
 
diff --git a/user/extendenrol.php b/user/extendenrol.php
index c08b62e..0054317 100644
--- a/user/extendenrol.php
+++ b/user/extendenrol.php
@@ -181,7 +181,7 @@ foreach ($_POST as $k => $v) {
                 $checkbox2);
     }
 }
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 echo "\n<div style=\"width:100%;text-align:center;\"><input type=\"submit\" value=\"".get_string('savechanges')."\" /></div>\n</form>\n";
 
 echo $OUTPUT->footer();
diff --git a/user/groupextendenrol.php b/user/groupextendenrol.php
index fc30f1e..4438270 100755
--- a/user/groupextendenrol.php
+++ b/user/groupextendenrol.php
@@ -171,7 +171,7 @@ foreach ($_POST as $k => $v) {
         );
     }
 }
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 echo '<div style="width:100%;text-align:center;"><strong>';
 echo get_string('extendperiod') . ' ';
 echo html_writer::select($periodmenu, 'extendperiod');
diff --git a/user/index.php b/user/index.php
index a583547..2da4df0 100644
--- a/user/index.php
+++ b/user/index.php
@@ -214,7 +214,7 @@
 
 /// Print settings and things in a table across the top
     $controlstable = new html_table();
-    $controlstable->add_class('controls');
+    $controlstable->attributes['class'] = 'controls';
     $controlstable->cellspacing = 0;
     $controlstable->data[] = new html_table_row();
 
@@ -318,23 +318,23 @@
     $select = new single_select($baseurl, 'mode', $formatmenu, $mode, null, 'formatmenu');
     $select->set_label(get_string('userlist'));
     $userlistcell = new html_table_cell();
-    $userlistcell->add_class('right');
+    $userlistcell->attributes['class'] = 'right';
     $userlistcell->text = $OUTPUT->render($select);
     $controlstable->data[0]->cells[] = $userlistcell;
 
-    echo $OUTPUT->table($controlstable);
+    echo html_writer::table($controlstable);
 
     if ($currentgroup and (!$isseparategroups or has_capability('moodle/site:accessallgroups', $context))) {    /// Display info about the group
         if ($group = groups_get_group($currentgroup)) {
             if (!empty($group->description) or (!empty($group->picture) and empty($group->hidepicture))) {
                 $groupinfotable = new html_table();
-                $groupinfotable->add_class('groupinfobox');
+                $groupinfotable->attributes['class'] = 'groupinfobox';
                 $picturecell = new html_table_cell();
-                $picturecell->add_classes(array('left', 'side', 'picture'));
+                $picturecell->attributes['class'] = 'left side picture';
                 $picturecell->text = print_group_picture($group, $course->id, true, false, false);
 
                 $contentcell = new html_table_cell();
-                $contentcell->add_class('content');
+                $contentcell->attributes['class'] = 'content';
                 $contentcell->text = print_group_picture($group, $course->id, true, false, false);
 
                 $contentheading = $group->name;
@@ -349,7 +349,7 @@
                 }
                 $contentcell->text = $OUTPUT->heading($contentheading, 3) . format_text($group->description, $group->descriptionformat);
                 $groupinfotable->data[] = new html_table_row(array($picturecell, $contentcell));
-                echo $OUTPUT->table($groupinfotable);
+                echo html_writer::table($groupinfotable);
             }
         }
     }
@@ -751,15 +751,15 @@
                         $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
                     }
                     $table = new html_table();
-                    $table->add_class('userinfobox');
+                    $table->attributes['class'] = 'userinfobox';
 
                     $row = new html_table_row();
                     $row->cells[0] = new html_table_cell();
-                    $row->cells[0]->add_class('left side');
+                    $row->cells[0]->attributes['class'] = 'left side';
 
                     $row->cells[0]->text = $OUTPUT->user_picture($user, array('courseid'=>$course->id));
                     $row->cells[1] = new html_table_cell();
-                    $row->cells[1]->add_class('content');
+                    $row->cells[1]->attributes['class'] = 'content';
 
                     $row->cells[1]->text = $OUTPUT->container(fullname($user, has_capability('moodle/site:viewfullnames', $context)), 'username');
                     $row->cells[1]->text .= $OUTPUT->container_start('info');
@@ -797,7 +797,7 @@
                     $row->cells[1]->text .= $OUTPUT->container_end();
 
                     $row->cells[2] = new html_table_cell();
-                    $row->cells[2]->add_class('links');
+                    $row->cells[2]->attributes['class'] = 'links';
                     $row->cells[2]->text = '';
 
                     $links = array();
@@ -831,7 +831,7 @@
                         $row->cells[2]->text .= '<br /><input type="checkbox" name="user'.$user->id.'" /> ';
                     }
                     $table->data = array($row);
-                    echo $OUTPUT->table($table);
+                    echo html_writer::table($table);
                 }
 
             } else {
diff --git a/user/managetoken.php b/user/managetoken.php
index ccc9365..b900ce4 100644
--- a/user/managetoken.php
+++ b/user/managetoken.php
@@ -175,7 +175,7 @@ switch ($action) {
 
                 $table->data[] = array($token->token, $token->name, $validuntil, $creatoratag, $reset);
             }
-            $return .= $OUTPUT->table($table);
+            $return .= html_writer::table($table);
           
         } else {
             $return .= get_string('notoken', 'webservice');
diff --git a/user/portfolio.php b/user/portfolio.php
index 708ec30..dac0699 100644
--- a/user/portfolio.php
+++ b/user/portfolio.php
@@ -119,7 +119,7 @@ if ($display) {
         );
     }
 
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
     echo $OUTPUT->box_end();
 }
 echo $OUTPUT->footer();
diff --git a/user/portfoliologs.php b/user/portfoliologs.php
index 3c3017e..76b15c4 100644
--- a/user/portfoliologs.php
+++ b/user/portfoliologs.php
@@ -101,7 +101,7 @@ if (count($queued) > 0) {
         unset($e); // this could potentially be quite big, so free it.
     }
     echo $OUTPUT->heading(get_string('queuesummary', 'portfolio'));
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
     $somethingprinted = true;
 }
 // paging - get total count separately
@@ -139,7 +139,7 @@ if ($logcount > 0) {
     echo $OUTPUT->heading(get_string('logsummary', 'portfolio'));
     $pagingbar = new paging_bar($logcount, $page, $perpage, $CFG->wwwroot . '/user/portfoliologs.php?');
     echo $OUTPUT->render($pagingbar);
-    echo $OUTPUT->table($table);
+    echo html_writer::table($table);
     echo $OUTPUT->render($pagingbar);
     $somethingprinted = true;
 }
diff --git a/user/profile/index.php b/user/profile/index.php
index 5da6d54..93ac676 100644
--- a/user/profile/index.php
+++ b/user/profile/index.php
@@ -120,7 +120,7 @@ foreach ($categories as $category) {
     $table->head  = array(get_string('profilefield', 'admin'), get_string('edit'));
     $table->align = array('left', 'right');
     $table->width = '95%';
-    $table->add_class ('generaltable profilefield');
+    $table->attributes['class'] = 'generaltable profilefield';
     $table->data = array();
 
     if ($fields = $DB->get_records('user_info_field', array('categoryid'=>$category->id), 'sortorder ASC')) {
@@ -131,7 +131,7 @@ foreach ($categories as $category) {
 
     echo $OUTPUT->heading(format_string($category->name) .' '.profile_category_icons($category));
     if (count($table->data)) {
-        echo $OUTPUT->table($table);
+        echo html_writer::table($table);
     } else {
         echo $OUTPUT->notification($strnofields);
     }
diff --git a/user/repository.php b/user/repository.php
index 8bd205e..2046d14 100644
--- a/user/repository.php
+++ b/user/repository.php
@@ -83,7 +83,7 @@ foreach ($instances as $i) {
             .get_string('settings', 'repository').'</a>' : '');
 }
 
-echo $OUTPUT->table($table);
+echo html_writer::table($table);
 echo $OUTPUT->footer();
 
 
