<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Leblangi</id>
	<title>MoodleDocs - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Leblangi"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Leblangi"/>
	<updated>2026-04-17T03:04:43Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=CodeSniffer&amp;diff=42870</id>
		<title>CodeSniffer</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=CodeSniffer&amp;diff=42870"/>
		<updated>2013-11-07T16:26:44Z</updated>

		<summary type="html">&lt;p&gt;Leblangi: /* Linux set up */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
===Scope===&lt;br /&gt;
This document describes the CodeSniffing/Code checker tools their purpose and usage.&lt;br /&gt;
&lt;br /&gt;
===Function===&lt;br /&gt;
The function of the CodeSniffer tool is to analyse PHP5 (only) code, apply a set of rules that match the [[Coding_style | Moodle Coding Style]], and output a report showing which parts of the code do not conform to this style.&lt;br /&gt;
&lt;br /&gt;
==Usage==&lt;br /&gt;
&lt;br /&gt;
===Using codechecker===&lt;br /&gt;
&lt;br /&gt;
codechecker is a local plugin that creates a web based interface for checking the syntax of a given file. It can be found at&lt;br /&gt;
https://github.com/moodlehq/moodle-local_codechecker&lt;br /&gt;
&lt;br /&gt;
Once installed a new codechecker option will appear in site administration\development page.&lt;br /&gt;
&lt;br /&gt;
This page allows for the code in a specified directory to be checked, e.g. if you wanted to check the code for the shortanswer question type you would enter&lt;br /&gt;
/question/type/shortanswer&lt;br /&gt;
&lt;br /&gt;
You would then be presented with a list of the count of files processed and any warnings or errors.&lt;br /&gt;
&lt;br /&gt;
===Installing codechecker===&lt;br /&gt;
&lt;br /&gt;
To install using git, type this command in the root of your Moodle install&lt;br /&gt;
    git clone git://github.com/moodlehq/moodle-local_codechecker.git local/codechecker&lt;br /&gt;
&lt;br /&gt;
Then edit .gitignore in your development folder eg: &lt;br /&gt;
    gedit /var/www/moodle/.gitignore&lt;br /&gt;
&lt;br /&gt;
And add /local/codechecker/ - including the slash at the end&lt;br /&gt;
&lt;br /&gt;
Alternatively, download the zip from &lt;br /&gt;
&lt;br /&gt;
https://github.com/moodlehq/moodle-local_codechecker/zipball/master&lt;br /&gt;
&lt;br /&gt;
unzip it into the local folder, and then rename the new folder to codechecker.&lt;br /&gt;
&lt;br /&gt;
===Codechecker output===&lt;br /&gt;
&lt;br /&gt;
The output is similar to the following &lt;br /&gt;
&lt;br /&gt;
Files found: 21&lt;br /&gt;
&lt;br /&gt;
question\type\calculated\backup\moodle1\lib.php - 1 error(s) and 10 warning(s)&lt;br /&gt;
then a list of all files checked with a count of errors and warnings..followed by a summary&lt;br /&gt;
Total: 31 error(s) and 262 warning(s)&lt;br /&gt;
&lt;br /&gt;
Then a list describing the exact issue in each file&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;question\type\calculated\backup\moodle1\lib.php&lt;br /&gt;
&lt;br /&gt;
2: The opening &amp;lt;?php tag must be followed by exactly one newline.&lt;br /&gt;
········//·convert·and·write·the·answers·first&lt;br /&gt;
50: Inline comments must start with a capital letter, digit or 3-dots sequence&lt;br /&gt;
etc etc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;You can then edit the files to attempt to remove each issue.&lt;br /&gt;
&lt;br /&gt;
===IDE plugin alternatives===&lt;br /&gt;
&lt;br /&gt;
Using the web based interface means switching between the browser and the editing environment. You may find it easier to use a plugin that allows you to check your code against the standards as you go along. &lt;br /&gt;
&lt;br /&gt;
For Eclipse users&lt;br /&gt;
http://www.phpsrc.org/&lt;br /&gt;
&lt;br /&gt;
For Netbeans users&lt;br /&gt;
&lt;br /&gt;
Make sure you have the PEAR php Codesniffer code installed, you can find instructions at &lt;br /&gt;
http://pear.php.net/package/PHP_CodeSniffer/download/All&lt;br /&gt;
&lt;br /&gt;
Then install the netbeans plugin which can be found at &lt;br /&gt;
&lt;br /&gt;
https://github.com/beberlei/netbeans-php-enhancements/downloads&lt;br /&gt;
&lt;br /&gt;
Once installed you can check it within Netbeans by going to &lt;br /&gt;
Tools/Options/PHP and click on the codesniffer tab.&lt;br /&gt;
&lt;br /&gt;
====Windows set up====&lt;br /&gt;
&lt;br /&gt;
There is an option for the codesniffer script. On my windows xampp install this needs to point to &lt;br /&gt;
&lt;br /&gt;
C:\xampp\php\phpcs.bat&lt;br /&gt;
&lt;br /&gt;
Underneath this should be a list of some of the coding standards available, but by default this will not include Moodle. To install the moodle standard, copy the&amp;quot;moodle&amp;quot; and &amp;quot;phpcompatibility&amp;quot; folders from local\codechecker into your standards directory which for me was under&lt;br /&gt;
&lt;br /&gt;
php\PEAR\PHP\CodeSniffer\Standards&lt;br /&gt;
&lt;br /&gt;
[[Image:codesniffer.jpg]]&lt;br /&gt;
&lt;br /&gt;
Now when you restart your Netbeans you should see a new moodle coding standard. Right clicking on a file name should present you with a new option of &amp;quot;Show Code Standard Violations&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
====Linux set up====&lt;br /&gt;
&lt;br /&gt;
After installing codesniffer and codechecker, copy the moodle and phpcompatibility standard folders from (assuming you have the code in /local/codechecker)&lt;br /&gt;
&lt;br /&gt;
/var/www/moodle/local/codechecker/&lt;br /&gt;
&lt;br /&gt;
to &lt;br /&gt;
&lt;br /&gt;
/usr/share/pear/PHP/CodeSniffer/Standards/&lt;br /&gt;
&lt;br /&gt;
There is an option to set the default standard in a configuration file:&lt;br /&gt;
&lt;br /&gt;
    phpcs --config-set default_standard moodle&lt;br /&gt;
