<?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=Gabrielros</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=Gabrielros"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Gabrielros"/>
	<updated>2026-04-18T02:58:17Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Git_for_developers&amp;diff=51078</id>
		<title>Git for developers</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Git_for_developers&amp;diff=51078"/>
		<updated>2016-11-15T14:17:01Z</updated>

		<summary type="html">&lt;p&gt;Gabrielros: /* Changing commit message, reordering and squashing commits */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document is for helping you get started on Moodle development with Git. For further details of Git, see [[:Category:Git]].&lt;br /&gt;
&lt;br /&gt;
== General workflow ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A reasonable knowledge of the Git basics is a good idea before you start to use it for development. If you are new to Git, you are encouraged to go to &#039;See also&#039; for some more general reading.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[image:git-pushpull-model.png|right|thumb|400px|Moodle development workflow with Git]]&lt;br /&gt;
Detailed explanation of the workflow can be found in the [[Process]] page. In short, the Moodle development with Git looks like this:&lt;br /&gt;
&lt;br /&gt;
* You as the contributor commit changes into your personal repository at your computer&lt;br /&gt;
* You push the changes into your public repository and publish links to your changes in the Moodle Tracker&lt;br /&gt;
* You request a peer review of your code from another developer&lt;br /&gt;
* When peer reviewer is happy they submit issue for integration&lt;br /&gt;
* Moodle integrators pull the changes from your public repository and if they like them, they put them into Moodle integration repository&lt;br /&gt;
* The integrated change is tested and finally pushed into Moodle production repository&lt;br /&gt;
* You update your local repository with all changes from the production repository and the next cycle may start again&lt;br /&gt;
&lt;br /&gt;
This workflow runs in roughly weekly cycles. The integration happens on Monday and Tuesday and the testing on Wednesday. On Thursday (or Friday if testing takes too long), the production repository moodle.git is usually updated with changes from the last development week.&lt;br /&gt;
&lt;br /&gt;
Most Moodle developers have their public repositories hosted at [http://github.com/ Github]. Alternatively you may want to try [http://gitorious.org Gitorious] or the legendary [http://repo.or.cz repo.or.cz]. In the examples in this guide we assume you&#039;ll set up your public repository at Github.&lt;br /&gt;
&lt;br /&gt;
When you first register on tracker you can not assign issues to yourself or send them for peer review. You will be added to the developers group after your first bug fix is integrated. Before that just comment on the issue with a link to your branch and component lead or another developer will send issue for peer review for you.&lt;br /&gt;
&lt;br /&gt;
== Installing Git on your computer ==&lt;br /&gt;
&lt;br /&gt;
Install Git on your computer. Most Linux distributions have Git available as a package to install. On Debian/Ubuntu, type &#039;&#039;&#039;&#039;sudo apt-get install git&#039;&#039;&#039;&#039; on the terminal. If you are on Mac, [http://code.google.com/p/git-osx-installer/ git-osx-installer] installs it in a few clicks. &lt;br /&gt;
&lt;br /&gt;
Immediately after the installation, set your name and contact e-mail. The name and e-mail will become part of your commits and they can&#039;t be changed later once your commits are accepted into the Moodle code. Therefore we ask contributors to use their real names written in capital letters, eg &amp;quot;John Smith&amp;quot; and not &amp;quot;john smith&amp;quot; or even &amp;quot;john5677&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
    git config --global user.name &amp;quot;Your Name&amp;quot;&lt;br /&gt;
    git config --global user.email yourmail@domain.tld&lt;br /&gt;
&lt;br /&gt;
Unless you are the repository maintainer, it is wise to set your Git to not push changes in file permissions:&lt;br /&gt;
&lt;br /&gt;
    git config --global core.filemode false&lt;br /&gt;
&lt;br /&gt;
Also, it&#039;s recommended to verify that the your git installation is not performing any transformation between LFs and CRLFs. All Moodle &#039;&#039;&#039;uses only LFs&#039;&#039;&#039; and you should &#039;&#039;&#039;fetch/edit and push&#039;&#039;&#039; it that way (may need to configure your editor/IDE too). Note that having any &amp;quot;magic&amp;quot; enabled is known to cause [[Common unit test problems#The_test_file_.22evolution.test.22_should_not_contain_section_named_.22.5Blots_of_content.5D.22|problems with unit tests]] execution. So we recommend you to set:&lt;br /&gt;
&lt;br /&gt;
    git config --global core.autocrlf false&lt;br /&gt;
&lt;br /&gt;
== Setting-up the public repository ==&lt;br /&gt;
&lt;br /&gt;
1. Go to [http://github.com/ Github] and create an account.&lt;br /&gt;
&lt;br /&gt;
2. Go to the [http://github.com/moodle/moodle official Moodle Github repository] and click on the Fork button. You now have your own Github Moodle repository.&lt;br /&gt;
&lt;br /&gt;
3. Now you need to set up your SSH public key, so you can push to your Github Moodle repository from your local Moodle repository. On Mac you can go on this [http://help.github.com/mac-key-setup/ Github help page]. If you are on another system, go to your Github administration page, to the section SSH Public Keys, and you should see a link to a help page. Done? Good! That was the most difficult part!&lt;br /&gt;
&lt;br /&gt;
== Setting-up the local repository at your computer  ==&lt;br /&gt;
&lt;br /&gt;
Create a local clone repository of your Github repository. In a terminal:&lt;br /&gt;
&lt;br /&gt;
    git clone git://github.com/YOUR_GITHUB_USERNAME/moodle.git LOCALDIR&lt;br /&gt;
&lt;br /&gt;
    (or:  git clone git@github.com:YOUR_GITHUB_USERNAME/moodle.git LOCALDIR)&lt;br /&gt;
&lt;br /&gt;
This command does several jobs for you. It creates a new folder, initializes an empty Git repository in it, sets your Github repository as the remote repository called &#039;origin&#039; and makes a local checkout of the branch &#039;master&#039; from it. The important point to remember now is that your Github repository is aliased as &#039;origin&#039; for your local clone.&lt;br /&gt;
&lt;br /&gt;
Note that the format of the URL here is important. In the first example, the URL starts &amp;quot;git://github.com&amp;quot; and this will give read-only access to the repository at github.com. If you use this URL, the &amp;quot;git push origin&amp;quot; command that appears later in this document will not work. Therefore, if you want to be able to update the &amp;quot;origin&amp;quot; repository, you should use the URL that starts &amp;quot;git@github.com&amp;quot;, i.e. the second of the two &amp;quot;git clone&amp;quot; commands given above. This will give you read and write access to the repository on github.com.&lt;br /&gt;
&lt;br /&gt;
== Keeping your public repository up-to-date ==&lt;br /&gt;
&lt;br /&gt;
[[image:git-sync-github.png|right|thumb|400px|Fetching changes from upstream and pushing them to github]]&lt;br /&gt;
Your fork at Github is not updated automatically. To keep it synced with the upstream Moodle repository, you have to fetch the recent changes from the official moodle.git and push them to your public repository. To avoid problems with this it is strongly recommended that you never modify the standard Moodle branches. &#039;&#039;Remember: never commit directly into master and MOODLE_xx_STABLE branches.&#039;&#039; In other words, always create topic branches to work on. In Gitspeak, the master branch and MOODLE_xx_STABLE branches should be always fast-forwardable.&lt;br /&gt;
&lt;br /&gt;
To keep your public repository up-to-date, we will register remote repository git://git.moodle.org/moodle.git under &#039;upstream&#039; alias. Then we create a script to be run regularly that fetches changes from the upstream repository and pushes them to your public repository. Note that this procedure will not affect your local working directory.&lt;br /&gt;
&lt;br /&gt;
To register the upstream remote:&lt;br /&gt;
&lt;br /&gt;
    cd moodle&lt;br /&gt;
    git remote add upstream git://git.moodle.org/moodle.git&lt;br /&gt;
&lt;br /&gt;
The following commands can be used to keep the standard Moodle branches at your Github repository synced with the upstream repository. You may wish to store them in a script so that you can run it every week after the upstream repository is updated.&lt;br /&gt;
&lt;br /&gt;
    #!/bin/bash&lt;br /&gt;
    git fetch upstream&lt;br /&gt;
    for BRANCH in MOODLE_{19..27}_STABLE master; do&lt;br /&gt;
        git push origin refs/remotes/upstream/$BRANCH:$BRANCH&lt;br /&gt;
    done&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== How it works ===&lt;br /&gt;
&lt;br /&gt;
The git-fetch command does not modify your current working dir (your checkout). It just downloads all recent changes from a remote repository and stores them into so called remote-tracking branches. The git-push command takes these remote-tracking branches from upstream and pushes them to Github under the same name. Understanding this fully requires a bit knowledge of Git internals - see gitrevisions(7) man page.&lt;br /&gt;
&lt;br /&gt;
Note there is no need to switch the local branch during this. You can even execute this via cron at your machine. Just note that the upstream repository updates typically just once a week.&lt;br /&gt;
&lt;br /&gt;
=== New branches ===&lt;br /&gt;
&lt;br /&gt;
Occasionally, moodle.org will create a new branch that does not exist in your public (e.g. Github.com) repository. If you try to push this new branch, you will see an error such as the following:&lt;br /&gt;
&lt;br /&gt;
    error: unable to push to unqualified destination: MOODLE_99_STABLE&lt;br /&gt;
    The destination refspec neither matches an existing ref on the remote&lt;br /&gt;
    nor begins with refs/, and we are unable to guess a prefix based on the source ref.&lt;br /&gt;
    error: failed to push some refs to &#039;git@github.com:YOUR_GITHUB_USERNAME/moodle.git&#039;&lt;br /&gt;
&lt;br /&gt;
In the above example, &amp;quot;MOODLE_99_STABLE&amp;quot;, is the name of the new branch that does not exist in your public repository. To fix the error, you need to create the new branch on your public repository, using the following commands, replacing &amp;quot;MOODLE_99_STABLE&amp;quot; with the name of the new branch you wish to create:&lt;br /&gt;
&lt;br /&gt;
    git checkout MOODLE_99_STABLE&lt;br /&gt;
    git push origin MOODLE_99_STABLE:MOODLE_99_STABLE&lt;br /&gt;
&lt;br /&gt;
The above code will create a new copy of the &amp;quot;MOODLE_99_STABLE&amp;quot; branch in your local repository. If you do not need to keep a local copy of the new branch - and probably you do not need it, you then can remove it from your local repository as follows:&lt;br /&gt;
&lt;br /&gt;
    git checkout master&lt;br /&gt;
    git branch -D MOODLE_99_STABLE&lt;br /&gt;
&lt;br /&gt;
== Preparing a patch ==&lt;br /&gt;
&lt;br /&gt;
As said earlier at this page, you never work on standard Moodle branches directly. Every time you are going to edit something, switch to a local branch. Fork the local branch off the standard branch you think it should be merged to. So if you are working on a patch for 1.9 or 2.0, fork the branch off MOODLE_19_STABLE or MOODLE_20_STABLE, respectively. Patches for the next [[Moodle versions|major version]] should be based on the master branch.&lt;br /&gt;
&lt;br /&gt;
    git checkout -b MDL-xxxxx-nasty-bug origin/master&lt;br /&gt;
&lt;br /&gt;
Note that if you forget to specify the starting point, the branch is based on the currently checked-out branch. It may not be what you want. It is recommended to always specify the starting point.&lt;br /&gt;
&lt;br /&gt;
To check the current branch, run&lt;br /&gt;
&lt;br /&gt;
    git branch&lt;br /&gt;
&lt;br /&gt;
The current branch is highlighted.&lt;br /&gt;
&lt;br /&gt;
Now go and fix the issue with your favorite IDE. Check the status of the files, view the change to be committed and finally commit the change:&lt;br /&gt;
&lt;br /&gt;
    vim filename.php&lt;br /&gt;
    git status&lt;br /&gt;
    git diff&lt;br /&gt;
    git commit -a&lt;br /&gt;
&lt;br /&gt;
Note that this is safe as the commit is recorded just locally, nothing is sent to any server yet (as it would in CVS). To see history of the commits, use&lt;br /&gt;
&lt;br /&gt;
    git log&lt;br /&gt;
&lt;br /&gt;
Once your local branch contains the change (note that it may consists of several patches) and you are happy with it, publish the branch at your public repository:&lt;br /&gt;
&lt;br /&gt;
    git push origin MDL-xxxxx-nasty-bug&lt;br /&gt;
&lt;br /&gt;
Now as your branch is published, you can ask Moodle core developers to review it and eventually integrate it into the standard Moodle repository.&lt;br /&gt;
&lt;br /&gt;
=== Changing commit message, reordering and squashing commits ===&lt;br /&gt;
&lt;br /&gt;
It often happens that you made a mistake in your patch or in the commit message and helpful CiBot pointed it out for you. You can &amp;quot;rewrite the history&amp;quot; and change the existing commits.&lt;br /&gt;
&lt;br /&gt;
Option 1. Reset all the changes in the branch and commit again. &lt;br /&gt;
&lt;br /&gt;
    git reset --mixed origin/master&lt;br /&gt;
&lt;br /&gt;
Now all your changes are still present but all commits on top of &amp;quot;master&amp;quot; branch are gone. You can create a new commit&lt;br /&gt;
&lt;br /&gt;
Option 2. Discover &#039;&#039;&#039;git rebase&#039;&#039;&#039; - this is a powerful tool to change the sequence of commit, change the commit messages, squash commits, etc. We will not cover it here, there are many articles in the Internet about it.&lt;br /&gt;
&lt;br /&gt;
Whatever option you chose, you have &amp;quot;rewritten the history&amp;quot; and you can not simply push the changes to github again because they would need to overwrite the commits that were already pushed. If you try &amp;quot;git push MDL-xxxxx-nasty-bug&amp;quot; you will get an error message suggesting you to force push. &lt;br /&gt;
To force push the changed commits use:&lt;br /&gt;
&lt;br /&gt;
    git push -f origin MDL-xxxxx-nasty-bug&lt;br /&gt;
&lt;br /&gt;
If an error occurs because you are still using the git protocol (read only), use this command : &lt;br /&gt;
&lt;br /&gt;
    git remote set-url origin https://github.com/&amp;lt;user.name&amp;gt;/moodle.git&lt;br /&gt;
&lt;br /&gt;
A prompt will ask for your credentials, if you previously setup your SSH public key you can also use this one : &lt;br /&gt;
&lt;br /&gt;
    git remote set-url origin git@github.com:&amp;lt;user.name&amp;gt;/moodle.git&lt;br /&gt;
&lt;br /&gt;
=== Checking if a branch has already been merged ===&lt;br /&gt;
&lt;br /&gt;
After some time contributing to Moodle you would have a lot of branches both in your local repository and in your public repository. To prune their list and delete those that were accepted by upstream, use the following&lt;br /&gt;
&lt;br /&gt;
    git fetch upstream                                      (1)&lt;br /&gt;
    git branch --merged upstream/master                     (2)&lt;br /&gt;
    git branch --merged upstream/MOODLE_20_STABLE           (3)&lt;br /&gt;
&lt;br /&gt;
The command (1) fetches the changes from your upstream repository at git.moodle.org (remember that git-fetch does not modify your working dir so it is safe to run it whenever). Command (2) and (3) print all branches that are merged into the upstream master branch and MOODLE_20_STABLE branch, respectively. To delete these local branches, use&lt;br /&gt;
&lt;br /&gt;
    git branch -d MDL-xxxxx-accepted-branch&lt;br /&gt;
&lt;br /&gt;
The similar approach can be used to check the branches published at your origin repository at github.com&lt;br /&gt;
&lt;br /&gt;
    git fetch origin                                        (1)&lt;br /&gt;
    git fetch upstream&lt;br /&gt;
    git branch -r --merged upstream/master                  (2)&lt;br /&gt;
    git branch -r --merged upstream/MOODLE_20_STABLE        (3)&lt;br /&gt;
&lt;br /&gt;
The command (1) makes sure that you have all your branches from github.com recorded as the remote tracking branch locally. Commands (2) and (3) work the same as in the previous example but they list remote tracking branches only ([http://www.kernel.org/pub/software/scm/git/docs/git-branch.html see -r param]). To delete a branch at github.com, use&lt;br /&gt;
&lt;br /&gt;
    git push origin :MDL-xxxx-branch-to-delete&lt;br /&gt;
&lt;br /&gt;
This syntax may look weird to you. However it is pretty logical. The general syntax of the git-push command is&lt;br /&gt;
&lt;br /&gt;
    git push &amp;lt;repository&amp;gt; &amp;lt;source ref&amp;gt;:&amp;lt;target ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
so deleting a remote branch can be understood as pushing an &amp;quot;empty (null) reference&amp;quot; to it.&lt;br /&gt;
&lt;br /&gt;
== Peer-reviewing someone else&#039;s code ==&lt;br /&gt;
&lt;br /&gt;
To review a branch that someone else pushed into their public repository, you do not need to register a new remote (unless you work with such repository frequently, of course). Let us imagine your friend Alice pushed a work-in-progress branch called &#039;wip-feature&#039; into her Github repository and asked you to review it. You need to know the read-only address of the repository and the name of the branch.&lt;br /&gt;
&lt;br /&gt;
    git fetch git://github.com/alice/moodle.git wip-feature&lt;br /&gt;
&lt;br /&gt;
This will download all required data and will keep the pointer to the tip of the wip-feature branch in a local symbolic reference FETCH_HEAD. To see what&#039;s there on that branch, use&lt;br /&gt;
&lt;br /&gt;
    git log -p FETCH_HEAD&lt;br /&gt;
&lt;br /&gt;
To see how a particular file looks at Alice&#039;s branch&lt;br /&gt;
&lt;br /&gt;
    git show FETCH_HEAD:admin/blocks.php&lt;br /&gt;
&lt;br /&gt;
To create a new local branch called &#039;alice-wip-feature&#039; containing the work by Alice, use&lt;br /&gt;
&lt;br /&gt;
    git checkout -b alice-wip-feature FETCH_HEAD&lt;br /&gt;
&lt;br /&gt;
To merge Alice&#039;s work into your current branch:&lt;br /&gt;
&lt;br /&gt;
    git merge FETCH_HEAD&lt;br /&gt;
&lt;br /&gt;
To see what would be merged into the current branch without actually modifying anything:&lt;br /&gt;
&lt;br /&gt;
    git diff ...FETCH_HEAD&lt;br /&gt;
&lt;br /&gt;
Once you are all set and reviewing code, this [[Peer_reviewing_checklist|checklist]] should prove to be useful.&lt;br /&gt;
&lt;br /&gt;
== Rebasing a branch ==&lt;br /&gt;
&lt;br /&gt;
Rebasing is a process when you cut off the branch from its current start point and transplant it to another point. Let us assume the following history exists:&lt;br /&gt;
&lt;br /&gt;
          A---B---C topic&lt;br /&gt;
         /&lt;br /&gt;
    D---E---F---G master&lt;br /&gt;
&lt;br /&gt;
From this point, the result of the command:&lt;br /&gt;
&lt;br /&gt;
    git rebase master topic&lt;br /&gt;
&lt;br /&gt;
would be:&lt;br /&gt;
&lt;br /&gt;
                  A&#039;--B&#039;--C&#039; topic&lt;br /&gt;
                 /&lt;br /&gt;
    D---E---F---G master&lt;br /&gt;
&lt;br /&gt;
and would end with &#039;topic&#039; being your current branch.&lt;br /&gt;
&lt;br /&gt;
You may be asked to rebase your branch submitted for the integration if the submitted branch was based on an outdated commit. The typical case is if you create a new branch as a fork off the upstream master branch on Tuesday. Then on Wednesday, the upstream master branch grows as all changes from the last integration cycle are merged to it. To make diff easy on Github for next weekly pull request review, you want to rebase your branch against the updated master.&lt;br /&gt;
&lt;br /&gt;
    git rebase master MDL-xxxxx-topic-branch&lt;br /&gt;
&lt;br /&gt;
Note that rebasing effectively rewrites the history of the branch. &#039;&#039;&#039;Do not rebase the branch if there is a chance that somebody has already forked it and based their own branch on it.&#039;&#039;&#039; For this reason, many Git tutorials discourage from rebasing any branch that has been published. However in Moodle, all branches submitted for integration are potential subject of rebase (even though we try to not to do it often) and you should not base your own branches on them.&lt;br /&gt;
&lt;br /&gt;
=== Conflicts during rebase ===&lt;br /&gt;
&lt;br /&gt;
During the rebase procedure, conflicts may appear. git-status commands reports the conflicted files. Explore them carefully and fix them in your editor (like you would do with CVS). Then add the files with &#039;git add&#039; command and continue.&lt;br /&gt;
&lt;br /&gt;
    vim conflicted.php&lt;br /&gt;
    git add conflicted.php&lt;br /&gt;
    git rebase --continue&lt;br /&gt;
&lt;br /&gt;
== Applying changes from one branch to another ==&lt;br /&gt;
&lt;br /&gt;
Most bugs are fixed at a stable branch (like MOODLE_20_STABLE) and the fix must be prepared for other branches, too (like MOODLE_21_STABLE and the main development branch - master). In Moodle, we do not merge stable branches into the master one. So usually the contributor prepares at least two branches - with the fix for the stable branch(es) and with the fix for the master branch.&lt;br /&gt;
&lt;br /&gt;
If you have a patch prepared on a local branch (let us say MDL-xxxx-topic_20_STABLE), it is possible to re-apply it to another branch.&lt;br /&gt;
&lt;br /&gt;
=== Cherry-picking a single commit ===&lt;br /&gt;
&lt;br /&gt;
Let us have two local Git repositories ~/public_html/moodle21 containing local installation of Moodle 2.1 and ~/public_html/moodledev with the local installation of most recent development version of Moodle. They both use your public repository at github.com as the origin. You have a branch in moodle21 called MDL-xxxx-topic_21_STABLE that was forked off MOODLE_21_STABLE. It contains one commit. Now you want to re-apply this commit to a branch MDL-xxxx-topic in moodledev.&lt;br /&gt;
&lt;br /&gt;
    cd ~/public_html/moodledev&lt;br /&gt;
    git checkout -b MDL-xxxx-topic origin/master            (1)&lt;br /&gt;
    git fetch ../moodle21 MDL-xxxx-topic_21_STABLE          (2)&lt;br /&gt;
    git cherry-pick FETCH_HEAD                              (3)&lt;br /&gt;
&lt;br /&gt;
The command (1) creates new local branch forked off the CONTHERE The command (1) fetches all data needed to re-apply the topic branch and stores the pointer to the tip of that branch to FETCH_HEAD symbolic reference. The command (2) picks the tip of the branch (the top-most commit on it) and tries to apply it on the current branch.&lt;br /&gt;
There is also a variant of the cherry-pick command that supports multiple commits, shortly (see its man page for details): &amp;lt;code bash&amp;gt;$ git cherry-pick A^..B&amp;lt;/code&amp;gt; if you want to include from A - see &#039;&#039;&#039;^&#039;&#039;&#039; - to B, A should be older than B. We will use another approach for cherry-picking multiple commits.&lt;br /&gt;
&lt;br /&gt;
=== Applying a set of patches ===&lt;br /&gt;
&lt;br /&gt;
If the branch MDL-xxxx-topic_21_STABLE from the previous example consists of several commits, it may be easier to use git-format-patch and git-am combo to re-apply the whole set of patches (aka patchset). Firstly you will export all commits from the topic branch to files.&lt;br /&gt;
&lt;br /&gt;
    cd ~/public_html/moodle21&lt;br /&gt;
    mkdir .patches&lt;br /&gt;
    git format-patch -o .patches MOODLE_21_STABLE..MDL-xxxx-topic_21_STABLE         (1)&lt;br /&gt;
&lt;br /&gt;
The command (1) takes all commits from the topic branch that are not in MOODLE_21_STABLE and exports them one by one to the output directory .patches. Look at the generated files. They contain the patch itself (in diff format) and additional information about the commit. You could eg send these files by email to a friend of yours for peer-review. We will use them in another repository.&lt;br /&gt;
&lt;br /&gt;
    cd ~/public_html/moodledev&lt;br /&gt;
    git checkout -b MDL-xxxx-topic origin/master&lt;br /&gt;
    git am -3 ../moodle21/.patches/*                        (1)&lt;br /&gt;
&lt;br /&gt;
The command (1) applies all the files from the .patches directory. When a patch does not apply cleanly, the command tries fall back on 3-way merge (see the -3 parameter). If conflicts occur during the procedure, you can either deal with them and then use `git am --continue` or abort the whole procedure with `git am --abort`.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
; Moodle forum discussions&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=168094 GIT help needed]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=165236 Best way to manage CONTRIB code with GIT]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=167063 Handy Git tip for tracking 3rd-party modules and plugins]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=167730 Moodle Git repositories]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=183409 Git help!! I don&#039;t understand rebase enough...]&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=217617 add MOODLE_24_STABLE to github.com repository]&lt;br /&gt;
&lt;br /&gt;
; External resources &lt;br /&gt;
* [http://www.kernel.org/pub/software/scm/git/docs/everyday.html Everyday GIT With 20 Commands Or So]&lt;br /&gt;
* [http://gitref.org/ Git Reference]&lt;br /&gt;
* [http://progit.org/book/ Pro Git book]&lt;br /&gt;
* [http://vimeo.com/14629850 Getting git by Scott Chacon] - an recording of an excellent 1-hour presentation that introducing git, including a simple introduction to what is going on under the hood.&lt;br /&gt;
* [http://tjhunt.blogspot.co.uk/2012/03/fixing-bug-in-moodle-core-mechanics.html Tim Hunt&#039;s blog: Fixing a bug in Moodle core: the mechanics]&lt;br /&gt;
&lt;br /&gt;
[[Category:Git]]&lt;br /&gt;
&lt;br /&gt;
[[ja:開発者用Git]]&lt;/div&gt;</summary>
		<author><name>Gabrielros</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Messaging_2.0&amp;diff=51029</id>
		<title>Messaging 2.0</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Messaging_2.0&amp;diff=51029"/>
		<updated>2016-11-07T16:42:41Z</updated>

		<summary type="html">&lt;p&gt;Gabrielros: /* Adding new message type */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = Enhanced messaging configuration&lt;br /&gt;
|state = implemented, merged into repository&lt;br /&gt;
|tracker = MDL-27171&lt;br /&gt;
|discussion = http://moodle.org/mod/forum/discuss.php?d=172825&lt;br /&gt;
|assignee = [[User:kabalin|Ruslan Kabalin]]&lt;br /&gt;
}}&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
==Enhanced messaging system==&lt;br /&gt;
&lt;br /&gt;
The messaging system in 2.0 has been revamped significantly:&lt;br /&gt;
* it is now event-driven;&lt;br /&gt;
* it allows users to control exactly what messages they receive and how;&lt;br /&gt;
* it allows administrator to override user settings and set defaults.&lt;br /&gt;
&lt;br /&gt;
Messaging behaviour is controlled by the combination of administrator settings, that define which message outputs are enabled, which outputs can, cannot and should be used for which messages, and user settings that defines which messages user will receive (given that the admin permitted user to control them). The system works graciously when things are not fully configured. For example, jabber notifications can only be send if a Jabber server has been configured, and user has specified his jabber ID in messaging configuration.&lt;br /&gt;
&lt;br /&gt;
Messaging system is enabled by default and controlled via &#039;&#039;Site Administration &amp;gt; Advanced features &amp;gt; Enable messaging system&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Configuration for administrator==&lt;br /&gt;
&lt;br /&gt;
There is a dedicated menu item where administrator may configure messaging settings, it is located in &#039;&#039;Site Administration &amp;gt; Plugins -&amp;gt; Message outputs&#039;&#039; menu. The menu contains the items for managing messaging outputs, defining default outputs and items for configuring particular outputs like email or jabber.&lt;br /&gt;
&lt;br /&gt;
===Manage message outputs===&lt;br /&gt;
&lt;br /&gt;
This page summarises which messaging outputs (or processors) you have in the system. You may enable or disable a particular output and proceed to message output system configuration screen. The outputs that are not configured are highlighted and cannot be used in the system (they are not listed in messaging preferences configuration screens). Disabled outputs cannot be used in the system either.&lt;br /&gt;
&lt;br /&gt;
[[File:Manage message outputs.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
===Default message outputs===&lt;br /&gt;
&lt;br /&gt;
Default message outputs page is a grid of message outputs (processors) across the top row and message types (providers) across the left column. The intersection cell of particular output and type contains default preferences for chosen messaging type and output.&lt;br /&gt;
&lt;br /&gt;
[[File:Default message outputs.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
The default preferences menu for each item is identical and allow administrator to choose permission and default setting when user is logged-in and offline. The possible preferences are:&lt;br /&gt;
* &#039;&#039;&#039;Disallowed&#039;&#039;&#039; - the message of chosen type will never be delivered through the chosen output, user is not allowed to change the personal preference for this combination of message type and output.&lt;br /&gt;
* &#039;&#039;&#039;Permitted&#039;&#039;&#039; - the message of chosen type is allowed to be delivered through the chosen output, default preferences can be set by administrator using the checkboxes below, user can control this preference on the messaging preferences page (and change the suggested defaults the most preferable way).&lt;br /&gt;
* &#039;&#039;&#039;Forced&#039;&#039;&#039; - the message of chosen type will be delivered through the chosen output, user is not allowed to change the personal preference for this combination of message type and output.&lt;br /&gt;
&lt;br /&gt;
===Outputs configuration===&lt;br /&gt;
&lt;br /&gt;
As it was mentioned earlier, the &#039;&#039;Message outputs&#039;&#039; menu contains the configuration for outputs that have system configuration settings. Unless output is configured, it cannot be used in the system. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Former settings &#039;&#039;Admin &amp;gt; Server &amp;gt; Email&#039;&#039; and &#039;&#039;Admin -&amp;gt; Server -&amp;gt; Jabber&#039;&#039; have been moved to &#039;&#039;Site Administration &amp;gt; Plugins -&amp;gt; Message outputs&#039;&#039;. Settings &amp;lt;tt&amp;gt;upportname&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;supportemail&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;supportpage&amp;lt;/tt&amp;gt; that were on Email settings page were moved to &#039;&#039;Site Administration &amp;gt; Server -&amp;gt; Support contact&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==Configuration for user==&lt;br /&gt;
&lt;br /&gt;
Users may configure the messaging preferences in their profile settings &#039;&#039;My Profile settings &amp;gt; Messaging&#039;&#039;. The message preferences are configured in &amp;quot;Configure destinations for incoming messages&amp;quot; box that contain a grid of enabled and configured message outputs and message types user has capabilities to access. If particular combination of message type and output is permitted by administrator, user may change the preferences by ticking off the corresponding boxes.&lt;br /&gt;
&lt;br /&gt;
[[File:User message preferences.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Some message outputs may require user configuration (e.g. jabber needs ID to be specified), in which case user will not able to set the preferences for the output unless it is configured on the user level. Message output settings are listed at the bottom of messaging preferences page.&lt;br /&gt;
&lt;br /&gt;
[[File:User message preferences settings.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
==Under the bonnet==&lt;br /&gt;
&lt;br /&gt;
===Capabilities===&lt;br /&gt;
&lt;br /&gt;
In order to configure messaging settings in the site administration menu admin requires &amp;lt;tt&amp;gt;moodle/site:config&amp;lt;/tt&amp;gt; permission. User is able to configure personal messaging preferences if &amp;lt;tt&amp;gt;moodle/user:editownmessageprofile&amp;lt;/tt&amp;gt; is granted.&lt;br /&gt;
&lt;br /&gt;
===Message types (providers)===&lt;br /&gt;
&lt;br /&gt;
Any plugin can declare any number of message types which can be used on [[Messaging_2.0_improvements#Default_message_outputs|Default message preferences]] and [[Messaging_2.0_improvements#Configuration_for_user|user messaging preferences]] pages. When the particular message type is being [[Messaging_2.0_improvements#Message_dispatching|dispatched]], the delivery method will be chosen based on messaging permissions and preferences defined by admin and user.&lt;br /&gt;
&lt;br /&gt;
====Adding new message type====&lt;br /&gt;
&lt;br /&gt;
Message types for the plugins are declared in &#039;&#039;db/messages.php&#039;&#039; in plugin directory (or in &#039;&#039;lib/db/messages.php&#039;&#039; for the core components). This file contains an array of message types. Each type is presented as array with optional parameters:&lt;br /&gt;
*&#039;&#039;capability&#039;&#039; that user require to receive the message dispatch by this component (plugin);&lt;br /&gt;
*&#039;&#039;defaults&#039;&#039; optional default settings for some message output.&lt;br /&gt;
&lt;br /&gt;
The file is processed during plugin installation and upgrade. The message type along with capability is stored in &#039;&#039;message_providers&#039;&#039; table.&lt;br /&gt;
&lt;br /&gt;
For example (&#039;&#039;[http://git.moodle.org/gw?p=moodle.git;a=blob;f=mod/quiz/db/messages.php;hb=HEAD mod/quiz/db/messages.php]&#039;&#039;):&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$messageproviders = array (&lt;br /&gt;
    &lt;br /&gt;
    // notify teacher that a student has submitted a quiz attempt&lt;br /&gt;
    &#039;submission&#039; =&amp;gt; array (&lt;br /&gt;
        &#039;capability&#039;  =&amp;gt; &#039;mod/quiz:emailnotifysubmission&#039;&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
    // confirm a student&#039;s quiz attempt&lt;br /&gt;
    &#039;confirmation&#039; =&amp;gt; array (&lt;br /&gt;
        &#039;capability&#039;  =&amp;gt; &#039;mod/quiz:emailconfirmsubmission&#039;&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The snippet above will create two message types: submission and confirmation. In the database these records will look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
id	name	        component	capability&lt;br /&gt;
12	submission	mod_quiz	mod/quiz:emailnotifysubmission&lt;br /&gt;
13	confirmation	mod_quiz	mod/quiz:emailconfirmsubmission&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once the provider has been added to the database, it become visible on [[Messaging_2.0_improvements#Default_message_outputs|Default message preferences]] admin interface and, if permitted based on capabilities, on [[Messaging_2.0_improvements#Configuration_for_user|User messaging preferences]] page.&lt;br /&gt;
&lt;br /&gt;
As it was mentioned above, it is also possible to set default message outputs settings in &#039;&#039;messages.php&#039;&#039; file. The optional &#039;&#039;default&#039;&#039; setting contains an array of message output names with the default settings. These settings define permission and defaults for online and offline states. The possible settings are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; | Type &lt;br /&gt;
! scope=&amp;quot;col&amp;quot; | Constants &lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; style=&amp;quot;text-align:left;&amp;quot; | Permissions&lt;br /&gt;
| |MESSAGE_DISALLOWED | MESSAGE_PERMITTED | MESSAGE_FORCED &lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; style=&amp;quot;text-align:left;&amp;quot; | Defaults for loggedin state&lt;br /&gt;
| MESSAGE_DEFAULT_LOGGEDIN&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; style=&amp;quot;text-align:left;&amp;quot; | Defaults for loggedoff state&lt;br /&gt;
| MESSAGE_DEFAULT_LOGGEDOFF&lt;br /&gt;
|}&lt;br /&gt;
Using the combination of the settings above the permission and/or defaults can be defined in the &#039;&#039;messages.php&#039;&#039; file, e.g.:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$messageproviders = array (&lt;br /&gt;
    &lt;br /&gt;
/// Ordinary single forum posts&lt;br /&gt;
    &#039;assignment_updates&#039; =&amp;gt; array (&lt;br /&gt;
        &#039;defaults&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;popup&#039; =&amp;gt; MESSAGE_PERMITTED + MESSAGE_DEFAULT_LOGGEDIN,&lt;br /&gt;
            &#039;email&#039; =&amp;gt; MESSAGE_FORCED,&lt;br /&gt;
        ),&lt;br /&gt;
    ),&lt;br /&gt;
    &lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Only one of &#039;&#039;&#039;Permissions&#039;&#039;&#039; constants should be used for single setting (e.g. &amp;lt;tt&amp;gt;&#039;popup&#039; =&amp;gt; MESSAGE_PERMITTED + MESSAGE_DISALLOWED&amp;lt;/tt&amp;gt; is invalid will result in having the suggested default setting for &#039;&#039;popup&#039;&#039; output ignored completely). The above snippet will set [[Messaging_2.0_improvements#Default_message_outputs|default message preferences]] to:&lt;br /&gt;
&lt;br /&gt;
[[File:Default message outputs preset example.jpg]]&lt;br /&gt;
&lt;br /&gt;
For those processors that are not listed in &#039;&#039;defaults&#039;&#039; array (like &#039;&#039;jabber&#039;&#039; in the code example above) or if plugin do not have defaults setting at all, or if default setting is invalid, the following defaults are set automatically:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&#039;email&#039; =&amp;gt; MESSAGE_PERMITTED + MESSAGE_DEFAULT_LOGGEDIN + MESSAGE_DEFAULT_LOGGEDOFF;&lt;br /&gt;
&#039;anyotheroutput&#039; =&amp;gt; MESSAGE_PERMITTED;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Message provider name====&lt;br /&gt;
&lt;br /&gt;
The message provider should have a name defined in the corresponding language file. The string should have a key of the format &#039;&#039;messageprovider:&#039;&#039;&#039;provider_name&#039;&#039;&#039;&#039;&#039;, e.g.&lt;br /&gt;
(&#039;&#039;[http://git.moodle.org/gw?p=moodle.git;a=blob;f=mod/quiz/lang/en/quiz.php;hb=HEAD mod/quiz/lang/en/quiz.php]&#039;&#039;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;messageprovider:confirmation&#039;] = &#039;Confirmation of your own quiz submissions&#039;;&lt;br /&gt;
$string[&#039;messageprovider:submission&#039;] = &#039;Notification of quiz submissions&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Message outputs (processors)===&lt;br /&gt;
&lt;br /&gt;
Each message output is presented as a plugin (see [http://git.moodle.org/gw?p=moodle.git;a=tree;f=message/output;hb=HEAD /message/output]). The outputs for email, jabber and web-based popups already exist. A new plugin for different messaging delivery method (e.g. twitter or SMS) can be added quite easily.&lt;br /&gt;
&lt;br /&gt;
The typical message output plugin directory looks like:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
message/output/jabber/&lt;br /&gt;
├── db&lt;br /&gt;
│   ├── install.php&lt;br /&gt;
│   └── upgrade.php&lt;br /&gt;
├── lang&lt;br /&gt;
│   └── en&lt;br /&gt;
│       └── message_jabber.php&lt;br /&gt;
├── lib.php&lt;br /&gt;
├── message_output_jabber.php&lt;br /&gt;
├── settings.php&lt;br /&gt;
└── version.php&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====message_output class====&lt;br /&gt;
&lt;br /&gt;
The plugin should contain &#039;&#039;message_output_&#039;&#039;&#039;name&#039;&#039;&#039;.php file&#039;&#039; (e.g. [http://git.moodle.org/gw?p=moodle.git;a=blob;f=message/output/jabber/message_output_jabber.php;hb=HEAD /message/output/jabber/message_output_jabber.php]) with &#039;&#039;message_output_&#039;&#039;&#039;name&#039;&#039;&#039;&#039;&#039; class (where &#039;&#039;&#039;name&#039;&#039;&#039; is the actual plugin name) that extends an abstract class called &#039;&#039;message_output&#039;&#039; in [http://git.moodle.org/gw?p=moodle.git;a=blob;f=message/output/lib.php;hb=HEAD /message/output/lib.php] with the methods:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
class message_output_name extends message_output {&lt;br /&gt;
&lt;br /&gt;
    public function send_message($message) {&lt;br /&gt;
       // Given a message object and user info, this actually&lt;br /&gt;
       // sends it. This function is called by send_message&lt;br /&gt;
       // function in lib/messagelib.php&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function config_form($preferences) {&lt;br /&gt;
       // This defines the config form fragment used on user&lt;br /&gt;
       // messaging preferences interface (message/edit.php)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function process_form($form, &amp;amp;$preferences) {&lt;br /&gt;
       // This processes the data from the config form fragment&lt;br /&gt;
       // (used in message/edit.php)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function load_data(&amp;amp;$preferences, $userid) {&lt;br /&gt;
       // This loads up user config for this plugin set via&lt;br /&gt;
       // config form fragment (used in message/edit.php)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function is_system_configured() {&lt;br /&gt;
       // This is an optional method that is supposed to return&lt;br /&gt;
       // true if output is configured on the system level&lt;br /&gt;
       // for example jabber server settings for jabber plugin.&lt;br /&gt;
       // Available as of Moodle 2.1&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function is_user_configured($user = null) {&lt;br /&gt;
       // This is an optional method that is supposed to return&lt;br /&gt;
       // true if output is configured on the user level&lt;br /&gt;
       // for example user&#039;s jabber ID for jabber plugin.&lt;br /&gt;
       // $user parameter defaults to $USER global&lt;br /&gt;
       // Available as of Moodle 2.1&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function get_default_messaging_settings() {&lt;br /&gt;
        // Allows you to specify what the default message&lt;br /&gt;
        // settings should be for this output, in case&lt;br /&gt;
        // the message provider supplying the message&lt;br /&gt;
        // has not specified them in its messages.php file&lt;br /&gt;
        // Available as of Moodle 2.1&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Settings file====&lt;br /&gt;
&lt;br /&gt;
If messaging output plugin requires system configuration, it should provide &#039;&#039;settings.php&#039;&#039; file with configuration settings. The link to configuration page will be displayed as a part of admin menu tree (in &#039;&#039;Site Administration &amp;gt; Plugins -&amp;gt; Message outputs&#039;&#039;) and in the [[Messaging_2.0_improvements#Manage_message_outputs|Manage message outputs]] page. See [[Admin_settings#Individual_settings|Admin_settings]] for more details.&lt;br /&gt;
&lt;br /&gt;
====Lanuage file====&lt;br /&gt;
&lt;br /&gt;
The plugin should have a &#039;&#039;message_&#039;&#039;&#039;name&#039;&#039;&#039;.php&#039;&#039; file (where &#039;&#039;&#039;name&#039;&#039;&#039; is the actual plugin name) in the correct language directory structure with at least one &#039;&#039;pluginname&#039;&#039; string with the name of the processor, e.g.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;pluginname&#039;] = &#039;Jabber message&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Installation and Upgrade====&lt;br /&gt;
&lt;br /&gt;
Like in any other moodle plugin, the message processor plugin should have install and upgrade routines defined in &#039;&#039;install.php&#039;&#039; and &#039;&#039;upgrade.php&#039;&#039; respectively. At the very list the plugin should register itself in &#039;&#039;message_processors&#039;&#039; table which will make it listed on messaging configuration pages. The example content of &#039;&#039;install.php&#039;&#039; file for jabber messaging processor is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function xmldb_message_jabber_install(){&lt;br /&gt;
    global $DB;&lt;br /&gt;
&lt;br /&gt;
    $result = true;&lt;br /&gt;
&lt;br /&gt;
    $provider = new stdClass();&lt;br /&gt;
    $provider-&amp;gt;name  = &#039;jabber&#039;;&lt;br /&gt;
    $DB-&amp;gt;insert_record(&#039;message_processors&#039;, $provider);&lt;br /&gt;
    return $result;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also the plugin should contain the &#039;&#039;version.php&#039;&#039; file. e.g.:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$plugin-&amp;gt;version  = 2008090900;&lt;br /&gt;
$plugin-&amp;gt;requires = 2008091500;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Message dispatching===&lt;br /&gt;
Messages are dispatched by calling /lib/messagelib.php message_send -method which returns the message ID or false for errors:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$eventdata = new object();&lt;br /&gt;
$eventdata-&amp;gt;component         = &#039;mod_forum&#039;;    // the component sending the message. Along with name this must exist in the table message_providers&lt;br /&gt;
$eventdata-&amp;gt;name              = &#039;posts&#039;;        // type of message from that module (as module defines it). Along with component this must exist in the table message_providers&lt;br /&gt;
$eventdata-&amp;gt;userfrom          = $userfrom;      // user object&lt;br /&gt;
$eventdata-&amp;gt;userto            = $userto;        // user object&lt;br /&gt;
$eventdata-&amp;gt;subject           = $postsubject;   // very short one-line subject&lt;br /&gt;
$eventdata-&amp;gt;fullmessage       = $posttext;      // raw text&lt;br /&gt;
$eventdata-&amp;gt;fullmessageformat = FORMAT_PLAIN;   // text format&lt;br /&gt;
$eventdata-&amp;gt;fullmessagehtml   = $posthtml;      // html rendered version&lt;br /&gt;
$eventdata-&amp;gt;smallmessage      = &#039;&#039;;             // useful for plugins like sms or twitter&lt;br /&gt;
&lt;br /&gt;
$result = message_send($eventdata);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The name of each provider is a string with a name like &#039;&#039;messageprovider:&#039;&#039;&#039;name&#039;&#039;&#039;&#039;&#039; from the component lang file (in this case, forum.php is derived automatically from mod/forum):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$string[&#039;messageprovider:posts&#039;] = &#039;Subscribed forum posts&#039;;&lt;br /&gt;
$string[&#039;messageprovider:digests&#039;] = &#039;Subscribed forum digests&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More providers can be added throughout Moodle as necessary, it&#039;s quite easy.  See the [[Events|Events API]] for info.&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [[Messaging_consumers|Messaging Consumer Plugins]]&lt;br /&gt;
* [[:en:GSOC/2008]]&lt;br /&gt;
* [[Events|Events API]]&lt;br /&gt;
* MDL-10107&lt;br /&gt;
* MDL-27171 / [https://moodle.org/mod/forum/discuss.php?d=172825 forum thread about some changes that were made to the messaging system]&lt;br /&gt;
&lt;br /&gt;
[[Category:Messaging]]&lt;/div&gt;</summary>
		<author><name>Gabrielros</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Local_plugins&amp;diff=49705</id>
		<title>Local plugins</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Local_plugins&amp;diff=49705"/>
		<updated>2016-03-18T11:01:41Z</updated>

		<summary type="html">&lt;p&gt;Gabrielros: little fix of core deprecated extension function name&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = Local customisations&lt;br /&gt;
|state = Implemented&lt;br /&gt;
|tracker = MDL-17376, MDL-16438&lt;br /&gt;
|discussion = http://moodle.org/mod/forum/discuss.php?d=126017 http://moodle.org/mod/forum/discuss.php?d=86903&lt;br /&gt;
|assignee = [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]], some parts were originally proposed and implemented in 1.9 by Penny Leach&lt;br /&gt;
}}&lt;br /&gt;
{{Moodle 2.0}}&lt;br /&gt;
&lt;br /&gt;
The recommended way to add new functionality to Moodle is to create a new standard plugin (module, block, auth, enrol, etc.).The /local/ plugins are mostly suitable for things that do not fit standard plugins.&lt;br /&gt;
&lt;br /&gt;
== Custom /local/ plugins ==&lt;br /&gt;
&lt;br /&gt;
Local plugins are used in cases when no standard plugin fits, examples are:&lt;br /&gt;
* event consumers communicating with external systems&lt;br /&gt;
* custom definitions of web services and external functions&lt;br /&gt;
* applications that extend moodle at the system level (hub server, amos server, etc.)&lt;br /&gt;
* new database tables used in core hacks (discouraged)&lt;br /&gt;
* new capability definitions used in core hacks&lt;br /&gt;
* custom admin settings&lt;br /&gt;
* extending the navigation block with custom menus [http://moodle.org/mod/forum/discuss.php?d=170325&amp;amp;parent=753095]&lt;br /&gt;
&lt;br /&gt;
=== Standard plugin features: ===&lt;br /&gt;
* /local/xxx/[[version.php]] - version of script (must be incremented after changes)&lt;br /&gt;
* /local/xxx/db/install.xml - executed during install (new version.php found)&lt;br /&gt;
* /local/xxx/db/install.php - executed right after install.xml&lt;br /&gt;
* /local/xxx/db/uninstall.php - executed during uninstallation&lt;br /&gt;
* /local/xxx/db/upgrade.php - executed after version.php change&lt;br /&gt;
* /local/xxx/db/access.php - definition of capabilities&lt;br /&gt;
* /local/xxx/db/events.php - event handlers and subscripts&lt;br /&gt;
* /local/xxx/db/messages.php - messaging registration&lt;br /&gt;
* /local/xxx/db/external.php - web services and external functions descriptions&lt;br /&gt;
* /local/xxx/cron.php - cron job, run at the interval defined in version.php. Alternatively, you can define &amp;lt;tt&amp;gt;local_xxx_cron()&amp;lt;/tt&amp;gt; in lib.php. (The lib.php method is now preferred.)&lt;br /&gt;
* /local/xxx/lang/en/local_pluginname.php - language file&lt;br /&gt;
* /local/xxx/lib.php - function library, automatically included with by config.php.  Hook functions local_pluginname_extend_navigation() and local_pluginname_extend_settings_navigation() can be used to add items to the navigation and settings blocks&lt;br /&gt;
* /local/xxx/settings.php - configuration options. These get added to the admin menu.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;xxx&#039;&#039; is used instead of your local plugin name, plugins of the same type are installed/upgraded in alphabetical order.&lt;br /&gt;
&lt;br /&gt;
=== List of differences from normal plugins: ===&lt;br /&gt;
* always executed last during install/upgrade - guaranteed by order of plugins in &amp;lt;code&amp;gt;get_plugin_types()&amp;lt;/code&amp;gt;&lt;br /&gt;
* are expected to use event handlers - events are intended for communication core--&amp;gt;plugins only, local plugins are the best candidates for event handlers&lt;br /&gt;
* can add admin settings to any settings page - loaded last when constructing admin tree&lt;br /&gt;
* do not need to have any UI - other plugins are usually visible somewhere&lt;br /&gt;
* some extra hooks (not implemented yet)&lt;br /&gt;
&lt;br /&gt;
== /local/xxx/db/messages.php ==&lt;br /&gt;
Example File Structure:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Defines message providers (types of messages being sent)&lt;br /&gt;
 *&lt;br /&gt;
 * @package mod-forum&lt;br /&gt;
 * @copyright  1999 onwards  Martin Dougiamas  http://moodle.com&lt;br /&gt;
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
$messageproviders = array (&lt;br /&gt;
&lt;br /&gt;
/// Ordinary single forum posts&lt;br /&gt;
    &#039;posts&#039; =&amp;gt; array (&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Other /local/ customisation files== &lt;br /&gt;
&lt;br /&gt;
===Customised site defaults=== &lt;br /&gt;
&lt;br /&gt;
Different default site settings can be stored in file /local/defaults.php.&lt;br /&gt;
These new defaults are used during installation, upgrade and later are&lt;br /&gt;
displayed as default values in admin settings. This means that the content&lt;br /&gt;
of the defaults files is usually updated BEFORE installation or upgrade.&lt;br /&gt;
&lt;br /&gt;
These customised defaults are useful especially when using CLI tools&lt;br /&gt;
for installation and upgrade.&lt;br /&gt;
&lt;br /&gt;
Sample /local/defaults.php file content:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
$defaults[&#039;moodle&#039;][&#039;forcelogin&#039;] = 1;  // new default for $CFG-&amp;gt;forcelogin&lt;br /&gt;
$defaults[&#039;scorm&#039;][&#039;maxgrade&#039;] = 20;    // default for get_config(&#039;scorm&#039;, &#039;maxgrade&#039;)&lt;br /&gt;
$defaults[&#039;moodlecourse&#039;][&#039;numsections&#039;] = 11;&lt;br /&gt;
$defaults[&#039;moodle&#039;][&#039;hiddenuserfields&#039;] = array(&#039;city&#039;, &#039;country&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
First bracket contains string from column plugin of config_plugins table.&lt;br /&gt;
Second bracket is the name of setting. In the admin settings UI the plugin and&lt;br /&gt;
name of setting is separated by &amp;quot;|&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The values usually correspond to the raw string in config table, with the exception&lt;br /&gt;
of comma separated lists that are usually entered as real arrays.&lt;br /&gt;
&lt;br /&gt;
Please note that not all settings are converted to admin_tree,&lt;br /&gt;
they are mostly intended to be set directly in config.php.&lt;br /&gt;
&lt;br /&gt;
=== 2.0 pre-upgrade script===&lt;br /&gt;
&lt;br /&gt;
You can use /local/upgrade_pre20.php script for any code that needs to&lt;br /&gt;
be executed before the main upgrade to 2.0. Most probably this will&lt;br /&gt;
be used for undoing of old hacks that would otherwise break normal&lt;br /&gt;
2.0 upgrade.&lt;br /&gt;
&lt;br /&gt;
This file is just included directly, there does not need to be any&lt;br /&gt;
function inside. If the execution stops the script is executed again&lt;br /&gt;
during the next upgrade. The first execution of lib/db/upgrade.php&lt;br /&gt;
increments the version number and the pre upgrade script is not&lt;br /&gt;
executed any more.&lt;br /&gt;
&lt;br /&gt;
== Customisations outside of /local/ directory== &lt;br /&gt;
&lt;br /&gt;
=== Forced settings=== &lt;br /&gt;
&lt;br /&gt;
Sometimes it is useful to force some settings and prevent any changes of these settings via the standard admin UI. It is possible to hardcode these settings in config.php.&lt;br /&gt;
&lt;br /&gt;
In case of course settings it is very simply, the values are assigned directly to $CFG properties. In case of plugins the values are specified in a multidimensional array in $CFG-&amp;gt;force_plugin_settings.&lt;br /&gt;
&lt;br /&gt;
Sample code in config.php&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$CFG-&amp;gt;allowobjectembed = 0;&lt;br /&gt;
$CFG-&amp;gt;forced_plugin_settings = array(&#039;page&#039;=&amp;gt;array(&#039;displayoptions&#039;=&amp;gt;5, &#039;requiremodintro&#039;=&amp;gt;1), &#039;folder&#039;=&amp;gt;array(&#039;requiremodintro&#039;=&amp;gt;1));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Local language customisations=== &lt;br /&gt;
&lt;br /&gt;
Moodle supports other type of local customisation of standard language&lt;br /&gt;
packs. If you want to create your own language pack based on another&lt;br /&gt;
language create new dataroot directory with &amp;quot;_local&amp;quot; suffix, for example&lt;br /&gt;
following file with content changes string &amp;quot;Login&amp;quot; to &amp;quot;Sign in&amp;quot;:&lt;br /&gt;
moodledata/lang/en_local&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
  $string[&#039;login&#039;] = &#039;Sign in&#039;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
See also https://docs.moodle.org/en/Language_editing&lt;br /&gt;
&lt;br /&gt;
=== Custom script injection=== &lt;br /&gt;
&lt;br /&gt;
Very old customisation option that allows you to modify scripts by injecting&lt;br /&gt;
code right after the require &#039;config.php&#039; call.&lt;br /&gt;
&lt;br /&gt;
This setting is enabled by manually setting $CFG-&amp;gt;customscripts variable&lt;br /&gt;
in config.php script. The value is expected to be full path to directory&lt;br /&gt;
with the same structure as dirroot. Please note this hack only affects&lt;br /&gt;
files that actually include the config.php!&lt;br /&gt;
&lt;br /&gt;
; Examples:&lt;br /&gt;
* disable one specific moodle page without code modification&lt;br /&gt;
* alter page parameters on the fly&lt;br /&gt;
&lt;br /&gt;
=== Direct code modifications=== &lt;br /&gt;
This is usually the last resort, if possible do not do it. And if you still do it use some version control system (preferably git).&lt;br /&gt;
&lt;br /&gt;
=== Direct database modifications=== &lt;br /&gt;
Very strongly discouraged! Sometimes field lengths may be modified without side effects. Adding or removing of db fields will most probably cause major problems during future upgrades. New database tables should be added only from plugins.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
=== Adding an element to the settings menu ===&lt;br /&gt;
&lt;br /&gt;
In local/*pluginname*/lib.php, define a function named local_*pluginname*_extend_settings_navigation, this will get called when Moodle builds the settings block.&lt;br /&gt;
This example adds a link to the bottom of the course administration section of the settings block.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function local_myplugin_extend_settings_navigation($settingsnav, $context) {&lt;br /&gt;
    global $CFG, $PAGE;&lt;br /&gt;
&lt;br /&gt;
    // Only add this settings item on non-site course pages.&lt;br /&gt;
    if (!$PAGE-&amp;gt;course or $PAGE-&amp;gt;course-&amp;gt;id == 1) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Only let users with the appropriate capability see this settings item.&lt;br /&gt;
    if (!has_capability(&#039;moodle/backup:backupcourse&#039;, context_course::instance($PAGE-&amp;gt;course-&amp;gt;id))) {&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($settingnode = $settingsnav-&amp;gt;find(&#039;courseadmin&#039;, navigation_node::TYPE_COURSE)) {&lt;br /&gt;
        $strfoo = get_string(&#039;foo&#039;, &#039;local_myplugin&#039;);&lt;br /&gt;
        $url = new moodle_url(&#039;/local/myplugin/foo.php&#039;, array(&#039;id&#039; =&amp;gt; $PAGE-&amp;gt;course-&amp;gt;id));&lt;br /&gt;
        $foonode = navigation_node::create(&lt;br /&gt;
            $strfoo,&lt;br /&gt;
            $url,&lt;br /&gt;
            navigation_node::NODETYPE_LEAF,&lt;br /&gt;
            &#039;myplugin&#039;,&lt;br /&gt;
            &#039;myplugin&#039;,&lt;br /&gt;
            new pix_icon(&#039;t/addcontact&#039;, $strfoo)&lt;br /&gt;
        );&lt;br /&gt;
        if ($PAGE-&amp;gt;url-&amp;gt;compare($url, URL_MATCH_BASE)) {&lt;br /&gt;
            $foonode-&amp;gt;make_active();&lt;br /&gt;
        }&lt;br /&gt;
        $settingnode-&amp;gt;add_node($foonode);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Removing the &amp;quot;Site Home&amp;quot; link from the navigation menu ===&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
function local_xxx_extend_navigation(global_navigation $navigation) {&lt;br /&gt;
    if ($home = $navigation-&amp;gt;find(&#039;home&#039;, global_navigation::TYPE_SETTING)) {&lt;br /&gt;
        $home-&amp;gt;remove();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Local customisations in previous versions ==&lt;br /&gt;
Previous versions include only partial support for customisations in /local/ directory.&lt;br /&gt;
&lt;br /&gt;
=== List of local customisations in 1.9.x: ===&lt;br /&gt;
* /local/cron.php - custom cron jobs&lt;br /&gt;
* /local/settings.php - custom admin settings&lt;br /&gt;
* /local/db/upgrade.php - general modifications&lt;br /&gt;
* /local/lang/* - custom strings&lt;br /&gt;
* /local/lib.php - local_delete_course()&lt;br /&gt;
&lt;br /&gt;
=== Migration from old 1.9.x /local/: ===&lt;br /&gt;
* &amp;lt;code&amp;gt;local/*&amp;lt;/code&amp;gt; needs to be copied to new directory&lt;br /&gt;
* &amp;lt;code&amp;gt;local/xxxx/db/install.php&amp;lt;/code&amp;gt; is intended for first installation, originally everything was in upgrade.php&lt;br /&gt;
* events are used instead of hooks&lt;br /&gt;
* upgrade code needs to migrate old settings, events, etc. directly in core db tables - such as change component strings and capability names from db/install.php or manually before/after upgrade&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=170325&amp;amp;parent=753095 Extending navigation block]&lt;br /&gt;
* Using Moodle [http://moodle.org/mod/forum/discuss.php?d=86903 Local Customisations] forum discussion&lt;br /&gt;
* http://cvs.moodle.org/moodle/local/readme.txt?view=markup&lt;br /&gt;
* [[Local customisation (Moodle 1.9)]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Gabrielros</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_xhprof_on_Moodle&amp;diff=47376</id>
		<title>Setting up xhprof on Moodle</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_xhprof_on_Moodle&amp;diff=47376"/>
		<updated>2015-02-16T14:19:05Z</updated>

		<summary type="html">&lt;p&gt;Gabrielros: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The following instructions are for setting up xhprof for Moodle under a Ubuntu/Debian environment. The process should be similar for other linux enviroments, but will need some tweaking if you wish to do this under windows. Please update this document if you find any major problems.&lt;br /&gt;
&lt;br /&gt;
==Installing xhprof with Linux==&lt;br /&gt;
&lt;br /&gt;
===Debian/Ubuntu package===&lt;br /&gt;
 apt-get install php5-xhprof&lt;br /&gt;
The current LTS Ubuntu package is version 0.9.4-1build1&lt;br /&gt;
&lt;br /&gt;
===Build manually===&lt;br /&gt;
&amp;lt;code bash&amp;gt;&lt;br /&gt;
mkdir ~/src/&lt;br /&gt;
cd ~/src/&lt;br /&gt;
wget http://pecl.php.net/get/xhprof-0.9.2.tgz&lt;br /&gt;
tar xvf xhprof-0.9.2.tgz&lt;br /&gt;
cd xhprof-0.9.2/extension/&lt;br /&gt;
phpize&lt;br /&gt;
./configure&lt;br /&gt;
make&lt;br /&gt;
sudo make install&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: The version downloaded via these instructions is not compatible with PHP 5.4 - instead you should download the latest version of the code from https://github.com/facebook/xhprof (before following the instructions from &#039;cd xhprof-0.9.2/extension/&#039; onwards). &lt;br /&gt;
&lt;br /&gt;
Note: It is available now, the 0.9.3 version from the pecl website. You can run wget http://pecl.php.net/get/xhprof-0.9.3.tgz, if you have PHP 5.4 version.&lt;br /&gt;
&lt;br /&gt;
Add the following to the apache version of you php.ini file&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code ini&amp;gt;&lt;br /&gt;
[xhprof]&lt;br /&gt;
extension=xhprof.so&lt;br /&gt;
xhprof.output_dir=&amp;quot;/var/tmp/xhprof&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Restart Apache&lt;br /&gt;
&amp;lt;code bash&amp;gt;&lt;br /&gt;
sudo service apache2 restart&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a file in your web root that makes a call to phpinfo(); and then view the result in your browser to make sure that xhprof is enabled in PHP. Checking the output of &#039;&#039;&#039;php -m&#039;&#039;&#039; would also work if you are sure that the command line version of PHP uses the same php.ini file as your web server.&lt;br /&gt;
&lt;br /&gt;
===Troubleshooting===&lt;br /&gt;
If you see a &#039;&#039;&#039;failed to shell execute cmd=&amp;quot; dot -Tpng&#039;&#039;&#039; error when you follow the &#039;&#039;&#039;View Full Callgraph&#039;&#039;&#039; link you may need to install graphviz (&#039;&#039;&#039;sudo apt-get install graphviz&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Into Windows environment this error can be caused by a path hardcoded into &amp;quot;\lib\xhprof\xhprof_lib\utils\callgraph_utils.php&amp;quot;, you must replace one parameter of the proc_open function which is a Linux path &amp;quot;/tmp&amp;quot; by a Windows one, like &amp;quot;c:/temp&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Installing xhprof with Windows==&lt;br /&gt;
&lt;br /&gt;
You will need to download PHP extensions compiled for your version of PHP. [http://dev.freshsite.pl/php-extensions/xhprof.html Here is one source...]&lt;br /&gt;
&lt;br /&gt;
Extract the contained dll file to the ext directory of your server. With XAMPP this is in xampp\php\ext&lt;br /&gt;
&lt;br /&gt;
Add a line to your php.ini file that matches dll filename you are using. This goes in the Dynamic Extensions section.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
extension=xhprof_0.10.3_php54_vc9.dll&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Stop and restart Apache through your server control interface. If it complains, you probably don&#039;t have the correct extension for your version of PHP, or the extension entry in your php.ini file doesn&#039;t match the dll file.&lt;br /&gt;
&lt;br /&gt;
To test that the extension is installed, log in to Moodle as an administrator and navigate to Administration &amp;gt; Site administration &amp;gt; Server &amp;gt; PHP info. Search for information about the xhprof extension. It should be present and enabled.&lt;br /&gt;
&lt;br /&gt;
==Configuring Moodle to use xhprof==&lt;br /&gt;
[[Image:profilingOption.png|thumb|left|The profiling option is displayed when the php xhprof extension is installed]]&lt;br /&gt;
[[Image:profilingOutput.png|thumb|right|Tabular profiling output produced by xhprof]]&lt;br /&gt;
[[Image:callgraph.png|thumb|right|An example call graph showing slow parts of the profiled run]]&lt;br /&gt;
Once the xhprof php extension is correctly installed you will find a new &amp;quot;Profiling&amp;quot; option available under Settings &amp;gt; Site administration &amp;gt; Development&lt;br /&gt;
&lt;br /&gt;
When you load the profiling settings page you are confronted with several options. In order to get xhprof up and running with minimal fuss you mearly need to check the &amp;quot;Enable profiling&amp;quot; box and set a path that you wish to be profiled. You can simply set this to a wildcard using the asterisk symbol (&#039;&#039;&#039;*&#039;&#039;&#039;) while you are testing profiling. Afterwards you can come back and set this to a more restrictive setting once you know profiling is working. Note the paths need to be specified relative to your Moodle directory and not the web root.&lt;br /&gt;
&lt;br /&gt;
After you have enabled profiling you should load some pages within the &amp;quot;Profile these&amp;quot; filter that you set in the step above. Once you have done these go to Settings &amp;gt; Site administration &amp;gt; Development &amp;gt; Profiling runs and you should see a list of the pages you visited. Clicking on one of these and then clicking on the &amp;quot;View profiling details&amp;quot; will take you to a profiling table full of helpful stats for tracking down slow pages and functions. You can get an even more ineresting breakdown of this by then clicking on the &amp;quot;View Full Callgraph&amp;quot; link. This callgraph makes it easy to see where the slow parts of each particular run are and functions which individually may not take a long time to run but which are run thousands of times and thus resulting in a great deal of slowdown.&lt;br /&gt;
[[Image:profilingSettings.png|frame|center|Enabling profiling and setting it to run on all pages via a wildcard]]&lt;br /&gt;
[[Image:profilingRuns.png|frame|left|A profiling runs option can be seen after enabling profiling]]&lt;br /&gt;
&lt;br /&gt;
==Using XHProf==&lt;br /&gt;
&lt;br /&gt;
MDL-39443 shows the kind of thing that can be done using XHProf.&lt;br /&gt;
&lt;br /&gt;
[http://tjhunt.blogspot.co.uk/2013/05/performance-testing-moodle.html This blog post] talks about the process.&lt;br /&gt;
&lt;br /&gt;
Since Moodle 2.5.1 it&#039;s possible to export and import any profiling run. That enables some interesting uses like, comparisons along the time, between different systems and sharing or runs in other systems like the Tracker when optimization issues are being fixed.&lt;/div&gt;</summary>
		<author><name>Gabrielros</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_xhprof_on_Moodle&amp;diff=47375</id>
		<title>Setting up xhprof on Moodle</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_xhprof_on_Moodle&amp;diff=47375"/>
		<updated>2015-02-16T14:16:10Z</updated>

		<summary type="html">&lt;p&gt;Gabrielros: adding indication on Troubleshooting part for windows installs&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The following instructions are for setting up xhprof for Moodle under a Ubuntu/Debian environment. The process should be similar for other linux enviroments, but will need some tweaking if you wish to do this under windows. Please update this document if you find any major problems.&lt;br /&gt;
&lt;br /&gt;
==Installing xhprof with Linux==&lt;br /&gt;
&lt;br /&gt;
===Debian/Ubuntu package===&lt;br /&gt;
 apt-get install php5-xhprof&lt;br /&gt;
The current LTS Ubuntu package is version 0.9.4-1build1&lt;br /&gt;
&lt;br /&gt;
===Build manually===&lt;br /&gt;
&amp;lt;code bash&amp;gt;&lt;br /&gt;
mkdir ~/src/&lt;br /&gt;
cd ~/src/&lt;br /&gt;
wget http://pecl.php.net/get/xhprof-0.9.2.tgz&lt;br /&gt;
tar xvf xhprof-0.9.2.tgz&lt;br /&gt;
cd xhprof-0.9.2/extension/&lt;br /&gt;
phpize&lt;br /&gt;
./configure&lt;br /&gt;
make&lt;br /&gt;
sudo make install&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note: The version downloaded via these instructions is not compatible with PHP 5.4 - instead you should download the latest version of the code from https://github.com/facebook/xhprof (before following the instructions from &#039;cd xhprof-0.9.2/extension/&#039; onwards). &lt;br /&gt;
&lt;br /&gt;
Note: It is available now, the 0.9.3 version from the pecl website. You can run wget http://pecl.php.net/get/xhprof-0.9.3.tgz, if you have PHP 5.4 version.&lt;br /&gt;
&lt;br /&gt;
Add the following to the apache version of you php.ini file&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code ini&amp;gt;&lt;br /&gt;
[xhprof]&lt;br /&gt;
extension=xhprof.so&lt;br /&gt;
xhprof.output_dir=&amp;quot;/var/tmp/xhprof&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Restart Apache&lt;br /&gt;
&amp;lt;code bash&amp;gt;&lt;br /&gt;
sudo service apache2 restart&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Create a file in your web root that makes a call to phpinfo(); and then view the result in your browser to make sure that xhprof is enabled in PHP. Checking the output of &#039;&#039;&#039;php -m&#039;&#039;&#039; would also work if you are sure that the command line version of PHP uses the same php.ini file as your web server.&lt;br /&gt;
&lt;br /&gt;
===Troubleshooting===&lt;br /&gt;
If you see a &#039;&#039;&#039;failed to shell execute cmd=&amp;quot; dot -Tpng&#039;&#039;&#039; error when you follow the &#039;&#039;&#039;View Full Callgraph&#039;&#039;&#039; link you may need to install graphviz (&#039;&#039;&#039;sudo apt-get install graphviz&#039;&#039;&#039;).&lt;br /&gt;
Into Windows environnement this error can be caused by a path hardcoded into &amp;quot;\lib\xhprof\xhprof_lib\utils\callgraph_utils.php&amp;quot;, you must replace one parameter of the proc_open function which is a Linux path &amp;quot;/tmp&amp;quot; by a Windows one, like &amp;quot;c:/temp&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Installing xhprof with Windows==&lt;br /&gt;
&lt;br /&gt;
You will need to download PHP extensions compiled for your version of PHP. [http://dev.freshsite.pl/php-extensions/xhprof.html Here is one source...]&lt;br /&gt;
&lt;br /&gt;
Extract the contained dll file to the ext directory of your server. With XAMPP this is in xampp\php\ext&lt;br /&gt;
&lt;br /&gt;
Add a line to your php.ini file that matches dll filename you are using. This goes in the Dynamic Extensions section.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
extension=xhprof_0.10.3_php54_vc9.dll&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Stop and restart Apache through your server control interface. If it complains, you probably don&#039;t have the correct extension for your version of PHP, or the extension entry in your php.ini file doesn&#039;t match the dll file.&lt;br /&gt;
&lt;br /&gt;
To test that the extension is installed, log in to Moodle as an administrator and navigate to Administration &amp;gt; Site administration &amp;gt; Server &amp;gt; PHP info. Search for information about the xhprof extension. It should be present and enabled.&lt;br /&gt;
&lt;br /&gt;
==Configuring Moodle to use xhprof==&lt;br /&gt;
[[Image:profilingOption.png|thumb|left|The profiling option is displayed when the php xhprof extension is installed]]&lt;br /&gt;
[[Image:profilingOutput.png|thumb|right|Tabular profiling output produced by xhprof]]&lt;br /&gt;
[[Image:callgraph.png|thumb|right|An example call graph showing slow parts of the profiled run]]&lt;br /&gt;
Once the xhprof php extension is correctly installed you will find a new &amp;quot;Profiling&amp;quot; option available under Settings &amp;gt; Site administration &amp;gt; Development&lt;br /&gt;
&lt;br /&gt;
When you load the profiling settings page you are confronted with several options. In order to get xhprof up and running with minimal fuss you mearly need to check the &amp;quot;Enable profiling&amp;quot; box and set a path that you wish to be profiled. You can simply set this to a wildcard using the asterisk symbol (&#039;&#039;&#039;*&#039;&#039;&#039;) while you are testing profiling. Afterwards you can come back and set this to a more restrictive setting once you know profiling is working. Note the paths need to be specified relative to your Moodle directory and not the web root.&lt;br /&gt;
&lt;br /&gt;
After you have enabled profiling you should load some pages within the &amp;quot;Profile these&amp;quot; filter that you set in the step above. Once you have done these go to Settings &amp;gt; Site administration &amp;gt; Development &amp;gt; Profiling runs and you should see a list of the pages you visited. Clicking on one of these and then clicking on the &amp;quot;View profiling details&amp;quot; will take you to a profiling table full of helpful stats for tracking down slow pages and functions. You can get an even more ineresting breakdown of this by then clicking on the &amp;quot;View Full Callgraph&amp;quot; link. This callgraph makes it easy to see where the slow parts of each particular run are and functions which individually may not take a long time to run but which are run thousands of times and thus resulting in a great deal of slowdown.&lt;br /&gt;
[[Image:profilingSettings.png|frame|center|Enabling profiling and setting it to run on all pages via a wildcard]]&lt;br /&gt;
[[Image:profilingRuns.png|frame|left|A profiling runs option can be seen after enabling profiling]]&lt;br /&gt;
&lt;br /&gt;
==Using XHProf==&lt;br /&gt;
&lt;br /&gt;
MDL-39443 shows the kind of thing that can be done using XHProf.&lt;br /&gt;
&lt;br /&gt;
[http://tjhunt.blogspot.co.uk/2013/05/performance-testing-moodle.html This blog post] talks about the process.&lt;br /&gt;
&lt;br /&gt;
Since Moodle 2.5.1 it&#039;s possible to export and import any profiling run. That enables some interesting uses like, comparisons along the time, between different systems and sharing or runs in other systems like the Tracker when optimization issues are being fixed.&lt;/div&gt;</summary>
		<author><name>Gabrielros</name></author>
	</entry>
</feed>