# Moodle Context

select * from mdl_context where contextinstanceid = {COURSEID} AND contextlevel = 50
so if you have a courseid 5:
select id from mdl_context where contextinstanceid = {COURSEID} AND contextlevel = 50
that should give you the course context id of the course you are working with.
contextlevel = 50 is the course context level

the contextinstanceid field refers to the courseid, or the userid, or the cmid depending on which level is being set at
if contextlevel == CONTEXT_COURSE (50) then contextinstanceid = the course id, if contextlevel == CONTEXT_USER (30) then contextinstanceid will be the userid

For reference:
CONTEXT_SYSTEM =10
CONTEXT_USER = 30
CONTEXT_COURSECAT = 40
CONTEXT_COURSE = 50
CONTEXT_MODULE = 70
CONTEXT_BLOCK = 80

# User Permissions and Roles

Permissions are assigned at different contexts/level like system or course etc

# Find a user's permissions

user/preferences.php?userid=77

# PHPUnit Test

# Run testsuit

vendor/bin/phpunit --testsuite workshopform_accumulative_testsuite

# Parallel testing

CODE_HOME=/var/www/html
SITE_TYPE=$1
php test/phpunit/phpunit.php init
php server/admin/tool/phpunit/cli/parallel_init.php --processes=3
php server/admin/tool/phpunit/cli/parallel_run.php --configuration=${CODE_HOME}/test/phpunit/phpunit.xml --processes=3

# Not starting in docker

I had reinstalled moodle-docker-compose in it and the site environment is set alright but it has permission issues. When I am initiating phpunittests I am having issues with composer. I am getting the below error:

In SelfUpdateCommand.php line 146:
fileowner(): stat failed for /var/www/.composer

Solution:
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker
mbash root

# Debugging

# IDE