&lt;br /&gt;
Then restart Netbeans and it should now work. You can also switch between coding standards.&lt;br /&gt;
&lt;br /&gt;
===Simple example===&lt;br /&gt;
The script is located in lib/pear/PHP and is called runsniffer. To check the syntax of a given file (e.g. index.php), run:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
lib/pear/PHP/runsniffer index.php&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will get a report that looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  --------------------------------------------------------------------------------&lt;br /&gt;
  FOUND 139 ERROR(S) AND 24 WARNING(S) AFFECTING 130 LINE(S)&lt;br /&gt;
  --------------------------------------------------------------------------------&lt;br /&gt;
     1 | WARNING | $Id$ tag is no longer required, please remove.&lt;br /&gt;
    28 | ERROR   | line indented incorrectly; expected 0 spaces, found 4&lt;br /&gt;
    50 | ERROR   | line indented incorrectly; expected 0 spaces, found 4&lt;br /&gt;
    50 | ERROR   | A cast statement must be followed by a single space&lt;br /&gt;
    55 | ERROR   | line indented incorrectly; expected 0 spaces, found 4&lt;br /&gt;
  ....&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first column shows the line at which the ERROR or WARNING was found. The CodeSniffer uses a set of rules which are still being defined, so that what is currently defined as ERROR or WARNING is likely to change in the near future. &lt;br /&gt;
&lt;br /&gt;
You should fix all ERRORs, but may safely ignore the WARNINGs. Fixing warnings will help your code be even more readable and consistent with other code that follow this standard.&lt;br /&gt;
&lt;br /&gt;
===Advanced Usage===&lt;br /&gt;
====Ignoring warnings====&lt;br /&gt;
You can run the CodeSniffer with the -n flag to ignore warnings:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
lib/pear/PHP/runsniffer -n index.php&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Resulting output:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  --------------------------------------------------------------------------------&lt;br /&gt;
  FOUND 139 ERROR(S) AFFECTING 125 LINE(S)&lt;br /&gt;
  --------------------------------------------------------------------------------&lt;br /&gt;
    28 | ERROR | line indented incorrectly; expected 0 spaces, found 4&lt;br /&gt;
    50 | ERROR | line indented incorrectly; expected 0 spaces, found 4&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Recursive analysis====&lt;br /&gt;
If you give the name of a folder instead of a file, it will search, analyse and report on all PHP files found in this folder and all its subfolders. This will produce a full report for each PHP file. Since this is likely to be too much information, you may want to print only a summary report, by using the following syntax (search the files/ folder as an example):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
lib/pear/PHP/runsniffer --report=summary files&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Report:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  PHP CODE SNIFFER REPORT SUMMARY&lt;br /&gt;
  --------------------------------------------------------------------------------&lt;br /&gt;
  FILE                                                            ERRORS  WARNINGS&lt;br /&gt;
  --------------------------------------------------------------------------------&lt;br /&gt;
  /web/htdocs/moodle_blog2/files/index.php                        11      58&lt;br /&gt;
  /web/htdocs/moodle_blog2/files/draftfiles.php                   6       22&lt;br /&gt;
  --------------------------------------------------------------------------------&lt;br /&gt;
  A TOTAL OF 17 ERROR(S) AND 80 WARNING(S) WERE FOUND IN 2 FILE(S)&lt;br /&gt;
  --------------------------------------------------------------------------------&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also use the -n flag to ignore warnings.&lt;br /&gt;
