Passed
Push — master ( 5e945b...52d6d0 )
by Andreas
20:39
created

plugin::get_config()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4.0466

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 6
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 10
ccs 6
cts 7
cp 0.8571
crap 4.0466
rs 10
1
<?php
2
/**
3
 * @package midcom.routing
4
 * @author CONTENT CONTROL http://www.contentcontrol-berlin.de/
5
 * @copyright CONTENT CONTROL http://www.contentcontrol-berlin.de/
6
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License
7
 */
8
9
namespace midcom\routing;
10
11
use midcom;
12
use midcom_admin_folder_management;
13
use midcom_admin_rcs_plugin;
14
use midcom_helper_imagepopup_viewer;
15
use midcom_admin_help_help;
16
use midgard_admin_asgard_plugin;
17
use midcom_error;
18
19
/**
20
 * <b>Plugin Interface</b>
21
 *
22
 * This class includes a plugin system which can be used to flexibly enhance the
23
 * functionality of the request classes by external sources. Your component does
24
 * not have to worry about this, you just have to provide a way to register plugins
25
 * to site authors.
26
 *
27
 * Plugins always come in "packages", which are assigned to a namespace. The namespace
28
 * is used to separate various plugins from each other, it is prepended before any
29
 * URL. Within a plugin you can register one or more handler classes. Each of this
30
 * classes can of course define more than one request handler.
31
 *
32
 * A plugin class must be a descendant of midcom_baseclasses_components_handler or at
33
 * least support its full interface.
34
 *
35
 * As outlined above, plugins are managed in a two-level hierarchy. First, there is
36
 * the plugin identifier, second the class identifier. When registering a plugin,
37
 * these two are specified. The request handlers obtained by the above callback are
38
 * automatically expanded to match the plugin namespace.
39
 *
40
 * <i>Example: Plugin registration</i>
41
 *
42
 * <code>
43
 * $this->register_plugin_namespace(
44
 *     '__ais', [
45
 *         'folder' => [
46
 *             'class' => 'midcom_admin_folder_management',
47
 *             'config' => null,
48
 *         ],
49
 *     ]
50
 * );
51
 * </code>
52
 *
53
 * The first argument of this call identifies the plugin namespace, the second
54
 * the list of classes associated with this plugin. Each class gets its own
55
 * identifier. The namespace and class identifier is used to construct the
56
 * final plugin URL: {$anchor_prefix}/{$namespace}/{$class_identifier}/...
57
 * This gives fully unique URL namespaces to all registered plugins.
58
 *
59
 * Plugin handlers always last in queue, so they won't override component handlers.
60
 * Their name is prefixed with __{$namespace}-{$class_identifier} to ensure
61
 * uniqueness.
62
 *
63
 * Each class must have these options:
64
 *
65
 * - class: The name of the class to use
66
 * - src: The source URL of the plugin class. This can be either a file:/...
67
 *   URL which is relative to MIDCOM_ROOT, snippet:/... which identifies an
68
 *   arbitrary snippet, or finally, component:...
69
 *   which will load the component specified. This is only used if the class
70
 *   is not yet available.
71
 * - name: This is the clear-text name of the plugin.
72
 * - config: This is an optional configuration argument, allows for customization.
73
 *   May be omitted, in which case it defaults to null.
74
 *
75
 * Once a plugin has been successfully initialized, its configuration is put
76
 * into the request data:
77
 *
78
 * - mixed plugin_config: The configuration passed to the plugin as outlined
79
 *   above.
80
 * - string plugin_name: The name of the plugin as defined in its config
81
 *
82
 * @package midcom.routing
83
 */
84
class plugin
85
{
86
    /**
87
     * This variable keeps track of the registered plugin namespaces. It maps namespace
88
     * identifiers against plugin config lists. This is used during can_handle startup
89
     * to determine whether the request has to be relayed to a plugin.
90
     *
91
     * You have to use the viewer's register_plugin_namespace() member function during the
92
     * _on_initialize event to register plugin namespaces.
93
     *
94
     * @var array
95
     */
96
    private static $registry = [];
97
98
    /**
99
     * Create a new plugin namespace and map the configuration to it.
100
     * It allows flexible, user-configurable extension of components.
101
     *
102
     * Only very basic testing is done to keep runtime up, currently the system only
103
     * checks to prevent duplicate namespace registrations. In such a case,
104
     * midcom_error will be thrown. Any further validation won't be done before
105
     * can_handle determines that a plugin is actually in use.
106
     *
107
     * @param string $namespace The plugin namespace, checked against $args[0] during
108
     *     URL parsing.
109
     * @param array $config The configuration of the plugin namespace as outlined in
110
     *     the class introduction
111
     */
112 6
    public static function register_namespace(string $namespace, array $config)
113
    {
114 6
        self::init();
115 6
        if (array_key_exists($namespace, self::$registry)) {
116 4
            throw new midcom_error("Tried to register the plugin namespace {$namespace}, but it is already registered.");
117
        }
118 2
        self::$registry[$namespace] = $config;
119 2
    }
120
121 278
    public static function get_config(string $namespace, string $name) : ?array
122
    {
123 278
        self::init();
124 278
        if (empty(self::$registry[$namespace][$name])) {
125 194
            return null;
126
        }
127 84
        if (empty(self::$registry[$namespace][$name]['class']) || !class_exists(self::$registry[$namespace][$name]['class'])) {
128
            throw new midcom_error("Failed to load the plugin {$namespace}/{$name}, implementation class not available.");
129
        }
130 84
        return self::$registry[$namespace][$name];
131
    }
132
133
    /**
134
     * Register the plugin namespaces provided from MidCOM core.
135
     */
136 278
    private static function init()
137
    {
138 278
        if (self::$registry) {
0 ignored issues
show
Bug Best Practice introduced by
The expression self::registry of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
139 278
            return;
140
        }
141 1
        self::$registry = [
142
            '__ais' => [
143
                'folder' => [
144 1
                    'class' => midcom_admin_folder_management::class,
145
                ],
146
                'rcs' => [
147
                    'class' => midcom_admin_rcs_plugin::class,
148
                ],
149
                'imagepopup' => [
150
                    'class' => midcom_helper_imagepopup_viewer::class,
151
                ],
152
                'help' => [
153
                    'class' => midcom_admin_help_help::class,
154
                ],
155
            ]
156
        ];
157
158
        // Load plugins registered via component manifests
159 1
        $plugins = midcom::get()->componentloader->get_all_manifest_customdata('request_handler_plugin');
160 1
        $plugins['asgard'] = [
161
            'class' => midgard_admin_asgard_plugin::class,
162
        ];
163
164 1
        $customdata = midcom::get()->componentloader->get_all_manifest_customdata('asgard_plugin');
165 1
        foreach ($customdata as $component => $plugin_config) {
166 1
            $plugins["asgard_{$component}"] = $plugin_config;
167
        }
168
169 1
        self::register_namespace('__mfa', $plugins);
170
    }
171
}