<?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=Msoni</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=Msoni"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Msoni"/>
	<updated>2026-06-07T03:22:05Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Moodle_Mobile_Push_Notifications&amp;diff=50378</id>
		<title>Moodle Mobile Push Notifications</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Moodle_Mobile_Push_Notifications&amp;diff=50378"/>
		<updated>2016-06-04T06:38:29Z</updated>

		<summary type="html">&lt;p&gt;Msoni: /* brainstorming use case */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Goal==&lt;br /&gt;
Moodle Mobile should receive Moodle messages as push notifications on iOS and Android.&lt;br /&gt;
&lt;br /&gt;
== Use case and web services ==&lt;br /&gt;
[[Image:Screenshot_2_05_13_5_16_PM.png|thumb]]&lt;br /&gt;
[[Image:Screenshot_2_05_13_5_14_PM.png|thumb]]&lt;br /&gt;
=== currently implemented use case ===&lt;br /&gt;
# The user opens the app and accepts to receive push notifications. The app contacts Apple push notification server and gets a device token. The mobile app PushPlugin plugin does it.&lt;br /&gt;
# The user enters its Moodle credentials. The app gets an [http://airnotifier.github.io AirNotifier] access key from the site. (note that this access key is currently the same for each site =&amp;gt; meaningless). The key is retrieved by calling the webservice message_airnotifier_get_access_key(permissions). create_token is the only possible permission at the moment. &lt;br /&gt;
# The app sends its token to [http://airnotifier.github.io AirNotifier] server - it&#039;s done by a HTTP POST request. &lt;br /&gt;
# The app registers its device to the site - it&#039;s done by a ws call message_airnotifier_add_user_device(appname, devicetoken, devicename)&lt;br /&gt;
# Someone/Something triggers a Moodle message. [http://airnotifier.github.io AirNotifier] provider (Moodle site) sends a payload for a specific device token to airnotifier server - it&#039;s done by a HTTP POST&lt;br /&gt;
# The user receive the notification.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== brainstorming use case ===&lt;br /&gt;
# During [http://airnotifier.github.io AirNotifier] provider installation, the site contacts Airnotifer server to request an access key for itself + an access key for the devices (to send their device token to [http://airnotifier.github.io AirNotifier] server).&lt;br /&gt;
# The user opens the app and accepts to receive push notifications. The app contacts Apple push notification server and gets a device token.&lt;br /&gt;
# The user enters its Moodle credentials. The app gets an [http://airnotifier.github.io AirNotifier] access key from the site. It&#039;s done calling the webservice message_airnotifier_get_access_key(type). An admin could request the site access key, the others only get the device access key.&lt;br /&gt;
# The app sends its device token to [http://airnotifier.github.io AirNotifier] server + the site url (so airnotifier knows the device/site couple, and so [http://airnotifier.github.io AirNotifier] can allow site broadcast) - it&#039;s done by a HTTP POST request. &lt;br /&gt;
# The app registers its device to the site - it&#039;s done by a ws call message_airnotifier_add_user_device(appname, devicetoken, devicename)&lt;br /&gt;
# During this web service, the site confirms the device token to [http://airnotifier.github.io AirNotifier]. It&#039;s done by a HTTP POST request. [http://airnotifier.github.io AirNotifier] server deletes unconfirmed device tokens older than one minute every hours.&lt;br /&gt;
# Someone/Something triggers a Moodle message. [http://airnotifier.github.io AirNotifier] provider (Moodle site) sends a payload for a specific device token to airnotifier server - it&#039;s done by a HTTP POST&lt;br /&gt;
# Time to time, the [http://airnotifier.github.io AirNotifier] server checks Apple feedback and delete the unactive device tokens. &lt;br /&gt;
# When the [http://airnotifier.github.io AirNotifier] provider tries to send a message to a deleted device, it receive an error from [http://airnotifier.github.io AirNotifier] server and stores it.  Then it sends a unique alert to the device user. The device is disabled on the user messaging settings. After a month, the cron processes delete the device.&lt;br /&gt;
&lt;br /&gt;
=== another brainstorming use case ===&lt;br /&gt;
# All the sites (public or privately) already registered in Moodle.net will have automatically keys for using [http://airnotifier.github.io AirNotifier]&lt;br /&gt;
# When registering a new site in Moodle.net there will be a new option for enabling PUSH Notificiations (true by default)&lt;br /&gt;
# If your site is not registered and your Mobile Services were enabled you will see a message in the Moodle Notifications page indicating that &amp;quot;You must register your site in order to be able to send PUSH Notifications&amp;quot;&lt;br /&gt;
# If your site is not registered and you enable Mobile Services you will see a message near to the &amp;quot;Enable Mobile Services&amp;quot; indicating that &amp;quot;You must register your site in order to be able to send PUSH Notifications&amp;quot;&lt;br /&gt;
# If your installation has a very big number of users, during the registration process and in the Notifications page you will see a message indicating &amp;quot;The public PUSH Notification server is limited to Moodle sites with less than N (5k, 20k...) users&amp;quot;&lt;br /&gt;
# The user opens the app and accepts to receive push notifications. The app contacts Apple push notification server and gets a device token. A user can disable at any time notifications for his device&lt;br /&gt;
# Every time the user open the app, the app gets an [http://airnotifier.github.io AirNotifier] access key from the site. It&#039;s done calling the webservice message_airnotifier_get_access_key(type). An admin could request the site access key, the others only get the device access key.&lt;br /&gt;
# The app sends its device token to [http://airnotifier.github.io AirNotifier] server + the site url (so airnotifier knows the device/site couple, and so [http://airnotifier.github.io AirNotifier] can allow site broadcast) - it&#039;s done by a HTTP POST request. This is done only if your device token has changed.&lt;br /&gt;
# The app registers its device to the site - it&#039;s done by a ws call message_airnotifier_add_user_device(appname, devicetoken, devicename, siteURL) This is done every time a user opens the app&lt;br /&gt;
# Since the app is sending its device token every time a user opens the app, a cron job in the Moodle Site can delete old device tokens (so we can avoid the [http://airnotifier.github.io AirNotifier] feedback service in the first stage)&lt;br /&gt;
# Someone/Something triggers a Moodle message. [http://airnotifier.github.io AirNotifier] provider (Moodle site) sends a payload for a specific device token + specific site to airnotifier server - it&#039;s done by a HTTP POST&lt;br /&gt;
# If the user disable the PUSH Notification feature, a WS message_airnotifier_remove_user_device is called, also the [http://airnotifier.github.io AirNotifier] is requested to delete the user device&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Benefits are:&lt;br /&gt;
-We can reuse the current registration process that is secure (as far as I know)&lt;br /&gt;
-The [http://airnotifier.github.io AirNotifier] API for register new sites will be exposed only to Moodle.net (not to all sites)&lt;br /&gt;
-It will be easier notify registered sites that are abusing (Moodle.net can communicate with sites (sending an automatic email to the user admin))&lt;br /&gt;
-Moodle will have statistics of sites using PUSH directly in Moodle.net (no need to ask [http://airnotifier.github.io AirNotifier])&lt;br /&gt;
-The registration process can be improved to retrieve the number of registered devices that are receiving notifications&lt;br /&gt;
-I think that it will &amp;quot;enforce&amp;quot; users to register their sites (for receive security notifications, etc..)&lt;br /&gt;
-Big companies with big Moodle installations usually doesn&#039;t register their Moodle sites, this will force these companies to use their own [http://airnotifier.github.io AirNotifier] server instance&lt;br /&gt;
-Since we have the number of users in a Moodle site, we can automatically disable [http://airnotifier.github.io AirNotifier] for big installations (more thant Nk users)&lt;br /&gt;
-I think that having all the information that the registration provides will help us to &amp;quot;monitor and prevent abuse&amp;quot; of the [http://airnotifier.github.io AirNotifier] server&lt;br /&gt;
&lt;br /&gt;
== Payload content ==&lt;br /&gt;
The current payload content would need a bit of brainstorming. We need to identify what to send as it is extremely short. The app will behave following the content it receives. &lt;br /&gt;
=== Apple ===&lt;br /&gt;
The Apple payload is limited to 256bytes and it includes everything sent. Our current implementation is still quite of a wip:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
{type:&#039;moodle_instantmessage&#039;,id:&#039;8&#039;,urlparams:&#039;{&amp;quot;user&amp;quot;:&amp;quot;2&amp;quot;,&amp;quot;id&amp;quot;:&amp;quot;8&amp;quot;}&#039;,userfrom:&#039;Manager Moodle&#039;,date:&#039;1367477362&#039;,alert:&#039;This is a message text.&#039;,}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
=== GCM ===&lt;br /&gt;
The Apple payload is about 4Kb. As it&#039;s more more permissive than Apple, it is not an issue. The content will be the same than Apple ones, just the format changes.&lt;br /&gt;
&lt;br /&gt;
==Deliverables==&lt;br /&gt;
* push notification support on the mobile app - the app receives the push notification and behaves correctly.&lt;br /&gt;
* The [http://airnotifier.github.io AirNotifier] server - it sends notification to APNS / GCM.&lt;br /&gt;
* The [http://airnotifier.github.io AirNotifier] provider - it sends Moodle messages to [http://airnotifier.github.io AirNotifier] - MDL-36445&lt;br /&gt;
&lt;br /&gt;
=== [http://airnotifier.github.io AirNotifier] messaging provider ===&lt;br /&gt;
In your messaging setting page you can select which of your devices can receive push notifications. MDL-36445&lt;br /&gt;
The provider has usual messaging provider settings.&lt;br /&gt;
&lt;br /&gt;
=== [http://airnotifier.github.io AirNotifier] server ===&lt;br /&gt;
To install the server follow: https://github.com/airnotifier/airnotifier/wiki/Installation&lt;br /&gt;
&lt;br /&gt;
Need to be done:&lt;br /&gt;
* feedback - MOBILE-191&lt;br /&gt;
* load stress&lt;br /&gt;
* IP banning - need to be tested MOBILE-192&lt;br /&gt;
* Site broadcast (site keys) MOBILE-395&lt;br /&gt;
* DDOS attacks&lt;br /&gt;
* iOS support - it works&lt;br /&gt;
* Android support MOBILE-396&lt;br /&gt;
&lt;br /&gt;
=== App push notification support in the mobile app ===&lt;br /&gt;
MOBILE-168&lt;br /&gt;
&lt;br /&gt;
==== The app is closed or is running in the background ====&lt;br /&gt;
It&#039;s a normal OS notification. The user can open the app from it. We need to define what happens when we open the app. See payload content section.&lt;br /&gt;
&lt;br /&gt;
==== The app is opened ====&lt;br /&gt;
The app displays a notification popup. Or better, it&#039;s a small temporary notification message at the top that retarct by itself - less intrusive.&lt;br /&gt;
&lt;br /&gt;
== Risks ==&lt;br /&gt;
These risks have been raised by Dan in MDL-36445:&lt;br /&gt;
* Have we load tested it with large numbers of users/notifications?&lt;br /&gt;
* What is stopping someone downloading Moodle getting the keys to DOS our push notification service (surely blacklisting us with apple)&lt;br /&gt;
* If someone gains access to device ids, could they then use our service to spam users?&lt;br /&gt;
* Are we checking the &#039;feedback service&#039; and removing devices which no longer exist, apple ominously writes &amp;quot;Note: APNs monitors providers for their diligence in checking the feedback service and refraining from sending push notifications to nonexistent applications on devices.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Improvements ==&lt;br /&gt;
See Apu&#039;s comment in https://tracker.moodle.org/browse/MDL-36445?focusedCommentId=200343&amp;amp;page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-200343.&lt;br /&gt;
Specially the mention about language.&lt;/div&gt;</summary>
		<author><name>Msoni</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Moodle_Mobile_Push_Notifications&amp;diff=50377</id>
		<title>Moodle Mobile Push Notifications</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Moodle_Mobile_Push_Notifications&amp;diff=50377"/>
		<updated>2016-06-04T06:36:17Z</updated>

		<summary type="html">&lt;p&gt;Msoni: /* brainstorming use case */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Goal==&lt;br /&gt;
Moodle Mobile should receive Moodle messages as push notifications on iOS and Android.&lt;br /&gt;
&lt;br /&gt;
== Use case and web services ==&lt;br /&gt;
[[Image:Screenshot_2_05_13_5_16_PM.png|thumb]]&lt;br /&gt;
[[Image:Screenshot_2_05_13_5_14_PM.png|thumb]]&lt;br /&gt;
=== currently implemented use case ===&lt;br /&gt;
# The user opens the app and accepts to receive push notifications. The app contacts Apple push notification server and gets a device token. The mobile app PushPlugin plugin does it.&lt;br /&gt;
# The user enters its Moodle credentials. The app gets an [http://airnotifier.github.io AirNotifier] access key from the site. (note that this access key is currently the same for each site =&amp;gt; meaningless). The key is retrieved by calling the webservice message_airnotifier_get_access_key(permissions). create_token is the only possible permission at the moment. &lt;br /&gt;
# The app sends its token to [http://airnotifier.github.io AirNotifier] server - it&#039;s done by a HTTP POST request. &lt;br /&gt;
# The app registers its device to the site - it&#039;s done by a ws call message_airnotifier_add_user_device(appname, devicetoken, devicename)&lt;br /&gt;
# Someone/Something triggers a Moodle message. [http://airnotifier.github.io AirNotifier] provider (Moodle site) sends a payload for a specific device token to airnotifier server - it&#039;s done by a HTTP POST&lt;br /&gt;
# The user receive the notification.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== brainstorming use case ===&lt;br /&gt;
# During [http://airnotifier.github.io AirNotifier] provider installation, the site contacts Airnotifer server to request an access key for itself + an access key for the devices (to send their device token to [http://airnotifier.github.io AirNotifier] server).&lt;br /&gt;
# The user opens the app and accepts to receive push notifications. The app contacts Apple push notification server and gets a device token.&lt;br /&gt;
# The user enters its Moodle credentials. The app gets an [http://airnotifier.github.io AirNotifier] access key from the site. It&#039;s done calling the webservice message_airnotifier_get_access_key(type). An admin could request the site access key, the others only get the device access key.&lt;br /&gt;
# The app sends its device token to [http://airnotifier.github.io AirNotifier] server + the site url (so airnotifier knows the device/site couple, and so [http://airnotifier.github.io AirNotifier] can allow site broadcast) - it&#039;s done by a HTTP POST request. &lt;br /&gt;
# The app registers its device to the site - it&#039;s done by a ws call core_user_add_user_device(appname, devicetoken, devicename)&lt;br /&gt;
# During this web service, the site confirms the device token to [http://airnotifier.github.io AirNotifier]. It&#039;s done by a HTTP POST request. [http://airnotifier.github.io AirNotifier] server deletes unconfirmed device tokens older than one minute every hours.&lt;br /&gt;
# Someone/Something triggers a Moodle message. [http://airnotifier.github.io AirNotifier] provider (Moodle site) sends a payload for a specific device token to airnotifier server - it&#039;s done by a HTTP POST&lt;br /&gt;
# Time to time, the [http://airnotifier.github.io AirNotifier] server checks Apple feedback and delete the unactive device tokens. &lt;br /&gt;
# When the [http://airnotifier.github.io AirNotifier] provider tries to send a message to a deleted device, it receive an error from [http://airnotifier.github.io AirNotifier] server and stores it.  Then it sends a unique alert to the device user. The device is disabled on the user messaging settings. After a month, the cron processes delete the device.&lt;br /&gt;
&lt;br /&gt;
=== another brainstorming use case ===&lt;br /&gt;
# All the sites (public or privately) already registered in Moodle.net will have automatically keys for using [http://airnotifier.github.io AirNotifier]&lt;br /&gt;
# When registering a new site in Moodle.net there will be a new option for enabling PUSH Notificiations (true by default)&lt;br /&gt;
# If your site is not registered and your Mobile Services were enabled you will see a message in the Moodle Notifications page indicating that &amp;quot;You must register your site in order to be able to send PUSH Notifications&amp;quot;&lt;br /&gt;
# If your site is not registered and you enable Mobile Services you will see a message near to the &amp;quot;Enable Mobile Services&amp;quot; indicating that &amp;quot;You must register your site in order to be able to send PUSH Notifications&amp;quot;&lt;br /&gt;
# If your installation has a very big number of users, during the registration process and in the Notifications page you will see a message indicating &amp;quot;The public PUSH Notification server is limited to Moodle sites with less than N (5k, 20k...) users&amp;quot;&lt;br /&gt;
# The user opens the app and accepts to receive push notifications. The app contacts Apple push notification server and gets a device token. A user can disable at any time notifications for his device&lt;br /&gt;
# Every time the user open the app, the app gets an [http://airnotifier.github.io AirNotifier] access key from the site. It&#039;s done calling the webservice message_airnotifier_get_access_key(type). An admin could request the site access key, the others only get the device access key.&lt;br /&gt;
# The app sends its device token to [http://airnotifier.github.io AirNotifier] server + the site url (so airnotifier knows the device/site couple, and so [http://airnotifier.github.io AirNotifier] can allow site broadcast) - it&#039;s done by a HTTP POST request. This is done only if your device token has changed.&lt;br /&gt;
# The app registers its device to the site - it&#039;s done by a ws call message_airnotifier_add_user_device(appname, devicetoken, devicename, siteURL) This is done every time a user opens the app&lt;br /&gt;
# Since the app is sending its device token every time a user opens the app, a cron job in the Moodle Site can delete old device tokens (so we can avoid the [http://airnotifier.github.io AirNotifier] feedback service in the first stage)&lt;br /&gt;
# Someone/Something triggers a Moodle message. [http://airnotifier.github.io AirNotifier] provider (Moodle site) sends a payload for a specific device token + specific site to airnotifier server - it&#039;s done by a HTTP POST&lt;br /&gt;
# If the user disable the PUSH Notification feature, a WS message_airnotifier_remove_user_device is called, also the [http://airnotifier.github.io AirNotifier] is requested to delete the user device&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Benefits are:&lt;br /&gt;
-We can reuse the current registration process that is secure (as far as I know)&lt;br /&gt;
-The [http://airnotifier.github.io AirNotifier] API for register new sites will be exposed only to Moodle.net (not to all sites)&lt;br /&gt;
-It will be easier notify registered sites that are abusing (Moodle.net can communicate with sites (sending an automatic email to the user admin))&lt;br /&gt;
-Moodle will have statistics of sites using PUSH directly in Moodle.net (no need to ask [http://airnotifier.github.io AirNotifier])&lt;br /&gt;
-The registration process can be improved to retrieve the number of registered devices that are receiving notifications&lt;br /&gt;
-I think that it will &amp;quot;enforce&amp;quot; users to register their sites (for receive security notifications, etc..)&lt;br /&gt;
-Big companies with big Moodle installations usually doesn&#039;t register their Moodle sites, this will force these companies to use their own [http://airnotifier.github.io AirNotifier] server instance&lt;br /&gt;
-Since we have the number of users in a Moodle site, we can automatically disable [http://airnotifier.github.io AirNotifier] for big installations (more thant Nk users)&lt;br /&gt;
-I think that having all the information that the registration provides will help us to &amp;quot;monitor and prevent abuse&amp;quot; of the [http://airnotifier.github.io AirNotifier] server&lt;br /&gt;
&lt;br /&gt;
== Payload content ==&lt;br /&gt;
The current payload content would need a bit of brainstorming. We need to identify what to send as it is extremely short. The app will behave following the content it receives. &lt;br /&gt;
=== Apple ===&lt;br /&gt;
The Apple payload is limited to 256bytes and it includes everything sent. Our current implementation is still quite of a wip:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
{type:&#039;moodle_instantmessage&#039;,id:&#039;8&#039;,urlparams:&#039;{&amp;quot;user&amp;quot;:&amp;quot;2&amp;quot;,&amp;quot;id&amp;quot;:&amp;quot;8&amp;quot;}&#039;,userfrom:&#039;Manager Moodle&#039;,date:&#039;1367477362&#039;,alert:&#039;This is a message text.&#039;,}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
=== GCM ===&lt;br /&gt;
The Apple payload is about 4Kb. As it&#039;s more more permissive than Apple, it is not an issue. The content will be the same than Apple ones, just the format changes.&lt;br /&gt;
&lt;br /&gt;
==Deliverables==&lt;br /&gt;
* push notification support on the mobile app - the app receives the push notification and behaves correctly.&lt;br /&gt;
* The [http://airnotifier.github.io AirNotifier] server - it sends notification to APNS / GCM.&lt;br /&gt;
* The [http://airnotifier.github.io AirNotifier] provider - it sends Moodle messages to [http://airnotifier.github.io AirNotifier] - MDL-36445&lt;br /&gt;
&lt;br /&gt;
=== [http://airnotifier.github.io AirNotifier] messaging provider ===&lt;br /&gt;
In your messaging setting page you can select which of your devices can receive push notifications. MDL-36445&lt;br /&gt;
The provider has usual messaging provider settings.&lt;br /&gt;
&lt;br /&gt;
=== [http://airnotifier.github.io AirNotifier] server ===&lt;br /&gt;
To install the server follow: https://github.com/airnotifier/airnotifier/wiki/Installation&lt;br /&gt;
&lt;br /&gt;
Need to be done:&lt;br /&gt;
* feedback - MOBILE-191&lt;br /&gt;
* load stress&lt;br /&gt;
* IP banning - need to be tested MOBILE-192&lt;br /&gt;
* Site broadcast (site keys) MOBILE-395&lt;br /&gt;
* DDOS attacks&lt;br /&gt;
* iOS support - it works&lt;br /&gt;
* Android support MOBILE-396&lt;br /&gt;
&lt;br /&gt;
=== App push notification support in the mobile app ===&lt;br /&gt;
MOBILE-168&lt;br /&gt;
&lt;br /&gt;
==== The app is closed or is running in the background ====&lt;br /&gt;
It&#039;s a normal OS notification. The user can open the app from it. We need to define what happens when we open the app. See payload content section.&lt;br /&gt;
&lt;br /&gt;
==== The app is opened ====&lt;br /&gt;
The app displays a notification popup. Or better, it&#039;s a small temporary notification message at the top that retarct by itself - less intrusive.&lt;br /&gt;
&lt;br /&gt;
== Risks ==&lt;br /&gt;
These risks have been raised by Dan in MDL-36445:&lt;br /&gt;
* Have we load tested it with large numbers of users/notifications?&lt;br /&gt;
* What is stopping someone downloading Moodle getting the keys to DOS our push notification service (surely blacklisting us with apple)&lt;br /&gt;
* If someone gains access to device ids, could they then use our service to spam users?&lt;br /&gt;
* Are we checking the &#039;feedback service&#039; and removing devices which no longer exist, apple ominously writes &amp;quot;Note: APNs monitors providers for their diligence in checking the feedback service and refraining from sending push notifications to nonexistent applications on devices.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Improvements ==&lt;br /&gt;
See Apu&#039;s comment in https://tracker.moodle.org/browse/MDL-36445?focusedCommentId=200343&amp;amp;page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-200343.&lt;br /&gt;
Specially the mention about language.&lt;/div&gt;</summary>
		<author><name>Msoni</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Local_plugins&amp;diff=34201</id>
		<title>Local plugins</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Local_plugins&amp;diff=34201"/>
		<updated>2012-06-15T04:02:18Z</updated>

		<summary type="html">&lt;p&gt;Msoni: &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&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;
== 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>Msoni</name></author>
	</entry>
</feed>