&lt;br /&gt;
====Several files in one folder====&lt;br /&gt;
If you want to search all files under a folder, but not recurse through the subfolders, you can use the -l flag (local files only):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
lib/pear/PHP/runsniffer --report=summary -l grade&lt;br /&gt;
&lt;br /&gt;
  PHP CODE SNIFFER REPORT SUMMARY&lt;br /&gt;
  --------------------------------------------------------------------------------&lt;br /&gt;
  FILE                                                            ERRORS  WARNINGS&lt;br /&gt;
  --------------------------------------------------------------------------------&lt;br /&gt;
  /web/htdocs/moodle_blog2/grade/index.php                        0       2&lt;br /&gt;
  /web/htdocs/moodle_blog2/grade/lib.php                          6       210&lt;br /&gt;
  /web/htdocs/moodle_blog2/grade/querylib.php                     5       39&lt;br /&gt;
  --------------------------------------------------------------------------------&lt;br /&gt;
  A TOTAL OF 11 ERROR(S) AND 251 WARNING(S) WERE FOUND IN 3 FILE(S)&lt;br /&gt;
  --------------------------------------------------------------------------------&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can pass as many files and folders to the script as you want, the analysis and flags will apply to all of them.&lt;br /&gt;
&lt;br /&gt;
===Special rules===&lt;br /&gt;
When recursing through folders, the CodeSniffer script looks for a file called thirdpartylibs.xml. Currently there is only one, found under lib/. It lists directories and files which are meant to stay &#039;as-is&#039; in Moodle, in order to ensure minimum hassle when upgrading these libraries. You can use this file as a template to create your own list of exceptions.&lt;br /&gt;
&lt;br /&gt;
===Other report formats===&lt;br /&gt;
CodeSniffer can export its reports in the following formats:&lt;br /&gt;
#full: default, shown first above&lt;br /&gt;
#summary: also shown above&lt;br /&gt;
#xml: Simple XML format&lt;br /&gt;
#csv: Comma-separated list&lt;br /&gt;
#checkstyle: XML format intended for use with CruiseControl&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
#[[Coding]]&lt;br /&gt;
#[[Coding style]]&lt;/div&gt;</summary>
		<author><name>Leblangi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Admin_settings&amp;diff=40873</id>
		<title>Admin settings</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Admin_settings&amp;diff=40873"/>
		<updated>2013-06-11T13:42:58Z</updated>

		<summary type="html">&lt;p&gt;Leblangi: /* See also */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Moodle&#039;s configuration is stored in a mixture of the config, config_plugins, and a few other tables. These settings are edited through the administration screens, which can be accessed by going to the .../admin/index.php URL on your moodle site, or using the Administration block that appears to administrators of the Moodle front page. This page explains how the code for displaying and editing of these settings works.&lt;br /&gt;
