Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
namespace core;
18
 
19
use Psr\Container\ContainerInterface;
20
 
21
/**
22
 * DI Container Helper.
23
 *
24
 * @package    core
25
 * @copyright  2023 Andrew Lyons <andrew@nicols.co.uk>
26
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27
 */
28
class di {
29
    /** @var ContainerInterface The stored container */
30
    protected static ?ContainerInterface $container;
31
 
32
    /**
33
     * Get the DI Container.
34
     *
35
     * @return ContainerInterface
36
     */
37
    public static function get_container(): ContainerInterface {
38
        if (!isset(self::$container)) {
39
            self::$container = self::create_container();
40
        }
41
        return self::$container;
42
    }
43
 
44
    /**
45
     * Reset the DI Container.
46
     *
47
     * This is primarily intended for Unit Testing, and for use in Scheduled tasks.
48
     */
49
    public static function reset_container(): void {
50
        self::$container = null;
51
    }
52
 
53
    /**
54
     * Finds an entry of the container by its identifier and returns it.
55
     *
56
     * This is a shortcut helper for \core\di::get_container()->get($id).
57
     *
58
     * @param string $id Identifier of the entry to look for.
59
     * @return mixed Entry.
60
     */
61
    public static function get(string $id): mixed {
62
        return self::get_container()->get($id);
63
    }
64
 
65
    /**
66
     * Set an entry in the container by its identifier.
67
     *
68
     * @param string $id Identifier of the entry to set
69
     * @param mixed $value The value to set
70
     */
71
    public static function set(string $id, mixed $value): void {
72
        // Please note that the `set` method is not a part of the PSR-11 standard.
73
        // We currently make use of PHP-DI which does have this method, but its use is not guaranteed.
74
        // If Moodle switches to alternative DI resolution, this method _must_ be updated to work with it.
75
 
76
        /** @var \DI\Container */
77
        $container = self::get_container();
78
        $container->set($id, $value);
79
    }
80
 
81
    /**
82
     * Create a new Container Instance.
83
     *
84
     * @return ContainerInterface
85
     */
86
    protected static function create_container(): ContainerInterface {
87
        global $CFG, $DB;
88
 
89
        // PHP Does not support function autoloading. We must manually include the file.
90
        require_once("{$CFG->libdir}/php-di/php-di/src/functions.php");
91
 
92
        // Configure the Container builder.
93
        $builder = new \DI\ContainerBuilder();
94
 
95
        // At the moment we are using autowiring, but not automatic attribute injection.
96
        // Automatic attribute injection is a php-di specific feature.
97
        $builder->useAutowiring(true);
98
 
99
        if (!$CFG->debugdeveloper) {
100
            // Enable compilation of the container and write proxies to disk in production.
101
            // See https://php-di.org/doc/performances.html for information.
102
            $cachedir = make_localcache_directory('di');
103
            $builder->enableCompilation($cachedir);
104
            $builder->writeProxiesToFile(true, $cachedir);
105
        }
106
 
107
        // Get the hook manager.
108
        $hookmanager = \core\hook\manager::get_instance();
109
 
110
        // Configure some basic definitions.
111
        $builder->addDefinitions([
112
            // The hook manager should be in the container.
113
            \core\hook\manager::class => $hookmanager,
114
 
115
            // The database.
116
            \moodle_database::class => $DB,
117
 
118
            // The string manager.
119
            \core_string_manager::class => fn() => get_string_manager(),
120
 
121
            // The Moodle Clock implementation, which itself is an extension of PSR-20.
122
            // Alias the PSR-20 clock interface to the Moodle clock. They are compatible.
123
            \core\clock::class => fn() => new \core\system_clock(),
124
            \Psr\Clock\ClockInterface::class => \DI\get(\core\clock::class),
125
        ]);
126
 
127
        // Add any additional definitions using hooks.
128
        $hookmanager->dispatch(new \core\hook\di_configuration($builder));
129
 
130
        // Build the container and return.
131
        return $builder->build();
132
    }
133
}