Setup your IDE (Visual code) following instructions here https://docs.moodle.org/dev/Setting_up_VSCode
    XDebug is required to enable PHP Debuggin in VC
        Follow [this](https://medium.com/@sirajul.anik/install-and-configure-xdebug-3-in-a-docker-container-and-integrate-step-debugging-with-phpstorm-5e135bc3290a) to install xdebug in docker container.
        Basically add the below lines to DockerFile:
            RUN pecl install xdebug
            RUN docker-php-ext-enable xdebug

# Moodle Template

https://docs.moodle.org/dev/Templates#Rendering_in_JavaScript
https://docs.moodle.org/dev/Javascript_Modules

See example on /home/sumaiyajaved/development/moodlenew/admin/tool/analytics/indicators.php

# Install a plugin on moodle using git

git remote add -f $REMOTENAME $GITURL.git
git subtree add --prefix $PATH/$PLUGINNAME $REMOTENAME $BRANCH --squash
git push
For e.g. install plugin "Course completion/activity filters"; https://github.com/catalyst/moodle-filter_coursecompletion
Branch: main
git remote add -f  moodle-filter_coursecompletion git@github.com:catalyst/moodle-filter_coursecompletion.git
git subtree add --prefix filter/coursecompletion  moodle-filter_coursecompletion main --squash
or
git subtree pull --prefix filter/coursecompletion  moodle-filter_coursecompletion main --squash
git push or git push -u origin mdl39-victoria-testing

# Maintain plugin inside site repo

This is useful when you have to maintain a plugin inside a Moodle repo. The plugin is in the subfolders and be pushed to their upstream by using the below approach.

git checkout -b <client-branch>
cd path/to/plugin
git init
git branch -m <newbranch-to-init>
git add .
git commit -m "init"
git remote add origin <git-repo>
git pull
git checkout -b <newbranch-with-fixes>
git diff <newbranch-to-init> <newbranch-with-fixes> > mydiff.diff
git apply mydiff.diff
git push origin <newbranch-with-fixes>
rm -rf .git

# Plugin repo for Totara vs Moodle

If you see a plugin catered towards Moodle, you might not be sure which version to choose for Totara. Best bet would be to go with MOODLE_34_STABLE.

# Install database from cli

php admin/cli/install_database.php --agree-license=yes --adminuser=admin --adminpass="${ADMINPASSWORD}" --fullname=${SITENAME} --shortname=${SITENAME}

# Update admin password from database

update mdl_user set password='$2y$10$st/h/qGG06Cm4jUYnc0D6eYhdcKSwgHH.Qj8vVj9.wCIAKZ707TbW' where username like 'admin';

# Make a user siteadmin from database

UPDATE mdl_config SET value = value || ',102' WHERE name = 'siteadmins';
or
$CFG->siteadmins = 102;

For more infor visit https://stackoverflow.com/questions/40654087/how-to-change-user-permissions-via-mysql-in-moodle

# Plugin development version bump

The best practice to follow when bumping / increasing the version of your plugin is found here https://docs.moodle.org/dev/version.php

- In the "latest" branch - eg T15 you bump it with the current date.
- In the older branches, you use micro bumps, i.e. only bump the last digit by 1

* But why do we have to follow this structure?

Let us take an example, we have a plugin in software version t15, we have to do something in future that updates a database field, but we don't need that in the version t13. As a result, it's important that the versions are different / lower than the latest one so that when we upgrade a t13 site to t15, it picks up any changes it needs.

Another example, a new field that we had added in t15 that bumps to a 2022 date - and imagine that we have the same version across all branches. Then after that we do something that changes something else, and is backported to older branches.  This would result into the t13 site without the db change with a version set to 2022. Then we upgrade that site to t15, and it sees version is the same, so doesn't run the db field change.

# Checking site logs from server

* Checking cron log

Copy cron log to you machine: scp yourname@machine:/var/log/cronlogs/thesite/cron.log-xxxxxxx.gz .

Extract log file
Use grep: cat cron.log-xxxxxxx | grep 'core_course\\task\\course_delete_modules'

* Error logs

# List of site administrators

You can get the list from admin/roles/admins.php

# See mail log

Moodle has plugin local_maillog you can use the below db query on the db server to see the mail logs

select id, userid, fromobj, toaddress, fromaddress, subject, success from mdl_mail_log where subject like '%Certification%' order by timesent desc limit 20;

# Coding Standards

To be able to follow Moodle coding standards, install the below plugins:
git remote add moodle-local_moodlecheck https://github.com/moodlehq/moodle-local_moodlecheck.git
git subtree add --prefix local/moodlecheck moodle-local_moodlecheck master --squash

git remote add moodle-local_codechecker https://github.com/moodlehq/moodle-local_codechecker.git
git subtree add --prefix local/codechecker moodle-local_codechecker master --squash

# Grunt

# Install and Run Grunt

https://docs.moodle.org/dev/Javascript_Modules#Install_grunt
nvm install && nvm use
npm install
npm install -g grunt-cli
cd to your module and run 'grunt amd
NOTE: For totaratxp, run the above in 'server' folder.

# Grunt not working for my totara installation

cd ~/development/totaratxp/server/
git checkout -- .
npm ci
cd mod/assign/feedback/apt/amd/
grunt amd

~/development/totaratxp/server/package.json has the grunt dependency, ~/development/totaratxp/package.json does not
there are two package.json files, one for the moodle / grunt stuff, the other for totara TUI
you originally installed the one for TUI, the commands I provided installs the one for moodle/grunt

# Errors

Fatal error: Node version not satisfied. Require >=16.14.0 <17.0.0-0, version installed: 14.18.0
    Try
    nvm install 16.14.0
    And
    Make sure you run the "grunt amd" by changing folders in the same terminal that was used to install grunt.

Loading "Gruntfile.js" tasks...ERROR >> Error: Missing binding node_modules/node-sass/vendor/linux-x64-93/binding.node
    npm rebuild node-sass

# Find ContextID from DB

select * from mdl_context where contextinstanceid = {COURSEID} AND contextlevel = 50
so if you have a courseid 5:
select id from mdl_context where contextinstanceid = {COURSEID} AND contextlevel = 50
that should give you the course context id of the course you are working with.
contextlevel = 50 is the course context level

why is contextlevel important in this case?
The context table stores information about courses, users, coursemodules etc

the contextinstanceid field refers to the courseid, or the userid, or the cmid depending on which level is being set at
if contextlevel == CONTEXT_COURSE (50) then contextinstanceid = the course id, if contextlevel == CONTEXT_USER (30) then contextinstanceid will be the userid

# Plugin Development

Basic plugin file structure
https://docs.moodle.org/dev/Plugin_files

# Find hooks in moodle

https://docs.moodle.org/dev/Callbacks#Types_of_callbacks_in_Moodle

# Debugging

# Display variable data in moodle form

$test = json_encode($grade);
$mform->addElement('html', "<div class='qheader'>TEST ".$test." ...</div>");

Read stack trace

Check error logs and other relevant logs

# XDebug

# XDebug not starting in vscode

After spending an hour or so, I found the solution was to click on 'Listen for XDebug' at the bottom bar instead of clicking the obvious button displayed on top of the screen. Make of it, whatever you may!

# Webservices

Enable web services
Enable protocol: rest
Created a token for site admin

If you want to use json for the calling convention then install  https://moodle.org/plugins/webservice_restful and enable 'restful' protocol
    Example of using curl to call a webservice
    curl -i -X POST -H "Content-Type: application/json" -H 'X-Moodle-Auth: 1JgQfgEUmfzGxPMvDkOLx2kWYCRNIwVM' -H "Accept: application/json" -d'{"assignmentid":"6", "aptgrade":"0", "submissionorgradeuserid":"77"}' "http://localhost:8000/webservice/restful/server.php/mod_assign_feedback_apt_assessor"

https://docs.moodle.org/dev/Adding_a_web_service_to_a_plugin

Also there is a simple php example for calling webservices, you could edit https://gitlab.wgtn.cat-it.co.nz/elearning/totarasync-ws-clients/-/blob/master/php/client.php

# Use ajax to update a form

To ajaxify a form, you would first need to create a webservice.
https://docs.moodle.org/dev/AJAX
Refer to nzqaapt mod_assignfeedback_apt custom plugin for this project which I had worked on with Catalyst
The library resides here server/lib/amd/src/modal_factory.js
ModalFactory.create({type: ModalFactory.types.DEFAULT});
https://docs.moodle.org/dev/AMD_Modal

# csp issue

Content blocking because of CSP on my local. This was not allowing me to browse the site.
Solution go to admin/settings.php?section=local_csp_settings
change https to http

# URL of the site

Use $PAGE->url to get the current path but global variable FULLME is handy
Global variable 'ME' can be  a bit of a pain sometimes because it includes the url path eg for nmit you get /moodle/local/login.php
so FULLME is usually safer as a comparison.
See it in action here https://github.com/sumaiyamannan/moodle-local_login/commit/5af02ee6faf9388d9f52faf51a848c87b5d83114

# Update moodle dependencies

run the below on commandline
    php composer.phar update

# Find how SQL query on a given page

Go to server/lib/tablelib.php -> function set_sql and add
 echo "params: <pre>"; print_r($this->sql);print "</pre>";

# Update email sender name site wide i.e. the from name

sender name is automatically selected as the main admin. The direct link would be user/profile.php?id=2

# Install database from cli

admin/cli/install_database.php --agree-license=yes --adminuser=admin --adminpass="${ADMINPASSWORD}" --fullname=${SITENAME} --shortname=${SITENAME}

# What is a physical location of a file in Moodle?

 You will have to look it's content hash up in the mdl_files table and then extract it from /var/lib/sitedata/<co>/<contenthash>

 For e.g. Let us you are searching for file 'backup-file-2022.mbz'

 select id, contenthash, pathnamehash, contextid from mdl_files where filename like 'backup-file-2022.mbz';
    id   |               contenthash                |               pathnamehash               | contextid
    --------+------------------------------------------+------------------------------------------+-----------
    439967 | 5f1935a069b0f18afc7a43f5f5afa7f4e8d18101 | 08e1ecca8cacced5ae4cfc9a27a837ce1f709242 |      7637

Then go to the sitedata folder
/var/lib/sitedata/<site-identifier>/filedir/5f/5f1935a069b0f18afc7a43f5f5afa7f4e8d18101

Note: In moodle there's actually two layers, so ae/s3/aes3425025 however we have reduced it to one to make our lsyncd processe run faster (it doesn't have to iterate so many directories).