&lt;br /&gt;
==Where to find the code==&lt;br /&gt;
&lt;br /&gt;
This is explained further below, but in summary:&lt;br /&gt;
* The library code is all in lib/adminlib.php.&lt;br /&gt;
* The definition of the all the parts of the admin tree is in admin/settings/* some of which call out to plugins to see if they have settings they want to add.&lt;br /&gt;
* The editing and saving of settings is managed by admin/settings.php, admin/upgradesettings.php, and admin/search.php.&lt;br /&gt;
* The administration blocks that appear on the front page and on most of the admin screens is in blocks/admin_tree and blocks/admin_bookmarks.&lt;br /&gt;
&lt;br /&gt;
In my experience most of this code is pretty easy to understand and work with, so here I will focus on giving an overview. For details, see the code.&lt;br /&gt;
&lt;br /&gt;
==The building blocks==&lt;br /&gt;
&lt;br /&gt;
All the settings are arranged into a tree structure. This tree structure is represented in memory as a tree of PHP objects.&lt;br /&gt;
&lt;br /&gt;
At the root of the tree is an &#039;&#039;&#039;admin_root&#039;&#039;&#039; object.&lt;br /&gt;
&lt;br /&gt;
That has children that are &#039;&#039;&#039;admin_category&#039;&#039;&#039;s.&lt;br /&gt;
&lt;br /&gt;
Admin categories contain other categories, &#039;&#039;&#039;admin_settingpage&#039;&#039;&#039;s, and &#039;&#039;&#039;admin_externalpage&#039;&#039;&#039;s.&lt;br /&gt;
&lt;br /&gt;
Settings pages contain individual &#039;&#039;&#039;admin_setting&#039;&#039;&#039;s.&lt;br /&gt;
&lt;br /&gt;
admin_setting is a base class with lots of subclasses like &#039;&#039;&#039;admin_setting_configtext&#039;&#039;&#039;, &#039;&#039;&#039;admin_setting_configcheckbox&#039;&#039;&#039;, and so on. If you need to, you can create new subclasses.&lt;br /&gt;
&lt;br /&gt;
External pages are for things that do not fit into the normal settings structure. For example the global assign roles page, or the page for managing activity modules.&lt;br /&gt;
&lt;br /&gt;
==How the tree is built==&lt;br /&gt;
&lt;br /&gt;
When Moodle needs the admin tree, it calls admin_get_root in lib/adminlib.php, which&lt;br /&gt;
# creates a global $ADMIN object which is an instance of admin_root.&lt;br /&gt;
# does require_once admin/settings/top.php, which adds the top level categories to $ADMIN.&lt;br /&gt;
# does require_once on all the other files in admin/settings to add more specific settings pages and the settings themselves. Some of these settings files additionally make calls out to various types of plugins. For example&lt;br /&gt;
#* admin/settings/plugins.php gives activity modules, blocks, question types, ... a chance to add admin settings.&lt;br /&gt;
# adds the admin reports to the tree.&lt;br /&gt;
&lt;br /&gt;
As an optimisation, before building each bit of the tree, some capability checks are performed, and bits of the tree are skipped if the current user does not have permission to access them.&lt;br /&gt;
&lt;br /&gt;
Exactly how different types of plugin should add their settings to the tree should be documented in the [[Developer_documentation#Make_a_new_plugin|instructions for writing that sort of plugin]].&lt;br /&gt;
&lt;br /&gt;
==Individual settings==&lt;br /&gt;
&lt;br /&gt;
Let us look at a simple example: [http://cvs.moodle.org/moodle/mod/forum/settings.php?view=markup mod/forum/settings.php]. This is included by admin/settings/plugins.php, which has already created $settings, which is an admin_settingpage that we can add to. The file contains lots of lines that look a bit like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $settings-&amp;gt;add(new admin_setting_configcheckbox(&#039;forum_replytouser&#039;, get_string(&#039;replytouser&#039;, &#039;forum&#039;),&lt;br /&gt;
                    get_string(&#039;replytouser_desc&#039;, &#039;forum&#039;), 1));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What this means is that to our settings page, we are adding a checkbox setting. To understand this in more detail, we need to know what arguments the constructor for an admin_setting takes. The definition of the constructor is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 function admin_setting($name, $visiblename, $description, $defaultsetting) {&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, $name here is &#039;forum_replytouser&#039;. This means that this setting is stored in the database in the row of the config table where name=&#039;forum_replytouser&#039;, and is accessible as $CFG-&amp;gt;forum_replytouser.&lt;br /&gt;
&lt;br /&gt;
$visiblename is get_string(&#039;replytouser&#039;, &#039;forum&#039;), this is the label that is put in front of setting on the admin screen.&lt;br /&gt;
&lt;br /&gt;
$description is get_string(&#039;replytouser_desc&#039;, &#039;forum&#039;), this is a short bit of text displayed underneath the setting to explain it further.&lt;br /&gt;
&lt;br /&gt;
$defaultsetting is the default value for this setting. This value is used when Moodle is installed. For simple settings like checkboxes and text fields, this is a simple value. For some more complicated settings, this is an array.&lt;br /&gt;
&lt;br /&gt;
Let as now look at a more complicated example, from mod/quiz/settingstree.php:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $quizsettings-&amp;gt;add(new admin_setting_text_with_advanced(&#039;quiz/timelimit&#039;,&lt;br /&gt;
         get_string(&#039;timelimit&#039;, &#039;quiz&#039;), get_string(&#039;timelimit_desc&#039;, &#039;quiz&#039;),&lt;br /&gt;
         array(&#039;value&#039; =&amp;gt; &#039;0&#039;, &#039;fix&#039; =&amp;gt; false), PARAM_INT));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This shows two new things:&lt;br /&gt;
&lt;br /&gt;
$name here is &#039;quiz/timelimit&#039;. This is more complicated than a simple setting name. It means that this setting is stored in the config_plugins table, in the row where plugin=&#039;quiz&#039; and name=&#039;timelimit&#039;. It is not accessible through $CFG, to get it you can use get_config(&#039;quiz&#039;, &#039;timelimit&#039;).&lt;br /&gt;
&lt;br /&gt;
And this example shows a $defaultsetting that is an array.&lt;br /&gt;
&lt;br /&gt;
Normally, if you want a particular sort of setting, the easiest way is to look around the admin screens of your Moodle site, and find a setting like the one you want. Then go and copy the code and edit it. Therefore, we do not include a complete list of setting types here.&lt;br /&gt;
&lt;br /&gt;
==External pages==&lt;br /&gt;
&lt;br /&gt;
admin_externalpages represent screens of settings that do not fall into the standard pattern of admin_settings. The admin_externalpage object in the settings tree holds the URL of a PHP page that controls various settings.&lt;br /&gt;
&lt;br /&gt;
In that PHP page, near the start you need to call the function admin_externalpage_setup($pagename), then, instead of the usual print_header and print_footer functions, you use admin_externalpage_print_header() and admin_externalpage_print_footer() functions. This ensures that your page appears with the administration blocks and appropriate navigation.&lt;br /&gt;
&lt;br /&gt;
Note that if your external page relies on additional optional or required params, you may need to use the optional arguments to admin_externalpage_print_header to ensure that the Blocks editing on/off button works.&lt;br /&gt;
&lt;br /&gt;
Note that there are some subclasses of admin_externalpage, for example admin_page_managemods. In a lot of cases, these subclasses only exist to override the search method so this page can be found by appropriate searches.&lt;br /&gt;
&lt;br /&gt;
Once again, to understand this in more depth, your best approach is to look at how some of the external pages in Moodle work.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[Modules|adding settings for activity modules]]&lt;br /&gt;
* [[Admin_reports#How_your_report_gets_included_in_the_admin_tree|adding admin reports to the tree]]&lt;br /&gt;
* [[Repository_plugins#APIs_for_Administration|configuration of repository plugins]]&lt;br /&gt;
* [[Filters#Adding_a_settings_screen|configuration for filter]]&lt;br /&gt;
* [[Developer_documentation|Other developer documentation]]&lt;/div&gt;</summary>
		<author><name>Leblangi</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Adding_courses_and_categories_to_the_custom_menu&amp;diff=40872</id>
		<title>Adding courses and categories to the custom menu</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Adding_courses_and_categories_to_the_custom_menu&amp;diff=40872"/>
		<updated>2013-06-11T12:44:05Z</updated>

		<summary type="html">&lt;p&gt;Leblangi: /* How to add &amp;quot;My Courses&amp;quot; to the Custom Menu Bar for Moodle 2.4 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Themes}}&lt;br /&gt;
Hello this is going to be a very brief tutorial on how to add a courses and categories tree to the custom menu.&amp;lt;br /&amp;gt;&lt;br /&gt;
The reason for writing this tutorial is simply that this seems to be a request that is being made over and over again.&lt;br /&gt;
&lt;br /&gt;
==Before we get started==&lt;br /&gt;
Please please please make sure you are familiar with the other Themes 2.0 tutorials before attempting this tutorial.&lt;br /&gt;
&lt;br /&gt;
In particular I would recommend being familiar with the following documents and tutorials as I&#039;m going to move through this tutorial at a fast pace.&lt;br /&gt;
&lt;br /&gt;
* [[Themes overview]]&lt;br /&gt;
* [[Creating a theme]]&lt;br /&gt;
* [[Overriding a renderer]]&lt;br /&gt;
* [[Extending the theme custom menu]]&lt;br /&gt;
&lt;br /&gt;
Providing you are familiar with the above you should manage just fine with this tutorial and if you ever get stuck don&#039;t forget to ask in the theme&#039;s forums, there is always someone around who can help.&lt;br /&gt;
&lt;br /&gt;
===Two words of warning===&lt;br /&gt;
&#039;&#039;&#039;First&#039;&#039;&#039; Just a quick warning here, this tutorial adds all categories and courses to the navigation, on a site with a large number of categories and/or courses this will be a performance hit. I would strongly suggest that if you are looking to implement something such as this on a large site that you talk to your system admin and/or resident developer about setting up a shared cache and caching the result of the get_course_category_tree method... it is a technical task but doing so will improve the performance of this extension on a large site.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Second&#039;&#039;&#039; If you have categories nested 2 or more deep then there is a chance that you will run into display problems with the custom menu on some themes... not too much you can do about it but if you encounter it with a core theme and you fix it perhaps you would be kind enough to create an issue in our bug tracker and share the fix. That&#039;d being said this is only a hunch I have all of the theme&#039;s may be fine :)&lt;br /&gt;
&lt;br /&gt;
==Laying the ground work==&lt;br /&gt;
Alright I don&#039;t want this tutorial to drag out so get ready. For this tutorial I am just going to extend the standard theme, I&#039;m going to make absolutely no changes to the design and layout of the theme or the custom menu I am ONLY going to add a list of courses and categories to it.&lt;br /&gt;
&lt;br /&gt;
So to begin with within your Moodle themes directory create a new directory coursecategorymenu in which I want you to create three files, the first config.php which is obviously required, the second renderers.php as we are going to achieve this by overriding a renderer, and the third the English language file for this theme.&lt;br /&gt;
&lt;br /&gt;
You should end up with:&lt;br /&gt;
&lt;br /&gt;
* moodle/theme/coursecategorymenu&lt;br /&gt;
* moodle/theme/coursecategorymenu/config.php&lt;br /&gt;
* moodle/theme/coursecategorymenu/renderers.php&lt;br /&gt;
* moodle/theme/coursecategorymenu/lang/en/theme_coursecategorymenu.php&lt;br /&gt;
&lt;br /&gt;
==config.php==&lt;br /&gt;
Obviously because all I want to base this theme off the standard theme and only override a renderer the config.php file is going to be VERY basic, so much so that I&#039;m not going to go into details about it, as you&#039;ve read the recommended tutorials you will already be completely familiar with everything it is doing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
$THEME-&amp;gt;name = &#039;coursecategorymenu&#039;;&lt;br /&gt;
$THEME-&amp;gt;parents = array(&#039;standard&#039;, &#039;base&#039;);&lt;br /&gt;
$THEME-&amp;gt;rendererfactory = &#039;theme_overridden_renderer_factory&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==renderers.php==&lt;br /&gt;
This is of course where the magic is going to happen.&lt;br /&gt;
&lt;br /&gt;
In my case I want to add a branch to the end of the custom menu titled &#039;&#039;Courses&#039;&#039; and then I want to add the category and course structure to that branch.&lt;br /&gt;
&lt;br /&gt;
So like the [[Themes 2.0 extending the custom menu|extending the custom menu]] tutorial I will be overriding the core renderer and I will also be overriding the render_custom_menu_method.&lt;br /&gt;
&lt;br /&gt;
So the code for this:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class theme_coursecategorymenu_core_renderer extends core_renderer {&lt;br /&gt;
 &lt;br /&gt;
    protected function render_custom_menu(custom_menu $menu) {&lt;br /&gt;
        // Our code will go here shortly&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You&#039;ll notice that is identical to the starting code for the extending custom menu tutorial.&lt;br /&gt;
&lt;br /&gt;
The difference comes in the code that we are going to populate it with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/lib.php&#039;);&lt;br /&gt;
        &lt;br /&gt;
$branch = $menu-&amp;gt;add(get_string(&#039;courses&#039;, &#039;theme_coursecategorymenu&#039;), null, null, 10000);&lt;br /&gt;
&lt;br /&gt;
$categorytree = get_course_category_tree();&lt;br /&gt;
foreach ($categorytree as $category) {&lt;br /&gt;
    $this-&amp;gt;add_category_to_custommenu($branch, $category);&lt;br /&gt;
}&lt;br /&gt;
        &lt;br /&gt;
return parent::render_custom_menu($menu);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So lets work through this code line by line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
require_once($CFG-&amp;gt;dirroot.&#039;/course/lib.php&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This we need to do because we are going to use part of the course API, in particular a function called &#039;&#039;get_course_category_tree()&#039;&#039; that we&#039;ll look at shortly.&lt;br /&gt;
The function we want to use exists within the course lib file and in order to be sure its always available we need to include this file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$branch = $menu-&amp;gt;add(get_string(&#039;courses&#039;, &#039;theme_coursecategorymenu&#039;), null, null, 10000);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line adds the &#039;&#039;Courses&#039;&#039; branch to the custom menu into which we will add the category and course structure.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$categorytree = get_course_category_tree();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line is the main one to note, here we are calling a Moodle function that will return us a category and course tree, because all courses need to be within a category the initial return is an array of categories, each category in the array will have the properties of the category as well as two additional properties, the first property &#039;&#039;&#039;categories&#039;&#039;&#039; is an array containing all of this categories sub categories, and the second property &#039;&#039;&#039;courses&#039;&#039;&#039; is also an array containing all of the courses within this category.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$categorytree = get_course_category_tree();&lt;br /&gt;
foreach ($categorytree as $category) {&lt;br /&gt;
    $this-&amp;gt;add_category_to_custommenu($branch, $category);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now these lines of code deal with the initial array of categories returned by the &#039;&#039;get_course_category_tree&#039;&#039; function.&lt;br /&gt;
&lt;br /&gt;
In this case we iterate of the initial categories and for each one we call a method of the renderer &#039;&#039;&#039;add_category_to_custommenu&#039;&#039;&#039; now those of you who are clued in will realise that this method doesn&#039;t exist yet... and you are correct - we need to write this method which is what we will look at next.&amp;lt;br /&amp;gt;&lt;br /&gt;
As a heads up the reason that we need to write another method is because we need a method that we can call recursivily as there are potentially infinite category branches all contains sub categories and courses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
return parent::render_custom_menu($menu);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The final line of code simply calls the original render_custom_menu method now that we have extended the custom menu as we want.&lt;br /&gt;
&lt;br /&gt;
Now that we have looked at the render_custom_menu lets write the function we just talked about &#039;&#039;&#039;add_category_to_custommenu&#039;&#039;&#039;.&amp;lt;br /&amp;gt;&lt;br /&gt;
This function as discussed above is special in that we intend to call it recursively, that means we want to call it once for EVERY category that exists in the tree. We will need to give it the categories parent menu item as well as the category object we want added.&lt;br /&gt;
&lt;br /&gt;
Lets look at the code for this method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
protected function add_category_to_custommenu(custom_menu_item $parent, stdClass $category) {&lt;br /&gt;
    $branch = $parent-&amp;gt;add($category-&amp;gt;name, new moodle_url(&#039;/course/category.php&#039;, array(&#039;id&#039; =&amp;gt;  $category-&amp;gt;id)));&lt;br /&gt;
    if (!empty($category-&amp;gt;categories)) {&lt;br /&gt;
        foreach ($category-&amp;gt;categories as $subcategory) {&lt;br /&gt;
            $this-&amp;gt;add_category_to_custommenu($branch, $subcategory);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if (!empty($category-&amp;gt;courses)) {&lt;br /&gt;
        foreach ($category-&amp;gt;courses as $course) {&lt;br /&gt;
            $branch-&amp;gt;add($course-&amp;gt;shortname, new moodle_url(&#039;/course/view.php&#039;, array(&#039;id&#039; =&amp;gt; $course-&amp;gt;id)), $course-&amp;gt;fullname);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ok so that doesn&#039;t look too bad, as you&#039;ve already read the extending custom menu tutorial you will be able to spot some of the things it is doing, none the less lets walk through the code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
protected function add_category_to_custommenu(custom_menu_item $parent, stdClass $category) {&lt;br /&gt;
    .....&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
First up the function definition, this function is going to be private because only we need it and it is going to take two arguments, the first $parent has to be a custom_menu_item, the second $category has to be the category object.&lt;br /&gt;
&lt;br /&gt;
The objective of this method is to add a category node to the custom menu, in regards to our arguments we want to add $category as a child of $parent.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$branch = $parent-&amp;gt;add($category-&amp;gt;name, new moodle_url(&#039;/course/category.php&#039;, array(&#039;id&#039; =&amp;gt;  $category-&amp;gt;id)));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line looks very familiar, here we are adding a node for the category to the $parent, we are also collecting the newly added node as $branch.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!empty($category-&amp;gt;categories)) {&lt;br /&gt;
    foreach ($category-&amp;gt;categories as $subcategory) {&lt;br /&gt;
        $this-&amp;gt;add_category_to_custommenu($branch, $subcategory);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now this code is responsible for add the sub categories of this category to the menu as well, first we need to check that the categories property isn&#039;t empty (if it is there is nothing to add).&lt;br /&gt;
Assuming there are sub categories we need go through each of them and call this method on them so that they get added to the custom menu as well.&amp;lt;br /&amp;gt;&lt;br /&gt;
This is called recursion.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
if (!empty($category-&amp;gt;courses)) {&lt;br /&gt;
    foreach ($category-&amp;gt;courses as $course) {&lt;br /&gt;
        $branch-&amp;gt;add($course-&amp;gt;shortname, new moodle_url(&#039;/course/view.php&#039;, array(&#039;id&#039; =&amp;gt; $course-&amp;gt;id)), $course-&amp;gt;fullname);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This code is very similar to the above code except that we are looking at the courses within this category.&amp;lt;br /&amp;gt;&lt;br /&gt;
Also note that this bit of code doesn&#039;t call add_category_to_custommenu recursivily, it doesn&#039;t need to as courses are the last bit we want to display on the menu within the category.&lt;br /&gt;
&lt;br /&gt;
And that is it, time to tidy up and we&#039;re done.&lt;br /&gt;
&lt;br /&gt;
==Finishing up==&lt;br /&gt;
All of the code is written now there is only last thing to do in order to tidy up however and that is to add the &#039;&#039;courses&#039;&#039; string that we used earlier... did you spot it?&lt;br /&gt;
&lt;br /&gt;
This is of course very easy, open up &#039;&#039;&#039;moodle/theme/coursecategorymenu/lang/en/theme_coursecategorymenu.php&#039;&#039;&#039; and add the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
$string[&#039;courses&#039;] = &#039;Courses&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And we&#039;re done. If you now browse to your site and change to the new theme you should see the Courses branch at the end of your custom menu that contains all of the categories, sub categories and courses for your site.&lt;br /&gt;
&lt;br /&gt;
==Full source==&lt;br /&gt;
===config.php===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
$THEME-&amp;gt;name = &#039;coursecategorymenu&#039;;&lt;br /&gt;
$THEME-&amp;gt;parents = array(&#039;standard&#039;, &#039;base&#039;);&lt;br /&gt;
$THEME-&amp;gt;rendererfactory = &#039;theme_overridden_renderer_factory&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
===renderers.php===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class theme_coursecategorymenu_core_renderer extends core_renderer {&lt;br /&gt;
 &lt;br /&gt;
    protected function render_custom_menu(custom_menu $menu) {&lt;br /&gt;
        global $CFG;&lt;br /&gt;
        &lt;br /&gt;
        require_once($CFG-&amp;gt;dirroot.&#039;/course/lib.php&#039;);&lt;br /&gt;
        &lt;br /&gt;
        $branch = $menu-&amp;gt;add(get_string(&#039;courses&#039;, &#039;theme_coursecategorymenu&#039;), null, null, 10000);&lt;br /&gt;
        &lt;br /&gt;
        $categorytree = get_course_category_tree();&lt;br /&gt;
        foreach ($categorytree as $category) {&lt;br /&gt;
            $this-&amp;gt;add_category_to_custommenu($branch, $category);&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        return parent::render_custom_menu($menu);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    protected function add_category_to_custommenu(custom_menu_item $parent, stdClass $category) {&lt;br /&gt;
        $branch = $parent-&amp;gt;add($category-&amp;gt;name, new moodle_url(&#039;/course/category.php&#039;, array(&#039;id&#039; =&amp;gt;  $category-&amp;gt;id)));&lt;br /&gt;
        if (!empty($category-&amp;gt;categories)) {&lt;br /&gt;
            foreach ($category-&amp;gt;categories as $subcategory) {&lt;br /&gt;
                $this-&amp;gt;add_category_to_custommenu($branch, $subcategory);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        if (!empty($category-&amp;gt;courses)) {&lt;br /&gt;
            foreach ($category-&amp;gt;courses as $course) {&lt;br /&gt;
                $branch-&amp;gt;add($course-&amp;gt;shortname, new moodle_url(&#039;/course/view.php&#039;, array(&#039;id&#039; =&amp;gt; $course-&amp;gt;id)), $course-&amp;gt;fullname);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
===lang/en/theme_coursecategorymenu.php===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
$string[&#039;courses&#039;] = &#039;Courses&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==How to add &amp;quot;My Courses&amp;quot; to the Custom Menu Bar for Moodle 2.4==&lt;br /&gt;
&lt;br /&gt;
This adds a nice drop down for logged in users so they can easily see their relevant courses.  Note the code below has not been tested on Moodle 2.0-2.3, but you can find working code and instructions on how to add &amp;quot;My Courses&amp;quot; to the custom menu bar for those versions at: [[Themes_2.0_extending_the_custom_menu]]&lt;br /&gt;
&lt;br /&gt;
Below is the Moodle 2.4 custom menu code to add to theme/themename/renderers.php &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
// Add the code below to Moodle 2.4   /theme/themname/renderers.php&lt;br /&gt;
&amp;lt;?php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class theme_themename_core_renderer extends core_renderer {&lt;br /&gt;
&lt;br /&gt;
    protected function render_custom_menu(custom_menu $menu) {&lt;br /&gt;
&lt;br /&gt;
        global $CFG;&lt;br /&gt;
        require_once($CFG-&amp;gt;dirroot.&#039;/course/lib.php&#039;);&lt;br /&gt;
&lt;br /&gt;
	// Moodle 2.4 doesn&#039;t appear to support $mycourses = $this-&amp;gt;page-&amp;gt;navigation-&amp;gt;get(&#039;mycourses&#039;); so &lt;br /&gt;
&lt;br /&gt;
	if (isloggedin() &amp;amp;&amp;amp; !isguestuser() &amp;amp;&amp;amp; $mycourses = enrol_get_my_courses(NULL, &#039;visible DESC, fullname ASC&#039;)) {  //which does work&lt;br /&gt;
&lt;br /&gt;
            $branchlabel = get_string(&#039;mycourses&#039;) ;&lt;br /&gt;
            $branchurl   = new moodle_url(&#039;/course/index.php&#039;);&lt;br /&gt;
            $branchtitle = $branchlabel;&lt;br /&gt;
            $branchsort  = 8000 ; // lower numbers = higher priority e.g. move this item to the left on the Custom Menu	&lt;br /&gt;
            $branch = $parent-&amp;gt;add($branchlabel, $branchurl, $branchtitle, $branchsort);&lt;br /&gt;
			&lt;br /&gt;
            foreach ($mycourses as $mycourse) {&lt;br /&gt;
                $branch-&amp;gt;add($mycourse-&amp;gt;shortname, new moodle_url(&#039;/course/view.php&#039;, array(&#039;id&#039; =&amp;gt; $mycourse-&amp;gt;id)), $mycourse-&amp;gt;fullname);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
//Note to integrate this into the code for adding course and categories at the top of this document page, &lt;br /&gt;
//remove this class definition (you only need it once, and change the function name here to:&lt;br /&gt;
//&lt;br /&gt;
//     protected function render_mycourses_custom_menu(custom_menu_item $menu, $position) {&lt;br /&gt;
//&lt;br /&gt;
//then add a line in the original render_custom_menu function towards the end of it and invoke this function by&lt;br /&gt;
//&lt;br /&gt;
//     $this-&amp;gt;render_mycourses_custom_menu($menu, 12000) ;  &lt;br /&gt;
//&lt;br /&gt;
//&lt;br /&gt;
//Finally, don&#039;t forget to add the language definition for mycourses if that is not already set.  Bon chance!!&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please note, in the comments I did also highlight the bit that doesn&#039;t work in Moodle 2.4.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [http://developer.yahoo.com/yui/3/node-menunav/ YUI 3 Menunav component the custom menu uses]&lt;/div&gt;</summary>
		<author><name>Leblangi</name></author>
	</entry>
</feed>