Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
27 changes: 18 additions & 9 deletions docs/apis/core/activitycompletion/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ To support the completion system, your activity must include a `[activityname]_s
* @param string $feature
* @return null|bool
*/
function forum_supports(string $feature): bool {
function forum_supports(string $feature): bool
{
switch($feature) {
case FEATURE_COMPLETION_TRACKS_VIEWS:
return true;
Expand Down Expand Up @@ -154,7 +155,8 @@ You will need to add information about the custom rules into the activities `cm_
* @return cached_cm_info An object on information that the courses
* will know about (most noticeably, an icon).
*/
function forum_get_coursemodule_info($coursemodule) {
function forum_get_coursemodule_info($coursemodule)
{
global $DB;

$dbparams = ['id' => $coursemodule->instance];
Expand Down Expand Up @@ -224,7 +226,8 @@ First, the function that adds these controls:
* @category completion
* @return array List of added element names, or names of wrapping group elements.
*/
public function add_completion_rules() {
public function add_completion_rules()
{

$mform = $this->_form;

Expand Down Expand Up @@ -264,7 +267,8 @@ public function add_completion_rules() {
return [$this->get_suffixed_name('completionpostsgroup')];
}

protected function get_suffixed_name(string $fieldname): string {
protected function get_suffixed_name(string $fieldname): string
{
return $fieldname . $this->get_suffix();
}
```
Expand All @@ -284,7 +288,8 @@ Next, a function for checking whether the user selected this option:
* @param array $data Input data not yet validated.
* @return bool True if one or more rules is enabled, false if none are.
*/
public function completion_rule_enabled($data) {
public function completion_rule_enabled($data)
{
return (!empty($data[$this->get_suffixed_name('completionpostsenabled')]) &&
$data[$this->get_suffixed_name('completionposts')] != 0);
}
Expand All @@ -295,7 +300,8 @@ public function completion_rule_enabled($data) {
That's all the 'required' functions, but we need to add some extra code to support the checkbox behaviour. I overrode `get_data` so that if there is a value in the edit field, but the checkbox is not ticked, the value counts as zero (the rule will not be enabled).

```php
function get_data() {
function get_data()
{
$data = parent::get_data();
if (!$data) {
return $data;
Expand All @@ -316,7 +322,8 @@ You may have noticed the `completionunlocked` check. When some users have alread
Finally, forum already had a `data_preprocessing` function but I added code to this to set up the checkboxes when the form is displayed, and to make the default value of the text fields 1 instead of 0:

```php
function data_preprocessing(&$default_values){
function data_preprocessing(&$default_values)
{
// [Existing code, not shown]

// Set up the completion checkboxes which aren't part of standard data.
Expand Down Expand Up @@ -360,7 +367,8 @@ Here's the function for forum (simplified to include only the one completion opt
* @param bool $type Type of comparison (or/and; can be used as return value if no conditions)
* @return bool True if completed, false if not, $type if conditions not set.
*/
function forum_get_completion_state($course, $cm, $userid, $type) {
function forum_get_completion_state($course, $cm, $userid, $type)
{
global $CFG,$DB;

// Get forum details
Expand Down Expand Up @@ -402,7 +410,8 @@ You need to return an array of strings for each completion rule that is active.
* @param cm_info|stdClass $cm object with fields ->completion and ->customdata['customcompletionrules']
* @return array $descriptions the array of descriptions for the custom rules.
*/
function mod_forum_get_completion_active_rule_descriptions($cm) {
function mod_forum_get_completion_active_rule_descriptions($cm)
{
// Values will be present in cm_info, and we assume these are up to date.
if (empty($cm->customdata['customcompletionrules']) || $cm->completion != COMPLETION_TRACKING_AUTOMATIC) {
return [];
Expand Down
15 changes: 10 additions & 5 deletions docs/apis/core/calendar/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ where '$prioritiesforeventtype1' is an associative array that has the timestamp
* @param int $lessonid The lesson ID.
* @return array|null Array of group override priorities for open and close times. Null if there are no group overrides.
*/
function lesson_get_group_override_priorities($lessonid) {
function lesson_get_group_override_priorities($lessonid)
{
global $DB;

// Fetch group overrides.
Expand Down Expand Up @@ -182,7 +183,8 @@ This callback determines if an event should be visible throughout the site. For
* @param calendar_event $event
* @return bool Returns true if the event is visible to the current user, false otherwise.
*/
function mod_assign_core_calendar_is_event_visible(calendar_event $event) {
function mod_assign_core_calendar_is_event_visible(calendar_event $event)
{
global $CFG, $USER;

require_once($CFG->dirroot . '/mod/assign/locallib.php');
Expand Down Expand Up @@ -259,7 +261,8 @@ Eg.
* @param int $itemcount The item count associated with the action event.
* @return bool
*/
function mod_assign_core_calendar_event_action_shows_item_count(calendar_event $event, $itemcount = 0) {
function mod_assign_core_calendar_event_action_shows_item_count(calendar_event $event, $itemcount = 0)
{
// List of event types where the action event's item count should be shown.
$eventtypesshowingitemcount = [
ASSIGN_EVENT_TYPE_GRADINGDUE
Expand Down Expand Up @@ -320,7 +323,8 @@ This callback handles updating the activity instance based on the changed action
Example:

```php
function mod_feedback_core_calendar_event_timestart_updated(\calendar_event $event, \stdClass $feedback) {
function mod_feedback_core_calendar_event_timestart_updated(\calendar_event $event, \stdClass $feedback)
{
global $CFG, $DB;

if (empty($event->instance) || $event->modulename != 'feedback') {
Expand Down Expand Up @@ -406,7 +410,8 @@ If the calendar event has no valid `timestart` values then the callback should r
Example:

```php
function mod_feedback_core_calendar_get_valid_event_timestart_range(\calendar_event $event, \stdClass $instance) {
function mod_feedback_core_calendar_get_valid_event_timestart_range(\calendar_event $event, \stdClass $instance)
{
$mindate = null;
$maxdate = null;

Expand Down
36 changes: 24 additions & 12 deletions docs/apis/core/clock/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,15 @@ The recommended approach is to have the Dependency Injector inject into the cons
```php title="Usage in injected classes"
namespace mod_example;

class post {
class post
{
public function __construct(
protected readonly \core\clock $clock,
protected readonly \moodle_database $db,
)

public function create_thing(\stdClass $data): \stdClass {
public function create_thing(\stdClass $data): \stdClass
{
$data->timecreated = $this->clock->time();

$data->id = $this->db->insert_record('example_thing', $data);
Expand Down Expand Up @@ -99,8 +101,10 @@ The incrementing clock increases the time by one second every time it is called.
A helper method, `mock_clock_with_incrementing(?int $starttime = null): \core\clock`, is provided within the standard testcase:

```php title="Obtaining the incrementing clock"
class my_test extends \advanced_testcase {
public function test_create_thing(): void {
class my_test extends \advanced_testcase
{
public function test_create_thing(): void
{
// This class inserts data into the database.
$this->resetAfterTest(true);

Expand Down Expand Up @@ -134,8 +138,10 @@ The frozen clock uses a time which does not change, unless manually set. This ca
A helper method, `mock_clock_with_frozen(?int $time = null): \core\clock`, is provided within the standard testcase:

```php title="Obtaining and using the frozen clock"
class my_test extends \advanced_testcase {
public function test_create_thing(): void {
class my_test extends \advanced_testcase
{
public function test_create_thing(): void
{
// This class inserts data into the database.
$this->resetAfterTest(true);

Expand Down Expand Up @@ -182,27 +188,33 @@ class my_test extends \advanced_testcase {
If the standard cases are not suitable for you, then you can create a custom clock and inject it into the DI container.

```php title="Creating a custom clock"
class my_clock implements \core\clock {
class my_clock implements \core\clock
{
public int $time;

public function __construct() {
public function __construct()
{
$this->time = time();
}

public function now(): \DateTimeImmutable {
public function now(): \DateTimeImmutable
{
$time = new \DateTimeImmutable('@' . $this->time);
$this->time = $this->time += 5;

return $time;
}

public function time(): int {
public function time(): int
{
return $this->now()->getTimestamp();
}
}

class my_test extends \advanced_testcase {
public function test_my_thing(): void {
class my_test extends \advanced_testcase
{
public function test_my_thing(): void
{
$clock = new my_clock();
\core\di:set(\core\clock::class, $clock);

Expand Down
3 changes: 2 additions & 1 deletion docs/apis/core/comment/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ This is an example of a possible callback for plugin `mod_myplugin`:
* @param stdClass $args
* @return boolean
*/
function mod_myplugin_comment_display(stdClass $comments, stdClass $args): stdClass {
function mod_myplugin_comment_display(stdClass $comments, stdClass $args): stdClass
{
if ($args->commentarea != 'entry_comments') {
throw new comment_exception('invalidcommentarea');
}
Expand Down
3 changes: 2 additions & 1 deletion docs/apis/core/customfields/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ The list of fields is cached in the handler and these two functions can be calle
:::

```php title="Example code for course custom fields. This function will return all the custom fields for a given courseid"
function get_course_metadata($courseid) {
function get_course_metadata($courseid)
{
$handler = \core_customfield\handler::get_handler('core_course', 'course');
// This is equivalent to the line above.
//$handler = \core_course\customfield\course_handler::create();
Expand Down
19 changes: 13 additions & 6 deletions docs/apis/core/deprecation/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,24 +40,29 @@ The attribute is a Moodle PHP Attribute and can be applied to:
```php title="Example attribute usage"
// On a global function:
#[\core\attribute\deprecated('random_bytes', since: '4.3')]
function random_bytes_emulate($length) {
function random_bytes_emulate($length)
{
// Replaced by random_bytes since Moodle 4.3.
}

// On a class:
#[\core\attribute\deprecated(replacement: null, since: '4.4', reason: 'This functionality has been removed.')]
class example {
class example
{
#[\core\attribute\deprecated(
replacement: '\core\example::do_something',
since: '4.3',
reason: 'No longer required',
mdl: 'MDL-12345',
)]
public function do_something(): void {}
public function do_something(): void
{
}
}

// On an enum case:
enum example {
enum example
{
#[\core\attribute\deprecated('example::OPTION', since: '4.4', final: true)]
case OPTION;
}
Expand All @@ -75,15 +80,17 @@ The `\core\deprecation` class contains helper methods to inspect for use of the
// A method which has been initially deprecated, and replaced by 'random_bytes'. It should show debugging.
/** @deprecated since 4.3 */
#[\core\attribute\deprecated('random_bytes', since: '4.3')]
function random_bytes_emulate($length) {
function random_bytes_emulate($length)
{
\core\deprecation::emit_deprecation_if_present(__FUNCTION__);
return random_bytes($length);
}

// A method which has been finally deprecated and should throw an exception.
/** @deprecated since 2.7 */
#[\core\attribute\deprecated(replacement: 'Events API', since: '2.3', final: true)]
function add_to_log() {
function add_to_log()
{
\core\deprecation::emit_deprecation_if_present(__FUNCTION__);
}

Expand Down
33 changes: 22 additions & 11 deletions docs/apis/core/di/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ Dependencies are stored using a string id attribute, which is typically the clas
When accessing dependencies within a class, it is advisable to inject them into the constructor, for example:

```php title="Fetching a instance of the \core\http_client class from within a class"
class my_thing {
class my_thing
{
public function __construct(
protected readonly \core\http_client $client,
) {
Expand All @@ -48,7 +49,8 @@ The use of readonly properties is also highly recommended as it ensures that dep
These language features are available in all Moodle versions supporting Dependency Injection.

```php
class example_without_promotion {
class example_without_promotion
{
protected \core\http_client $client;

public function __construct(
Expand All @@ -58,7 +60,8 @@ class example_without_promotion {
}
}

class example_with_promotion {
class example_with_promotion
{
public function __construct(
protected readonly \core\http_client $client,
) {
Expand Down Expand Up @@ -101,8 +104,10 @@ namespace mod_example;

use core\hook\di_configuration;

class hook_listener {
public static function inject_dependencies(di_configuration $hook): void {
class hook_listener
{
public static function inject_dependencies(di_configuration $hook): void
{
$hook->add_definition(
id: complex_client::class,
definition: function (
Expand Down Expand Up @@ -139,8 +144,10 @@ use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use GuzzleHttp\Psr7\Response;

class example_test extends \advanced_testcase {
public function test_the_thing(): void {
class example_test extends \advanced_testcase
{
public function test_the_thing(): void
{
// Mock our responses to the http_client.
$handlerstack = HandlerStack::create(new MockHandler([
new Response(200, [], json_encode(['name' => 'Colin'])),
Expand Down Expand Up @@ -170,13 +177,15 @@ Dependencies can be usually be easily injected into classes which are themselves
In most cases in Moodle, this should be via the class constructor, for example:

```php title="Injecting via the constructor"
class thing_manager {
class thing_manager
{
public function __construct(
protected readonly \moodle_database $db,
) {
}

public function get_things(): array {
public function get_things(): array
{
return $this->db->get_records('example_things');
}
}
Expand All @@ -186,13 +195,15 @@ $manager = \core\di::get(thing_manager::class);
$things = $manager->get_things();

// Using it in a child class:
class other_thing {
class other_thing
{
public function __construct(
protected readonly thing_manager $manager,
) {
}

public function manage_things(): void {
public function manage_things(): void
{
$this->manager->get_things();
}
}
Expand Down
3 changes: 2 additions & 1 deletion docs/apis/core/dml/ddl.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ Of course, feel free to clarify, complete and add more info to all this document
- All the function calls in this page are public methods of the **database manager**, accessible from the $DB global object. You will need to "import" it within the upgrade function of your **upgrade.php** main function using the `global` keyword, for example:

```php
function xmldb_xxxx_upgrade {
function xmldb_xxxx_upgrade
{
global $DB;

// Load the DDL manager and xmldb API.
Expand Down
Loading
Loading