Completed
Pull Request — development (#3073)
by John
10:11
created

Action::initialize()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 4
nop 3
dl 0
loc 19
ccs 8
cts 8
cp 1
crap 3
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Defines an action with its associated sub-actions
5
 *
6
 * @name      ElkArte Forum
7
 * @copyright ElkArte Forum contributors
8
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause
9
 *
10
 * @version 1.1
11
 *
12
 */
13
14
/**
15
 * Action class defines an action with its associated sub-actions.
16
 * Object-oriented controllers (with sub-actions) uses it to set their action-subaction arrays, and have it call the
17
 * right function or method handlers.
18
 *
19
 * Replaces the sub-actions arrays in every dispatching function.
20
 * (the $subActions = ... etc, and calls for $_REQUEST['sa'])
21
 *
22
 */
23
class Action
24
{
25
	/**
26
	 * Array of sub-actions.
27
	 * The accepted array format is:
28
	 *    'sub_action name' => 'function name',
29
	 *  or
30
	 *    'sub_action name' => array(
31
	 *    'function' => 'function name'),
32
	 *  or
33
	 *    'sub_action name' => array(
34
	 *        'controller' => 'controller name',
35
	 *        'function' => 'method name',
36
	 *        'enabled' => true/false,
37
	 *        'permission' => area),
38
	 *  or
39
	 *    'sub_action name' => array(
40
	 *        'controller object, i.e. $this',
41
	 *        'method name',
42
	 *        'enabled' => true/false
43
	 *        'permission' => area),
44
	 *  or
45
	 *    'sub_action name' => array(
46
	 *        'controller' => 'controller name',
47
	 *        'function' => 'method name',
48
	 *        'enabled' => true/false,
49
	 *        'permission' => area)
50
	 */
51
52
	/**
53
	 * All the subactions we understand
54
	 * @var array
55
	 */
56
	protected $_subActions = [];
57
58
	/**
59
	 * The default subAction.
60
	 * @var string
61
	 */
62
	protected $_default;
63
64
	/**
65
	 * An (unique) id that triggers a hook
66
	 * @var string
67
	 */
68
	protected $_name;
69
70
	/** @var HttpReq Access to post/get data */
71
	protected $req;
72
73
	/**
74
	 * Constructor!
75
	 *
76
	 * @param string $name   Hook name
0 ignored issues
show
Documentation introduced by
Should the type for parameter $name not be null|string?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
77 6
	 * @param        HttpReq Access to post/get data
78
	 */
79 6
	public function __construct(string $name = null, HttpReq $req = null)
80 6
	{
81
		$this->_name = $name;
82
		$this->req = $req ?: HttpReq::instance();
83
	}
84
85
	/**
86
	 * Initialize the instance with an array of sub-actions.
87
	 *
88
	 * What it does:
89
	 *
90
	 * - Sub-actions have to be in the format expected for Action::_subActions array,
91
	 * indexed by sa.
92
	 *
93
	 * @param mixed[] $subActions   array of known subactions
94
	 * @param string  $default      default action if unknown sa is requested
0 ignored issues
show
Documentation introduced by
Should the type for parameter $default not be null|string?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
95
	 * @param string  $requestParam default key to check request value, defaults to sa
96 6
	 *
97
	 * @return string
98 6
	 */
99 6
	public function initialize(array $subActions, string $default = null, string $requestParam = 'sa'): string
100
	{
101 6
		if ($this->_name !== null)
102
		{
103 6
			call_integration_hook('integrate_sa_' . $this->_name, [&$subActions]);
104 4
		}
105
106 6
		$this->_subActions = array_filter(
107
			$subActions,
108 6
			function ($subAction)
109 6
			{
110
				return !empty($subAction['enabled']);
111 6
			}
112
		);
113
114
		$this->_default = $default ?: key($this->_subActions);
115
116
		return $this->req->getQuery($requestParam, 'trim|strval', $this->_default);
117
	}
118
119
	/**
120
	 * Call the function or method for the selected subaction.
121
	 *
122
	 * Both the controller and the method are set up in the subactions array. If a controller
123 6
	 * is not specified, the function is assumed to be a regular callable.
124
	 *
125
	 * @param string $sub_id a valid index in the subactions array
126 6
	 */
127 4
	public function dispatch(string $sub_id): void
128
	{
129
		$subAction = $this->_subActions[$sub_id] ?? $this->_default;
130
		$this->isAllowedTo($sub_id);
131
132 6
		// Start off by assuming that this is a callable of some kind.
133
		$call = [$subAction];
134
135 6
		if (isset($subAction['function']))
136 4
		{
137
			// This is just a good ole' function
138
			$call = [$subAction['function']];
139
		}
140
141
		// Calling a method within a controller?
142 View Code Duplication
		if (isset($subAction['controller']))
143 6
		{
144 4
			// Instance of a class
145
			if (is_object($subAction['controller']))
146
			{
147 6
				$controller = $subAction['controller'];
148 4
			}
149 6
			else
150 6
			{
151
				// 'controller' => 'ManageAttachments_Controller'
152
				// 'function' => 'action_avatars'
153
				$controller = new $subAction['controller'](new Event_Manager());
154
155 6
				// always set up the environment
156 4
				$controller->pre_dispatch();
157
			}
158 6
159 6
			// Modify the call accordingly
160
			$call = [$controller] + $call;
161 6
		}
162 4
163
		call_user_func($call);
164
	}
165
166 2
	/**
167
	 * Security check: verify that the user has the permission to perform the given action.
168 4
	 *
169
	 * What it does:
170
	 *
171
	 * - Verifies if the user has the permission set for the given action.
172
	 * - Return true if no permission was set for the action.
173
	 * - Results in a fatal_lang_error() if the user doesn't have permission,
174
	 * or this instance was not initialized, or the action cannot be found in it.
175
	 *
176
	 * @param string $sub_id The sub action
177
	 *
178
	 * @return bool
179
	 */
180
	protected function isAllowedTo(string $sub_id): bool
181
	{
182
		if (isset($this->_subActions[$sub_id], $this->_subActions[$sub_id]['permission']))
183
		{
184
			isAllowedTo($this->_subActions[$sub_id]['permission']);
185
		}
186
187
		return true;
188
	}
189
}
190