Completed
Pull Request — rbac (#7)
by Michael
06:00
created
includes/Fragments/NavigationMenuAccessControl.php 2 patches
Doc Comments   +5 added lines, -1 removed lines patch added patch discarded remove patch
@@ -24,6 +24,10 @@  discard block
 block discarded – undo
24 24
 
25 25
 trait NavigationMenuAccessControl
26 26
 {
27
+    /**
28
+     * @param string $name
29
+     * @param boolean $value
30
+     */
27 31
     protected abstract function assign($name, $value);
28 32
 
29 33
     /**
@@ -32,7 +36,7 @@  discard block
 block discarded – undo
32 36
     protected abstract function getSecurityManager();
33 37
 
34 38
     /**
35
-     * @param $currentUser
39
+     * @param \Waca\DataObjects\User $currentUser
36 40
      */
37 41
     protected function setupNavMenuAccess($currentUser)
38 42
     {
Please login to merge, or discard this patch.
Indentation   +36 added lines, -36 removed lines patch added patch discarded remove patch
@@ -24,45 +24,45 @@
 block discarded – undo
24 24
 
25 25
 trait NavigationMenuAccessControl
26 26
 {
27
-    protected abstract function assign($name, $value);
27
+	protected abstract function assign($name, $value);
28 28
 
29
-    /**
30
-     * @return SecurityManager
31
-     */
32
-    protected abstract function getSecurityManager();
29
+	/**
30
+	 * @return SecurityManager
31
+	 */
32
+	protected abstract function getSecurityManager();
33 33
 
34
-    /**
35
-     * @param $currentUser
36
-     */
37
-    protected function setupNavMenuAccess($currentUser)
38
-    {
39
-        $this->assign('nav__canRequests', $this->getSecurityManager()
40
-                ->allows(PageMain::class, RoleConfiguration::MAIN, $currentUser) === SecurityManager::ALLOWED);
34
+	/**
35
+	 * @param $currentUser
36
+	 */
37
+	protected function setupNavMenuAccess($currentUser)
38
+	{
39
+		$this->assign('nav__canRequests', $this->getSecurityManager()
40
+				->allows(PageMain::class, RoleConfiguration::MAIN, $currentUser) === SecurityManager::ALLOWED);
41 41
 
42
-        $this->assign('nav__canLogs', $this->getSecurityManager()
43
-                ->allows(PageLog::class, RoleConfiguration::MAIN, $currentUser) === SecurityManager::ALLOWED);
44
-        $this->assign('nav__canUsers', $this->getSecurityManager()
45
-                ->allows(StatsUsers::class, RoleConfiguration::MAIN, $currentUser) === SecurityManager::ALLOWED);
46
-        $this->assign('nav__canSearch', $this->getSecurityManager()
47
-                ->allows(PageSearch::class, RoleConfiguration::MAIN, $currentUser) === SecurityManager::ALLOWED);
48
-        $this->assign('nav__canStats', $this->getSecurityManager()
49
-                ->allows(StatsMain::class, RoleConfiguration::MAIN, $currentUser) === SecurityManager::ALLOWED);
42
+		$this->assign('nav__canLogs', $this->getSecurityManager()
43
+				->allows(PageLog::class, RoleConfiguration::MAIN, $currentUser) === SecurityManager::ALLOWED);
44
+		$this->assign('nav__canUsers', $this->getSecurityManager()
45
+				->allows(StatsUsers::class, RoleConfiguration::MAIN, $currentUser) === SecurityManager::ALLOWED);
46
+		$this->assign('nav__canSearch', $this->getSecurityManager()
47
+				->allows(PageSearch::class, RoleConfiguration::MAIN, $currentUser) === SecurityManager::ALLOWED);
48
+		$this->assign('nav__canStats', $this->getSecurityManager()
49
+				->allows(StatsMain::class, RoleConfiguration::MAIN, $currentUser) === SecurityManager::ALLOWED);
50 50
 
51
-        $this->assign('nav__canBan', $this->getSecurityManager()
52
-                ->allows(PageBan::class, RoleConfiguration::MAIN, $currentUser) === SecurityManager::ALLOWED);
53
-        $this->assign('nav__canEmailMgmt', $this->getSecurityManager()
54
-                ->allows(PageEmailManagement::class, RoleConfiguration::MAIN,
55
-                    $currentUser) === SecurityManager::ALLOWED);
56
-        $this->assign('nav__canWelcomeMgmt', $this->getSecurityManager()
57
-                ->allows(PageWelcomeTemplateManagement::class, RoleConfiguration::MAIN,
58
-                    $currentUser) === SecurityManager::ALLOWED);
59
-        $this->assign('nav__canSiteNoticeMgmt', $this->getSecurityManager()
60
-                ->allows(PageSiteNotice::class, RoleConfiguration::MAIN, $currentUser) === SecurityManager::ALLOWED);
61
-        $this->assign('nav__canUserMgmt', $this->getSecurityManager()
62
-                ->allows(PageUserManagement::class, RoleConfiguration::MAIN,
63
-                    $currentUser) === SecurityManager::ALLOWED);
51
+		$this->assign('nav__canBan', $this->getSecurityManager()
52
+				->allows(PageBan::class, RoleConfiguration::MAIN, $currentUser) === SecurityManager::ALLOWED);
53
+		$this->assign('nav__canEmailMgmt', $this->getSecurityManager()
54
+				->allows(PageEmailManagement::class, RoleConfiguration::MAIN,
55
+					$currentUser) === SecurityManager::ALLOWED);
56
+		$this->assign('nav__canWelcomeMgmt', $this->getSecurityManager()
57
+				->allows(PageWelcomeTemplateManagement::class, RoleConfiguration::MAIN,
58
+					$currentUser) === SecurityManager::ALLOWED);
59
+		$this->assign('nav__canSiteNoticeMgmt', $this->getSecurityManager()
60
+				->allows(PageSiteNotice::class, RoleConfiguration::MAIN, $currentUser) === SecurityManager::ALLOWED);
61
+		$this->assign('nav__canUserMgmt', $this->getSecurityManager()
62
+				->allows(PageUserManagement::class, RoleConfiguration::MAIN,
63
+					$currentUser) === SecurityManager::ALLOWED);
64 64
 
65
-        $this->assign('nav__canViewRequest', $this->getSecurityManager()
66
-                ->allows(PageViewRequest::class, RoleConfiguration::MAIN, $currentUser) === SecurityManager::ALLOWED);
67
-    }
65
+		$this->assign('nav__canViewRequest', $this->getSecurityManager()
66
+				->allows(PageViewRequest::class, RoleConfiguration::MAIN, $currentUser) === SecurityManager::ALLOWED);
67
+	}
68 68
 }
69 69
\ No newline at end of file
Please login to merge, or discard this patch.
includes/Fragments/RequestData.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -136,7 +136,7 @@
 block discarded – undo
136 136
     /**
137 137
      * Assigns a Smarty variable
138 138
      *
139
-     * @param  array|string $name  the template variable name(s)
139
+     * @param  string $name  the template variable name(s)
140 140
      * @param  mixed        $value the value to assign
141 141
      */
142 142
     abstract protected function assign($name, $value);
Please login to merge, or discard this patch.
Indentation   +318 added lines, -318 removed lines patch added patch discarded remove patch
@@ -23,322 +23,322 @@
 block discarded – undo
23 23
 
24 24
 trait RequestData
25 25
 {
26
-    /**
27
-     * @var array Array of IP address classed as 'private' by RFC1918.
28
-     */
29
-    protected static $rfc1918ips = array(
30
-        "10.0.0.0"    => "10.255.255.255",
31
-        "172.16.0.0"  => "172.31.255.255",
32
-        "192.168.0.0" => "192.168.255.255",
33
-        "169.254.0.0" => "169.254.255.255",
34
-        "127.0.0.0"   => "127.255.255.255",
35
-    );
36
-
37
-    /**
38
-     * Gets a request object
39
-     *
40
-     * @param PdoDatabase $database  The database connection
41
-     * @param int         $requestId The ID of the request to retrieve
42
-     *
43
-     * @return Request
44
-     * @throws ApplicationLogicException
45
-     */
46
-    protected function getRequest(PdoDatabase $database, $requestId)
47
-    {
48
-        if ($requestId === null) {
49
-            throw new ApplicationLogicException("No request specified");
50
-        }
51
-
52
-        $request = Request::getById($requestId, $database);
53
-        if ($request === false || !is_a($request, Request::class)) {
54
-            throw new ApplicationLogicException('Could not load the requested request!');
55
-        }
56
-
57
-        return $request;
58
-    }
59
-
60
-    /**
61
-     * Returns a value stating whether the user is allowed to see private data or not
62
-     *
63
-     * @param Request $request
64
-     * @param User    $currentUser
65
-     *
66
-     * @return bool
67
-     * @category Security-Critical
68
-     */
69
-    protected function isAllowedPrivateData(Request $request, User $currentUser)
70
-    {
71
-        // Test the main security barrier for private data access using SecurityManager
72
-        if ($this->barrierTest('alwaysSeePrivateData', $currentUser, 'RequestData')) {
73
-            // Tool admins/check-users can always see private data
74
-            return true;
75
-        }
76
-
77
-        // reserving user is allowed to see the data
78
-        if ($currentUser->getId() === $request->getReserved()
79
-            && $request->getReserved() !== null
80
-            && $this->barrierTest('seePrivateDataWhenReserved', $currentUser, 'RequestData')
81
-        ) {
82
-            return true;
83
-        }
84
-
85
-        // user has the reveal hash
86
-        if (WebRequest::getString('hash') === $request->getRevealHash()
87
-            && $this->barrierTest('seePrivateDataWithHash', $currentUser, 'RequestData')
88
-        ) {
89
-            return true;
90
-        }
91
-
92
-        // nope. Not allowed.
93
-        return false;
94
-    }
95
-
96
-    /**
97
-     * Tests the security barrier for a specified action.
98
-     *
99
-     * Don't use within templates
100
-     *
101
-     * @param string      $action
102
-     *
103
-     * @param User        $user
104
-     * @param null|string $pageName
105
-     *
106
-     * @return bool
107
-     * @category Security-Critical
108
-     */
109
-    abstract protected function barrierTest($action, User $user, $pageName = null);
110
-
111
-    /**
112
-     * Gets the name of the route that has been passed from the request router.
113
-     * @return string
114
-     */
115
-    abstract protected function getRouteName();
116
-
117
-    /** @return SecurityManager */
118
-    abstract protected function getSecurityManager();
119
-
120
-    /**
121
-     * Sets the name of the template this page should display.
122
-     *
123
-     * @param string $name
124
-     */
125
-    abstract protected function setTemplate($name);
126
-
127
-    /** @return IXffTrustProvider */
128
-    abstract protected function getXffTrustProvider();
129
-
130
-    /** @return ILocationProvider */
131
-    abstract protected function getLocationProvider();
132
-
133
-    /** @return IRDnsProvider */
134
-    abstract protected function getRdnsProvider();
135
-
136
-    /**
137
-     * Assigns a Smarty variable
138
-     *
139
-     * @param  array|string $name  the template variable name(s)
140
-     * @param  mixed        $value the value to assign
141
-     */
142
-    abstract protected function assign($name, $value);
143
-
144
-    /**
145
-     * @param int         $requestReservationId
146
-     * @param PdoDatabase $database
147
-     * @param User        $currentUser
148
-     */
149
-    protected function setupReservationDetails($requestReservationId, PdoDatabase $database, User $currentUser)
150
-    {
151
-        $requestIsReserved = $requestReservationId !== null;
152
-        $this->assign('requestIsReserved', $requestIsReserved);
153
-        $this->assign('requestIsReservedByMe', false);
154
-
155
-        if ($requestIsReserved) {
156
-            $this->assign('requestReservedByName', User::getById($requestReservationId, $database)->getUsername());
157
-            $this->assign('requestReservedById', $requestReservationId);
158
-
159
-            if ($requestReservationId === $currentUser->getId()) {
160
-                $this->assign('requestIsReservedByMe', true);
161
-            }
162
-        }
163
-
164
-        $this->assign('canBreakReservation', $this->barrierTest('force', $currentUser, PageBreakReservation::class));
165
-    }
166
-
167
-    /**
168
-     * Adds private request data to Smarty. DO NOT USE WITHOUT FIRST CHECKING THAT THE USER IS AUTHORISED!
169
-     *
170
-     * @param Request           $request
171
-     * @param User              $currentUser
172
-     * @param SiteConfiguration $configuration
173
-     *
174
-     * @param PdoDatabase       $database
175
-     */
176
-    protected function setupPrivateData(
177
-        $request,
178
-        User $currentUser,
179
-        SiteConfiguration $configuration,
180
-        PdoDatabase $database
181
-    ) {
182
-        $xffProvider = $this->getXffTrustProvider();
183
-
184
-        $relatedEmailRequests = RequestSearchHelper::get($database)
185
-            ->byEmailAddress($request->getEmail())
186
-            ->withConfirmedEmail()
187
-            ->excludingPurgedData($configuration)
188
-            ->excludingRequest($request->getId())
189
-            ->fetch();
190
-
191
-        $this->assign('requestEmail', $request->getEmail());
192
-        $emailDomain = explode("@", $request->getEmail())[1];
193
-        $this->assign("emailurl", $emailDomain);
194
-        $this->assign('requestRelatedEmailRequestsCount', count($relatedEmailRequests));
195
-        $this->assign('requestRelatedEmailRequests', $relatedEmailRequests);
196
-
197
-        $trustedIp = $xffProvider->getTrustedClientIp($request->getIp(), $request->getForwardedIp());
198
-        $this->assign('requestTrustedIp', $trustedIp);
199
-        $this->assign('requestRealIp', $request->getIp());
200
-        $this->assign('requestForwardedIp', $request->getForwardedIp());
201
-
202
-        $trustedIpLocation = $this->getLocationProvider()->getIpLocation($trustedIp);
203
-        $this->assign('requestTrustedIpLocation', $trustedIpLocation);
204
-
205
-        $this->assign('requestHasForwardedIp', $request->getForwardedIp() !== null);
206
-
207
-        $relatedIpRequests = RequestSearchHelper::get($database)
208
-            ->byIp($trustedIp)
209
-            ->withConfirmedEmail()
210
-            ->excludingPurgedData($configuration)
211
-            ->excludingRequest($request->getId())
212
-            ->fetch();
213
-
214
-        $this->assign('requestRelatedIpRequestsCount', count($relatedIpRequests));
215
-        $this->assign('requestRelatedIpRequests', $relatedIpRequests);
216
-
217
-        $this->assign('showRevealLink', false);
218
-        if ($request->getReserved() === $currentUser->getId() ||
219
-            $this->barrierTest('alwaysSeeHash', $currentUser, 'RequestData')
220
-        ) {
221
-            $this->assign('showRevealLink', true);
222
-            $this->assign('revealHash', $request->getRevealHash());
223
-        }
224
-
225
-        $this->setupForwardedIpData($request);
226
-    }
227
-
228
-    /**
229
-     * Adds checkuser request data to Smarty. DO NOT USE WITHOUT FIRST CHECKING THAT THE USER IS AUTHORISED!
230
-     *
231
-     * @param Request $request
232
-     */
233
-    protected function setupCheckUserData(Request $request)
234
-    {
235
-        $this->assign('requestUserAgent', $request->getUserAgent());
236
-    }
237
-
238
-    /**
239
-     * Sets up the basic data for this request, and adds it to Smarty
240
-     *
241
-     * @param Request           $request
242
-     * @param SiteConfiguration $config
243
-     */
244
-    protected function setupBasicData(Request $request, SiteConfiguration $config)
245
-    {
246
-        $this->assign('requestId', $request->getId());
247
-        $this->assign('updateVersion', $request->getUpdateVersion());
248
-        $this->assign('requestName', $request->getName());
249
-        $this->assign('requestDate', $request->getDate());
250
-        $this->assign('requestStatus', $request->getStatus());
251
-
252
-        $this->assign('requestIsClosed', !array_key_exists($request->getStatus(), $config->getRequestStates()));
253
-    }
254
-
255
-    /**
256
-     * Sets up the forwarded IP data for this request and adds it to Smarty
257
-     *
258
-     * @param Request $request
259
-     */
260
-    protected function setupForwardedIpData(Request $request)
261
-    {
262
-        if ($request->getForwardedIp() !== null) {
263
-            $requestProxyData = array(); // Initialize array to store data to be output in Smarty template.
264
-            $proxyIndex = 0;
265
-
266
-            // Assuming [client] <=> [proxy1] <=> [proxy2] <=> [proxy3] <=> [us], we will see an XFF header of [client],
267
-            // [proxy1], [proxy2], and our actual IP will be [proxy3]
268
-            $proxies = explode(",", $request->getForwardedIp());
269
-            $proxies[] = $request->getIp();
270
-
271
-            // Origin is the supposed "client" IP.
272
-            $origin = $proxies[0];
273
-            $this->assign("forwardedOrigin", $origin);
274
-
275
-            // We step through the servers in reverse order, from closest to furthest
276
-            $proxies = array_reverse($proxies);
277
-
278
-            // By default, we have trust, because the first in the chain is now REMOTE_ADDR, which is hardest to spoof.
279
-            $trust = true;
280
-
281
-            /**
282
-             * @var int    $index     The zero-based index of the proxy.
283
-             * @var string $proxyData The proxy IP address (although possibly not!)
284
-             */
285
-            foreach ($proxies as $index => $proxyData) {
286
-                $proxyAddress = trim($proxyData);
287
-                $requestProxyData[$proxyIndex]['ip'] = $proxyAddress;
288
-
289
-                // get data on this IP.
290
-                $thisProxyIsTrusted = $this->getXffTrustProvider()->isTrusted($proxyAddress);
291
-
292
-                $proxyIsInPrivateRange = $this->getXffTrustProvider()
293
-                    ->ipInRange(self::$rfc1918ips, $proxyAddress);
294
-
295
-                if (!$proxyIsInPrivateRange) {
296
-                    $proxyReverseDns = $this->getRdnsProvider()->getReverseDNS($proxyAddress);
297
-                    $proxyLocation = $this->getLocationProvider()->getIpLocation($proxyAddress);
298
-                }
299
-                else {
300
-                    // this is going to fail, so why bother trying?
301
-                    $proxyReverseDns = false;
302
-                    $proxyLocation = false;
303
-                }
304
-
305
-                // current trust chain status BEFORE this link
306
-                $preLinkTrust = $trust;
307
-
308
-                // is *this* link trusted? Note, this will be true even if there is an untrusted link before this!
309
-                $requestProxyData[$proxyIndex]['trustedlink'] = $thisProxyIsTrusted;
310
-
311
-                // set the trust status of the chain to this point
312
-                $trust = $trust & $thisProxyIsTrusted;
313
-
314
-                // If this is the origin address, and the chain was trusted before this point, then we can trust
315
-                // the origin.
316
-                if ($preLinkTrust && $proxyAddress == $origin) {
317
-                    // if this is the origin, then we are at the last point in the chain.
318
-                    // @todo: this is probably the cause of some bugs when an IP appears twice - we're missing a check
319
-                    // to see if this is *really* the last in the chain, rather than just the same IP as it.
320
-                    $trust = true;
321
-                }
322
-
323
-                $requestProxyData[$proxyIndex]['trust'] = $trust;
324
-
325
-                $requestProxyData[$proxyIndex]['rdnsfailed'] = $proxyReverseDns === false;
326
-                $requestProxyData[$proxyIndex]['rdns'] = $proxyReverseDns;
327
-                $requestProxyData[$proxyIndex]['routable'] = !$proxyIsInPrivateRange;
328
-
329
-                $requestProxyData[$proxyIndex]['location'] = $proxyLocation;
330
-
331
-                if ($proxyReverseDns === $proxyAddress && $proxyIsInPrivateRange === false) {
332
-                    $requestProxyData[$proxyIndex]['rdns'] = null;
333
-                }
334
-
335
-                $showLinks = (!$trust || $proxyAddress == $origin) && !$proxyIsInPrivateRange;
336
-                $requestProxyData[$proxyIndex]['showlinks'] = $showLinks;
337
-
338
-                $proxyIndex++;
339
-            }
340
-
341
-            $this->assign("requestProxyData", $requestProxyData);
342
-        }
343
-    }
26
+	/**
27
+	 * @var array Array of IP address classed as 'private' by RFC1918.
28
+	 */
29
+	protected static $rfc1918ips = array(
30
+		"10.0.0.0"    => "10.255.255.255",
31
+		"172.16.0.0"  => "172.31.255.255",
32
+		"192.168.0.0" => "192.168.255.255",
33
+		"169.254.0.0" => "169.254.255.255",
34
+		"127.0.0.0"   => "127.255.255.255",
35
+	);
36
+
37
+	/**
38
+	 * Gets a request object
39
+	 *
40
+	 * @param PdoDatabase $database  The database connection
41
+	 * @param int         $requestId The ID of the request to retrieve
42
+	 *
43
+	 * @return Request
44
+	 * @throws ApplicationLogicException
45
+	 */
46
+	protected function getRequest(PdoDatabase $database, $requestId)
47
+	{
48
+		if ($requestId === null) {
49
+			throw new ApplicationLogicException("No request specified");
50
+		}
51
+
52
+		$request = Request::getById($requestId, $database);
53
+		if ($request === false || !is_a($request, Request::class)) {
54
+			throw new ApplicationLogicException('Could not load the requested request!');
55
+		}
56
+
57
+		return $request;
58
+	}
59
+
60
+	/**
61
+	 * Returns a value stating whether the user is allowed to see private data or not
62
+	 *
63
+	 * @param Request $request
64
+	 * @param User    $currentUser
65
+	 *
66
+	 * @return bool
67
+	 * @category Security-Critical
68
+	 */
69
+	protected function isAllowedPrivateData(Request $request, User $currentUser)
70
+	{
71
+		// Test the main security barrier for private data access using SecurityManager
72
+		if ($this->barrierTest('alwaysSeePrivateData', $currentUser, 'RequestData')) {
73
+			// Tool admins/check-users can always see private data
74
+			return true;
75
+		}
76
+
77
+		// reserving user is allowed to see the data
78
+		if ($currentUser->getId() === $request->getReserved()
79
+			&& $request->getReserved() !== null
80
+			&& $this->barrierTest('seePrivateDataWhenReserved', $currentUser, 'RequestData')
81
+		) {
82
+			return true;
83
+		}
84
+
85
+		// user has the reveal hash
86
+		if (WebRequest::getString('hash') === $request->getRevealHash()
87
+			&& $this->barrierTest('seePrivateDataWithHash', $currentUser, 'RequestData')
88
+		) {
89
+			return true;
90
+		}
91
+
92
+		// nope. Not allowed.
93
+		return false;
94
+	}
95
+
96
+	/**
97
+	 * Tests the security barrier for a specified action.
98
+	 *
99
+	 * Don't use within templates
100
+	 *
101
+	 * @param string      $action
102
+	 *
103
+	 * @param User        $user
104
+	 * @param null|string $pageName
105
+	 *
106
+	 * @return bool
107
+	 * @category Security-Critical
108
+	 */
109
+	abstract protected function barrierTest($action, User $user, $pageName = null);
110
+
111
+	/**
112
+	 * Gets the name of the route that has been passed from the request router.
113
+	 * @return string
114
+	 */
115
+	abstract protected function getRouteName();
116
+
117
+	/** @return SecurityManager */
118
+	abstract protected function getSecurityManager();
119
+
120
+	/**
121
+	 * Sets the name of the template this page should display.
122
+	 *
123
+	 * @param string $name
124
+	 */
125
+	abstract protected function setTemplate($name);
126
+
127
+	/** @return IXffTrustProvider */
128
+	abstract protected function getXffTrustProvider();
129
+
130
+	/** @return ILocationProvider */
131
+	abstract protected function getLocationProvider();
132
+
133
+	/** @return IRDnsProvider */
134
+	abstract protected function getRdnsProvider();
135
+
136
+	/**
137
+	 * Assigns a Smarty variable
138
+	 *
139
+	 * @param  array|string $name  the template variable name(s)
140
+	 * @param  mixed        $value the value to assign
141
+	 */
142
+	abstract protected function assign($name, $value);
143
+
144
+	/**
145
+	 * @param int         $requestReservationId
146
+	 * @param PdoDatabase $database
147
+	 * @param User        $currentUser
148
+	 */
149
+	protected function setupReservationDetails($requestReservationId, PdoDatabase $database, User $currentUser)
150
+	{
151
+		$requestIsReserved = $requestReservationId !== null;
152
+		$this->assign('requestIsReserved', $requestIsReserved);
153
+		$this->assign('requestIsReservedByMe', false);
154
+
155
+		if ($requestIsReserved) {
156
+			$this->assign('requestReservedByName', User::getById($requestReservationId, $database)->getUsername());
157
+			$this->assign('requestReservedById', $requestReservationId);
158
+
159
+			if ($requestReservationId === $currentUser->getId()) {
160
+				$this->assign('requestIsReservedByMe', true);
161
+			}
162
+		}
163
+
164
+		$this->assign('canBreakReservation', $this->barrierTest('force', $currentUser, PageBreakReservation::class));
165
+	}
166
+
167
+	/**
168
+	 * Adds private request data to Smarty. DO NOT USE WITHOUT FIRST CHECKING THAT THE USER IS AUTHORISED!
169
+	 *
170
+	 * @param Request           $request
171
+	 * @param User              $currentUser
172
+	 * @param SiteConfiguration $configuration
173
+	 *
174
+	 * @param PdoDatabase       $database
175
+	 */
176
+	protected function setupPrivateData(
177
+		$request,
178
+		User $currentUser,
179
+		SiteConfiguration $configuration,
180
+		PdoDatabase $database
181
+	) {
182
+		$xffProvider = $this->getXffTrustProvider();
183
+
184
+		$relatedEmailRequests = RequestSearchHelper::get($database)
185
+			->byEmailAddress($request->getEmail())
186
+			->withConfirmedEmail()
187
+			->excludingPurgedData($configuration)
188
+			->excludingRequest($request->getId())
189
+			->fetch();
190
+
191
+		$this->assign('requestEmail', $request->getEmail());
192
+		$emailDomain = explode("@", $request->getEmail())[1];
193
+		$this->assign("emailurl", $emailDomain);
194
+		$this->assign('requestRelatedEmailRequestsCount', count($relatedEmailRequests));
195
+		$this->assign('requestRelatedEmailRequests', $relatedEmailRequests);
196
+
197
+		$trustedIp = $xffProvider->getTrustedClientIp($request->getIp(), $request->getForwardedIp());
198
+		$this->assign('requestTrustedIp', $trustedIp);
199
+		$this->assign('requestRealIp', $request->getIp());
200
+		$this->assign('requestForwardedIp', $request->getForwardedIp());
201
+
202
+		$trustedIpLocation = $this->getLocationProvider()->getIpLocation($trustedIp);
203
+		$this->assign('requestTrustedIpLocation', $trustedIpLocation);
204
+
205
+		$this->assign('requestHasForwardedIp', $request->getForwardedIp() !== null);
206
+
207
+		$relatedIpRequests = RequestSearchHelper::get($database)
208
+			->byIp($trustedIp)
209
+			->withConfirmedEmail()
210
+			->excludingPurgedData($configuration)
211
+			->excludingRequest($request->getId())
212
+			->fetch();
213
+
214
+		$this->assign('requestRelatedIpRequestsCount', count($relatedIpRequests));
215
+		$this->assign('requestRelatedIpRequests', $relatedIpRequests);
216
+
217
+		$this->assign('showRevealLink', false);
218
+		if ($request->getReserved() === $currentUser->getId() ||
219
+			$this->barrierTest('alwaysSeeHash', $currentUser, 'RequestData')
220
+		) {
221
+			$this->assign('showRevealLink', true);
222
+			$this->assign('revealHash', $request->getRevealHash());
223
+		}
224
+
225
+		$this->setupForwardedIpData($request);
226
+	}
227
+
228
+	/**
229
+	 * Adds checkuser request data to Smarty. DO NOT USE WITHOUT FIRST CHECKING THAT THE USER IS AUTHORISED!
230
+	 *
231
+	 * @param Request $request
232
+	 */
233
+	protected function setupCheckUserData(Request $request)
234
+	{
235
+		$this->assign('requestUserAgent', $request->getUserAgent());
236
+	}
237
+
238
+	/**
239
+	 * Sets up the basic data for this request, and adds it to Smarty
240
+	 *
241
+	 * @param Request           $request
242
+	 * @param SiteConfiguration $config
243
+	 */
244
+	protected function setupBasicData(Request $request, SiteConfiguration $config)
245
+	{
246
+		$this->assign('requestId', $request->getId());
247
+		$this->assign('updateVersion', $request->getUpdateVersion());
248
+		$this->assign('requestName', $request->getName());
249
+		$this->assign('requestDate', $request->getDate());
250
+		$this->assign('requestStatus', $request->getStatus());
251
+
252
+		$this->assign('requestIsClosed', !array_key_exists($request->getStatus(), $config->getRequestStates()));
253
+	}
254
+
255
+	/**
256
+	 * Sets up the forwarded IP data for this request and adds it to Smarty
257
+	 *
258
+	 * @param Request $request
259
+	 */
260
+	protected function setupForwardedIpData(Request $request)
261
+	{
262
+		if ($request->getForwardedIp() !== null) {
263
+			$requestProxyData = array(); // Initialize array to store data to be output in Smarty template.
264
+			$proxyIndex = 0;
265
+
266
+			// Assuming [client] <=> [proxy1] <=> [proxy2] <=> [proxy3] <=> [us], we will see an XFF header of [client],
267
+			// [proxy1], [proxy2], and our actual IP will be [proxy3]
268
+			$proxies = explode(",", $request->getForwardedIp());
269
+			$proxies[] = $request->getIp();
270
+
271
+			// Origin is the supposed "client" IP.
272
+			$origin = $proxies[0];
273
+			$this->assign("forwardedOrigin", $origin);
274
+
275
+			// We step through the servers in reverse order, from closest to furthest
276
+			$proxies = array_reverse($proxies);
277
+
278
+			// By default, we have trust, because the first in the chain is now REMOTE_ADDR, which is hardest to spoof.
279
+			$trust = true;
280
+
281
+			/**
282
+			 * @var int    $index     The zero-based index of the proxy.
283
+			 * @var string $proxyData The proxy IP address (although possibly not!)
284
+			 */
285
+			foreach ($proxies as $index => $proxyData) {
286
+				$proxyAddress = trim($proxyData);
287
+				$requestProxyData[$proxyIndex]['ip'] = $proxyAddress;
288
+
289
+				// get data on this IP.
290
+				$thisProxyIsTrusted = $this->getXffTrustProvider()->isTrusted($proxyAddress);
291
+
292
+				$proxyIsInPrivateRange = $this->getXffTrustProvider()
293
+					->ipInRange(self::$rfc1918ips, $proxyAddress);
294
+
295
+				if (!$proxyIsInPrivateRange) {
296
+					$proxyReverseDns = $this->getRdnsProvider()->getReverseDNS($proxyAddress);
297
+					$proxyLocation = $this->getLocationProvider()->getIpLocation($proxyAddress);
298
+				}
299
+				else {
300
+					// this is going to fail, so why bother trying?
301
+					$proxyReverseDns = false;
302
+					$proxyLocation = false;
303
+				}
304
+
305
+				// current trust chain status BEFORE this link
306
+				$preLinkTrust = $trust;
307
+
308
+				// is *this* link trusted? Note, this will be true even if there is an untrusted link before this!
309
+				$requestProxyData[$proxyIndex]['trustedlink'] = $thisProxyIsTrusted;
310
+
311
+				// set the trust status of the chain to this point
312
+				$trust = $trust & $thisProxyIsTrusted;
313
+
314
+				// If this is the origin address, and the chain was trusted before this point, then we can trust
315
+				// the origin.
316
+				if ($preLinkTrust && $proxyAddress == $origin) {
317
+					// if this is the origin, then we are at the last point in the chain.
318
+					// @todo: this is probably the cause of some bugs when an IP appears twice - we're missing a check
319
+					// to see if this is *really* the last in the chain, rather than just the same IP as it.
320
+					$trust = true;
321
+				}
322
+
323
+				$requestProxyData[$proxyIndex]['trust'] = $trust;
324
+
325
+				$requestProxyData[$proxyIndex]['rdnsfailed'] = $proxyReverseDns === false;
326
+				$requestProxyData[$proxyIndex]['rdns'] = $proxyReverseDns;
327
+				$requestProxyData[$proxyIndex]['routable'] = !$proxyIsInPrivateRange;
328
+
329
+				$requestProxyData[$proxyIndex]['location'] = $proxyLocation;
330
+
331
+				if ($proxyReverseDns === $proxyAddress && $proxyIsInPrivateRange === false) {
332
+					$requestProxyData[$proxyIndex]['rdns'] = null;
333
+				}
334
+
335
+				$showLinks = (!$trust || $proxyAddress == $origin) && !$proxyIsInPrivateRange;
336
+				$requestProxyData[$proxyIndex]['showlinks'] = $showLinks;
337
+
338
+				$proxyIndex++;
339
+			}
340
+
341
+			$this->assign("requestProxyData", $requestProxyData);
342
+		}
343
+	}
344 344
 }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -295,8 +295,7 @@
 block discarded – undo
295 295
                 if (!$proxyIsInPrivateRange) {
296 296
                     $proxyReverseDns = $this->getRdnsProvider()->getReverseDNS($proxyAddress);
297 297
                     $proxyLocation = $this->getLocationProvider()->getIpLocation($proxyAddress);
298
-                }
299
-                else {
298
+                } else {
300 299
                     // this is going to fail, so why bother trying?
301 300
                     $proxyReverseDns = false;
302 301
                     $proxyLocation = false;
Please login to merge, or discard this patch.
includes/Pages/Registration/PageRegisterBase.php 3 patches
Doc Comments   +8 added lines, -5 removed lines patch added patch discarded remove patch
@@ -44,6 +44,9 @@  discard block
 block discarded – undo
44 44
         }
45 45
     }
46 46
 
47
+    /**
48
+     * @return string
49
+     */
47 50
     protected abstract function getRegistrationTemplate();
48 51
 
49 52
     protected function isProtectedPage()
@@ -70,12 +73,12 @@  discard block
 block discarded – undo
70 73
     }
71 74
 
72 75
     /**
73
-     * @param $emailAddress
74
-     * @param $password
75
-     * @param $username
76
+     * @param null|string $emailAddress
77
+     * @param null|string $password
78
+     * @param null|string $username
76 79
      * @param $useOAuthSignup
77
-     * @param $confirmationId
78
-     * @param $onwikiUsername
80
+     * @param null|integer $confirmationId
81
+     * @param null|string $onwikiUsername
79 82
      *
80 83
      * @throws ApplicationLogicException
81 84
      */
Please login to merge, or discard this patch.
Indentation   +198 added lines, -198 removed lines patch added patch discarded remove patch
@@ -18,202 +18,202 @@
 block discarded – undo
18 18
 
19 19
 abstract class PageRegisterBase extends InternalPageBase
20 20
 {
21
-    /**
22
-     * Main function for this page, when no specific actions are called.
23
-     */
24
-    protected function main()
25
-    {
26
-        $useOAuthSignup = $this->getSiteConfiguration()->getUseOAuthSignup();
27
-
28
-        // Dual-mode page
29
-        if (WebRequest::wasPosted()) {
30
-            $this->validateCSRFToken();
31
-
32
-            try {
33
-                $this->handlePost($useOAuthSignup);
34
-            }
35
-            catch (ApplicationLogicException $ex) {
36
-                SessionAlert::error($ex->getMessage());
37
-                $this->redirect('register');
38
-            }
39
-        }
40
-        else {
41
-            $this->assignCSRFToken();
42
-            $this->assign("useOAuthSignup", $useOAuthSignup);
43
-            $this->setTemplate($this->getRegistrationTemplate());
44
-        }
45
-    }
46
-
47
-    protected abstract function getRegistrationTemplate();
48
-
49
-    protected function isProtectedPage()
50
-    {
51
-        return false;
52
-    }
53
-
54
-    /**
55
-     * @param string $emailAddress
56
-     *
57
-     * @throws ApplicationLogicException
58
-     */
59
-    protected function validateUniqueEmail($emailAddress)
60
-    {
61
-        $query = 'SELECT COUNT(id) FROM user WHERE email = :email';
62
-        $statement = $this->getDatabase()->prepare($query);
63
-        $statement->execute(array(':email' => $emailAddress));
64
-
65
-        if ($statement->fetchColumn() > 0) {
66
-            throw new ApplicationLogicException('That email address is already in use on this system.');
67
-        }
68
-
69
-        $statement->closeCursor();
70
-    }
71
-
72
-    /**
73
-     * @param $emailAddress
74
-     * @param $password
75
-     * @param $username
76
-     * @param $useOAuthSignup
77
-     * @param $confirmationId
78
-     * @param $onwikiUsername
79
-     *
80
-     * @throws ApplicationLogicException
81
-     */
82
-    protected function validateRequest(
83
-        $emailAddress,
84
-        $password,
85
-        $username,
86
-        $useOAuthSignup,
87
-        $confirmationId,
88
-        $onwikiUsername
89
-    ) {
90
-        if (!WebRequest::postBoolean('guidelines')) {
91
-            throw new ApplicationLogicException('You must read the interface guidelines before your request may be submitted.');
92
-        }
93
-
94
-        $this->validateGeneralInformation($emailAddress, $password, $username);
95
-        $this->validateUniqueEmail($emailAddress);
96
-        $this->validateNonOAuthFields($useOAuthSignup, $confirmationId, $onwikiUsername);
97
-    }
98
-
99
-    /**
100
-     * @param $useOAuthSignup
101
-     * @param $confirmationId
102
-     * @param $onwikiUsername
103
-     *
104
-     * @throws ApplicationLogicException
105
-     */
106
-    protected function validateNonOAuthFields($useOAuthSignup, $confirmationId, $onwikiUsername)
107
-    {
108
-        if (!$useOAuthSignup) {
109
-            if ($confirmationId === null || $confirmationId <= 0) {
110
-                throw new ApplicationLogicException('Please enter the revision id of your confirmation edit.');
111
-            }
112
-
113
-            if ($onwikiUsername === null) {
114
-                throw new ApplicationLogicException('Please specify your on-wiki username.');
115
-            }
116
-        }
117
-    }
118
-
119
-    /**
120
-     * @param $emailAddress
121
-     * @param $password
122
-     * @param $username
123
-     *
124
-     * @throws ApplicationLogicException
125
-     */
126
-    protected function validateGeneralInformation($emailAddress, $password, $username)
127
-    {
128
-        if ($emailAddress === null) {
129
-            throw new ApplicationLogicException('Your email address appears to be invalid!');
130
-        }
131
-
132
-        if ($password !== WebRequest::postString('pass2')) {
133
-            throw new ApplicationLogicException('Your passwords did not match, please try again.');
134
-        }
135
-
136
-        if (User::getByUsername($username, $this->getDatabase()) !== false) {
137
-            throw new ApplicationLogicException('That username is already in use on this system.');
138
-        }
139
-    }
140
-
141
-    /**
142
-     * @param $useOAuthSignup
143
-     *
144
-     * @throws ApplicationLogicException
145
-     * @throws \Exception
146
-     */
147
-    protected function handlePost($useOAuthSignup)
148
-    {
149
-        // Get the data
150
-        $emailAddress = WebRequest::postEmail('email');
151
-        $password = WebRequest::postString('pass');
152
-        $username = WebRequest::postString('name');
153
-
154
-        // Only set if OAuth is disabled
155
-        $confirmationId = WebRequest::postInt('conf_revid');
156
-        $onwikiUsername = WebRequest::postString('wname');
157
-
158
-        // Do some validation
159
-        $this->validateRequest($emailAddress, $password, $username, $useOAuthSignup, $confirmationId,
160
-            $onwikiUsername);
161
-
162
-        $database = $this->getDatabase();
163
-
164
-        $user = new User();
165
-        $user->setDatabase($database);
166
-
167
-        $user->setUsername($username);
168
-        $user->setPassword($password);
169
-        $user->setEmail($emailAddress);
170
-
171
-        if (!$useOAuthSignup) {
172
-            $user->setOnWikiName($onwikiUsername);
173
-            $user->setConfirmationDiff($confirmationId);
174
-        }
175
-
176
-        $user->save();
177
-
178
-        $defaultRole = $this->getDefaultRole();
179
-
180
-        $role = new UserRole();
181
-        $role->setDatabase($database);
182
-        $role->setUser($user->getId());
183
-        $role->setRole($defaultRole);
184
-        $role->save();
185
-
186
-        // Log now to get the signup date.
187
-        Logger::newUser($database, $user);
188
-        Logger::userRolesEdited($database, $user, 'Registration', array($defaultRole), array());
189
-
190
-        if ($useOAuthSignup) {
191
-            $oauthHelper = $this->getOAuthHelper();
192
-
193
-            $requestToken = $oauthHelper->getRequestToken();
194
-            $user->setOAuthRequestToken($requestToken->key);
195
-            $user->setOAuthRequestSecret($requestToken->secret);
196
-            $user->save();
197
-
198
-            WebRequest::setPartialLogin($user);
199
-
200
-            $this->redirectUrl($oauthHelper->getAuthoriseUrl($requestToken->key));
201
-        }
202
-        else {
203
-            // only notify if we're not using the oauth signup.
204
-            $this->getNotificationHelper()->userNew($user);
205
-            WebRequest::setLoggedInUser($user);
206
-            $this->redirect('preferences');
207
-        }
208
-    }
209
-
210
-    protected abstract function getDefaultRole();
211
-
212
-    /**
213
-     * Entry point for registration complete
214
-     */
215
-    protected function done()
216
-    {
217
-        $this->setTemplate('registration/alert-registrationcomplete.tpl');
218
-    }
21
+	/**
22
+	 * Main function for this page, when no specific actions are called.
23
+	 */
24
+	protected function main()
25
+	{
26
+		$useOAuthSignup = $this->getSiteConfiguration()->getUseOAuthSignup();
27
+
28
+		// Dual-mode page
29
+		if (WebRequest::wasPosted()) {
30
+			$this->validateCSRFToken();
31
+
32
+			try {
33
+				$this->handlePost($useOAuthSignup);
34
+			}
35
+			catch (ApplicationLogicException $ex) {
36
+				SessionAlert::error($ex->getMessage());
37
+				$this->redirect('register');
38
+			}
39
+		}
40
+		else {
41
+			$this->assignCSRFToken();
42
+			$this->assign("useOAuthSignup", $useOAuthSignup);
43
+			$this->setTemplate($this->getRegistrationTemplate());
44
+		}
45
+	}
46
+
47
+	protected abstract function getRegistrationTemplate();
48
+
49
+	protected function isProtectedPage()
50
+	{
51
+		return false;
52
+	}
53
+
54
+	/**
55
+	 * @param string $emailAddress
56
+	 *
57
+	 * @throws ApplicationLogicException
58
+	 */
59
+	protected function validateUniqueEmail($emailAddress)
60
+	{
61
+		$query = 'SELECT COUNT(id) FROM user WHERE email = :email';
62
+		$statement = $this->getDatabase()->prepare($query);
63
+		$statement->execute(array(':email' => $emailAddress));
64
+
65
+		if ($statement->fetchColumn() > 0) {
66
+			throw new ApplicationLogicException('That email address is already in use on this system.');
67
+		}
68
+
69
+		$statement->closeCursor();
70
+	}
71
+
72
+	/**
73
+	 * @param $emailAddress
74
+	 * @param $password
75
+	 * @param $username
76
+	 * @param $useOAuthSignup
77
+	 * @param $confirmationId
78
+	 * @param $onwikiUsername
79
+	 *
80
+	 * @throws ApplicationLogicException
81
+	 */
82
+	protected function validateRequest(
83
+		$emailAddress,
84
+		$password,
85
+		$username,
86
+		$useOAuthSignup,
87
+		$confirmationId,
88
+		$onwikiUsername
89
+	) {
90
+		if (!WebRequest::postBoolean('guidelines')) {
91
+			throw new ApplicationLogicException('You must read the interface guidelines before your request may be submitted.');
92
+		}
93
+
94
+		$this->validateGeneralInformation($emailAddress, $password, $username);
95
+		$this->validateUniqueEmail($emailAddress);
96
+		$this->validateNonOAuthFields($useOAuthSignup, $confirmationId, $onwikiUsername);
97
+	}
98
+
99
+	/**
100
+	 * @param $useOAuthSignup
101
+	 * @param $confirmationId
102
+	 * @param $onwikiUsername
103
+	 *
104
+	 * @throws ApplicationLogicException
105
+	 */
106
+	protected function validateNonOAuthFields($useOAuthSignup, $confirmationId, $onwikiUsername)
107
+	{
108
+		if (!$useOAuthSignup) {
109
+			if ($confirmationId === null || $confirmationId <= 0) {
110
+				throw new ApplicationLogicException('Please enter the revision id of your confirmation edit.');
111
+			}
112
+
113
+			if ($onwikiUsername === null) {
114
+				throw new ApplicationLogicException('Please specify your on-wiki username.');
115
+			}
116
+		}
117
+	}
118
+
119
+	/**
120
+	 * @param $emailAddress
121
+	 * @param $password
122
+	 * @param $username
123
+	 *
124
+	 * @throws ApplicationLogicException
125
+	 */
126
+	protected function validateGeneralInformation($emailAddress, $password, $username)
127
+	{
128
+		if ($emailAddress === null) {
129
+			throw new ApplicationLogicException('Your email address appears to be invalid!');
130
+		}
131
+
132
+		if ($password !== WebRequest::postString('pass2')) {
133
+			throw new ApplicationLogicException('Your passwords did not match, please try again.');
134
+		}
135
+
136
+		if (User::getByUsername($username, $this->getDatabase()) !== false) {
137
+			throw new ApplicationLogicException('That username is already in use on this system.');
138
+		}
139
+	}
140
+
141
+	/**
142
+	 * @param $useOAuthSignup
143
+	 *
144
+	 * @throws ApplicationLogicException
145
+	 * @throws \Exception
146
+	 */
147
+	protected function handlePost($useOAuthSignup)
148
+	{
149
+		// Get the data
150
+		$emailAddress = WebRequest::postEmail('email');
151
+		$password = WebRequest::postString('pass');
152
+		$username = WebRequest::postString('name');
153
+
154
+		// Only set if OAuth is disabled
155
+		$confirmationId = WebRequest::postInt('conf_revid');
156
+		$onwikiUsername = WebRequest::postString('wname');
157
+
158
+		// Do some validation
159
+		$this->validateRequest($emailAddress, $password, $username, $useOAuthSignup, $confirmationId,
160
+			$onwikiUsername);
161
+
162
+		$database = $this->getDatabase();
163
+
164
+		$user = new User();
165
+		$user->setDatabase($database);
166
+
167
+		$user->setUsername($username);
168
+		$user->setPassword($password);
169
+		$user->setEmail($emailAddress);
170
+
171
+		if (!$useOAuthSignup) {
172
+			$user->setOnWikiName($onwikiUsername);
173
+			$user->setConfirmationDiff($confirmationId);
174
+		}
175
+
176
+		$user->save();
177
+
178
+		$defaultRole = $this->getDefaultRole();
179
+
180
+		$role = new UserRole();
181
+		$role->setDatabase($database);
182
+		$role->setUser($user->getId());
183
+		$role->setRole($defaultRole);
184
+		$role->save();
185
+
186
+		// Log now to get the signup date.
187
+		Logger::newUser($database, $user);
188
+		Logger::userRolesEdited($database, $user, 'Registration', array($defaultRole), array());
189
+
190
+		if ($useOAuthSignup) {
191
+			$oauthHelper = $this->getOAuthHelper();
192
+
193
+			$requestToken = $oauthHelper->getRequestToken();
194
+			$user->setOAuthRequestToken($requestToken->key);
195
+			$user->setOAuthRequestSecret($requestToken->secret);
196
+			$user->save();
197
+
198
+			WebRequest::setPartialLogin($user);
199
+
200
+			$this->redirectUrl($oauthHelper->getAuthoriseUrl($requestToken->key));
201
+		}
202
+		else {
203
+			// only notify if we're not using the oauth signup.
204
+			$this->getNotificationHelper()->userNew($user);
205
+			WebRequest::setLoggedInUser($user);
206
+			$this->redirect('preferences');
207
+		}
208
+	}
209
+
210
+	protected abstract function getDefaultRole();
211
+
212
+	/**
213
+	 * Entry point for registration complete
214
+	 */
215
+	protected function done()
216
+	{
217
+		$this->setTemplate('registration/alert-registrationcomplete.tpl');
218
+	}
219 219
 }
Please login to merge, or discard this patch.
Braces   +2 added lines, -4 removed lines patch added patch discarded remove patch
@@ -36,8 +36,7 @@  discard block
 block discarded – undo
36 36
                 SessionAlert::error($ex->getMessage());
37 37
                 $this->redirect('register');
38 38
             }
39
-        }
40
-        else {
39
+        } else {
41 40
             $this->assignCSRFToken();
42 41
             $this->assign("useOAuthSignup", $useOAuthSignup);
43 42
             $this->setTemplate($this->getRegistrationTemplate());
@@ -198,8 +197,7 @@  discard block
 block discarded – undo
198 197
             WebRequest::setPartialLogin($user);
199 198
 
200 199
             $this->redirectUrl($oauthHelper->getAuthoriseUrl($requestToken->key));
201
-        }
202
-        else {
200
+        } else {
203 201
             // only notify if we're not using the oauth signup.
204 202
             $this->getNotificationHelper()->userNew($user);
205 203
             WebRequest::setLoggedInUser($user);
Please login to merge, or discard this patch.
includes/Router/PublicRequestRouter.php 2 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -47,7 +47,7 @@
 block discarded – undo
47 47
     /**
48 48
      * Gets the default route if no explicit route is requested.
49 49
      *
50
-     * @return callable
50
+     * @return string[]
51 51
      */
52 52
     protected function getDefaultRoute()
53 53
     {
Please login to merge, or discard this patch.
Indentation   +37 added lines, -37 removed lines patch added patch discarded remove patch
@@ -15,42 +15,42 @@
 block discarded – undo
15 15
 
16 16
 class PublicRequestRouter extends RequestRouter
17 17
 {
18
-    /**
19
-     * Gets the route map to be used by this request router.
20
-     *
21
-     * @return array
22
-     */
23
-    protected function getRouteMap()
24
-    {
25
-        return array(
26
-            // Page showing a message stating the request has been submitted to our internal queues
27
-            'requestSubmitted'          =>
28
-                array(
29
-                    'class'   => PageRequestSubmitted::class,
30
-                    'actions' => array(),
31
-                ),
32
-            // Page showing a message stating that email confirmation is required to continue
33
-            'emailConfirmationRequired' =>
34
-                array(
35
-                    'class'   => PageEmailConfirmationRequired::class,
36
-                    'actions' => array(),
37
-                ),
38
-            // Action page which handles email confirmation
39
-            'confirmEmail'              =>
40
-                array(
41
-                    'class'   => PageConfirmEmail::class,
42
-                    'actions' => array(),
43
-                ),
44
-        );
45
-    }
18
+	/**
19
+	 * Gets the route map to be used by this request router.
20
+	 *
21
+	 * @return array
22
+	 */
23
+	protected function getRouteMap()
24
+	{
25
+		return array(
26
+			// Page showing a message stating the request has been submitted to our internal queues
27
+			'requestSubmitted'          =>
28
+				array(
29
+					'class'   => PageRequestSubmitted::class,
30
+					'actions' => array(),
31
+				),
32
+			// Page showing a message stating that email confirmation is required to continue
33
+			'emailConfirmationRequired' =>
34
+				array(
35
+					'class'   => PageEmailConfirmationRequired::class,
36
+					'actions' => array(),
37
+				),
38
+			// Action page which handles email confirmation
39
+			'confirmEmail'              =>
40
+				array(
41
+					'class'   => PageConfirmEmail::class,
42
+					'actions' => array(),
43
+				),
44
+		);
45
+	}
46 46
 
47
-    /**
48
-     * Gets the default route if no explicit route is requested.
49
-     *
50
-     * @return callable
51
-     */
52
-    protected function getDefaultRoute()
53
-    {
54
-        return array(PageRequestAccount::class, 'main');
55
-    }
47
+	/**
48
+	 * Gets the default route if no explicit route is requested.
49
+	 *
50
+	 * @return callable
51
+	 */
52
+	protected function getDefaultRoute()
53
+	{
54
+		return array(PageRequestAccount::class, 'main');
55
+	}
56 56
 }
57 57
\ No newline at end of file
Please login to merge, or discard this patch.
includes/Router/RequestRouter.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -440,7 +440,7 @@
 block discarded – undo
440 440
     }
441 441
 
442 442
     /**
443
-     * @return callable
443
+     * @return string[]
444 444
      */
445 445
     protected function getDefaultRoute()
446 446
     {
Please login to merge, or discard this patch.
Indentation   +391 added lines, -391 removed lines patch added patch discarded remove patch
@@ -55,395 +55,395 @@
 block discarded – undo
55 55
  */
56 56
 class RequestRouter implements IRequestRouter
57 57
 {
58
-    /**
59
-     * This is the core routing table for the application. The basic idea is:
60
-     *
61
-     *      array(
62
-     *          "foo" =>
63
-     *              array(
64
-     *                  "class"   => PageFoo::class,
65
-     *                  "actions" => array("bar", "other")
66
-     *              ),
67
-     * );
68
-     *
69
-     * Things to note:
70
-     *     - If no page is requested, we go to PageMain. PageMain can't have actions defined.
71
-     *
72
-     *     - If a page is defined and requested, but no action is requested, go to that page's main() method
73
-     *     - If a page is defined and requested, and an action is defined and requested, go to that action's method.
74
-     *     - If a page is defined and requested, and an action NOT defined and requested, go to Page404 and it's main()
75
-     *       method.
76
-     *     - If a page is NOT defined and requested, go to Page404 and it's main() method.
77
-     *
78
-     *     - Query parameters are ignored.
79
-     *
80
-     * The key point here is request routing with validation that this is allowed, before we start hitting the
81
-     * filesystem through the AutoLoader, and opening random files. Also, so that we validate the action requested
82
-     * before we start calling random methods through the web UI.
83
-     *
84
-     * Examples:
85
-     * /internal.php                => returns instance of PageMain, routed to main()
86
-     * /internal.php?query          => returns instance of PageMain, routed to main()
87
-     * /internal.php/foo            => returns instance of PageFoo, routed to main()
88
-     * /internal.php/foo?query      => returns instance of PageFoo, routed to main()
89
-     * /internal.php/foo/bar        => returns instance of PageFoo, routed to bar()
90
-     * /internal.php/foo/bar?query  => returns instance of PageFoo, routed to bar()
91
-     * /internal.php/foo/baz        => returns instance of Page404, routed to main()
92
-     * /internal.php/foo/baz?query  => returns instance of Page404, routed to main()
93
-     * /internal.php/bar            => returns instance of Page404, routed to main()
94
-     * /internal.php/bar?query      => returns instance of Page404, routed to main()
95
-     * /internal.php/bar/baz        => returns instance of Page404, routed to main()
96
-     * /internal.php/bar/baz?query  => returns instance of Page404, routed to main()
97
-     *
98
-     * Take care when changing this - a lot of places rely on the array key for redirects and other links. If you need
99
-     * to change the key, then you'll likely have to update a lot of files.
100
-     *
101
-     * @var array
102
-     */
103
-    private $routeMap = array(
104
-
105
-        //////////////////////////////////////////////////////////////////////////////////////////////////
106
-        // Login and registration
107
-        'logout'                      =>
108
-            array(
109
-                'class'   => PageLogout::class,
110
-                'actions' => array(),
111
-            ),
112
-        'login'                       =>
113
-            array(
114
-                'class'   => PageLogin::class,
115
-                'actions' => array(),
116
-            ),
117
-        'forgotPassword'              =>
118
-            array(
119
-                'class'   => PageForgotPassword::class,
120
-                'actions' => array('reset'),
121
-            ),
122
-        'register'                    =>
123
-            array(
124
-                'class'   => PageRegisterOption::class,
125
-                'actions' => array(),
126
-            ),
127
-        'register/standard'           =>
128
-            array(
129
-                'class'   => PageRegisterStandard::class,
130
-                'actions' => array('done'),
131
-            ),
132
-
133
-        //////////////////////////////////////////////////////////////////////////////////////////////////
134
-        // Discovery
135
-        'search'                      =>
136
-            array(
137
-                'class'   => PageSearch::class,
138
-                'actions' => array(),
139
-            ),
140
-        'logs'                        =>
141
-            array(
142
-                'class'   => PageLog::class,
143
-                'actions' => array(),
144
-            ),
145
-
146
-        //////////////////////////////////////////////////////////////////////////////////////////////////
147
-        // Administration
148
-        'bans'                        =>
149
-            array(
150
-                'class'   => PageBan::class,
151
-                'actions' => array('set', 'remove'),
152
-            ),
153
-        'userManagement'              =>
154
-            array(
155
-                'class'   => PageUserManagement::class,
156
-                'actions' => array(
157
-                    'approve',
158
-                    'decline',
159
-                    'rename',
160
-                    'editUser',
161
-                    'suspend',
162
-                    'editRoles',
163
-                ),
164
-            ),
165
-        'siteNotice'                  =>
166
-            array(
167
-                'class'   => PageSiteNotice::class,
168
-                'actions' => array(),
169
-            ),
170
-        'emailManagement'             =>
171
-            array(
172
-                'class'   => PageEmailManagement::class,
173
-                'actions' => array('create', 'edit', 'view'),
174
-            ),
175
-
176
-        //////////////////////////////////////////////////////////////////////////////////////////////////
177
-        // Personal preferences
178
-        'preferences'                 =>
179
-            array(
180
-                'class'   => PagePreferences::class,
181
-                'actions' => array('changePassword'),
182
-            ),
183
-        'oauth'                       =>
184
-            array(
185
-                'class'   => PageOAuth::class,
186
-                'actions' => array('detach', 'attach'),
187
-            ),
188
-
189
-        //////////////////////////////////////////////////////////////////////////////////////////////////
190
-        // Welcomer configuration
191
-        'welcomeTemplates'            =>
192
-            array(
193
-                'class'   => PageWelcomeTemplateManagement::class,
194
-                'actions' => array('select', 'edit', 'delete', 'add', 'view'),
195
-            ),
196
-
197
-        //////////////////////////////////////////////////////////////////////////////////////////////////
198
-        // Statistics
199
-        'statistics'                  =>
200
-            array(
201
-                'class'   => StatsMain::class,
202
-                'actions' => array(),
203
-            ),
204
-        'statistics/fastCloses'       =>
205
-            array(
206
-                'class'   => StatsFastCloses::class,
207
-                'actions' => array(),
208
-            ),
209
-        'statistics/inactiveUsers'    =>
210
-            array(
211
-                'class'   => StatsInactiveUsers::class,
212
-                'actions' => array(),
213
-            ),
214
-        'statistics/monthlyStats'     =>
215
-            array(
216
-                'class'   => StatsMonthlyStats::class,
217
-                'actions' => array(),
218
-            ),
219
-        'statistics/reservedRequests' =>
220
-            array(
221
-                'class'   => StatsReservedRequests::class,
222
-                'actions' => array(),
223
-            ),
224
-        'statistics/templateStats'    =>
225
-            array(
226
-                'class'   => StatsTemplateStats::class,
227
-                'actions' => array(),
228
-            ),
229
-        'statistics/topCreators'      =>
230
-            array(
231
-                'class'   => StatsTopCreators::class,
232
-                'actions' => array(),
233
-            ),
234
-        'statistics/users'            =>
235
-            array(
236
-                'class'   => StatsUsers::class,
237
-                'actions' => array('detail'),
238
-            ),
239
-
240
-        //////////////////////////////////////////////////////////////////////////////////////////////////
241
-        // Zoom page
242
-        'viewRequest'                 =>
243
-            array(
244
-                'class'   => PageViewRequest::class,
245
-                'actions' => array(),
246
-            ),
247
-        'viewRequest/reserve'         =>
248
-            array(
249
-                'class'   => PageReservation::class,
250
-                'actions' => array(),
251
-            ),
252
-        'viewRequest/breakReserve'    =>
253
-            array(
254
-                'class'   => PageBreakReservation::class,
255
-                'actions' => array(),
256
-            ),
257
-        'viewRequest/defer'           =>
258
-            array(
259
-                'class'   => PageDeferRequest::class,
260
-                'actions' => array(),
261
-            ),
262
-        'viewRequest/comment'         =>
263
-            array(
264
-                'class'   => PageComment::class,
265
-                'actions' => array(),
266
-            ),
267
-        'viewRequest/sendToUser'      =>
268
-            array(
269
-                'class'   => PageSendToUser::class,
270
-                'actions' => array(),
271
-            ),
272
-        'viewRequest/close'           =>
273
-            array(
274
-                'class'   => PageCloseRequest::class,
275
-                'actions' => array(),
276
-            ),
277
-        'viewRequest/drop'            =>
278
-            array(
279
-                'class'   => PageDropRequest::class,
280
-                'actions' => array(),
281
-            ),
282
-        'viewRequest/custom'          =>
283
-            array(
284
-                'class'   => PageCustomClose::class,
285
-                'actions' => array(),
286
-            ),
287
-        'editComment'                 =>
288
-            array(
289
-                'class'   => PageEditComment::class,
290
-                'actions' => array(),
291
-            ),
292
-
293
-        //////////////////////////////////////////////////////////////////////////////////////////////////
294
-        // Misc stuff
295
-        'team'                        =>
296
-            array(
297
-                'class'   => PageTeam::class,
298
-                'actions' => array(),
299
-            ),
300
-        'requestList'                 =>
301
-            array(
302
-                'class'   => PageExpandedRequestList::class,
303
-                'actions' => array(),
304
-            ),
305
-    );
306
-
307
-    /**
308
-     * @return IRoutedTask
309
-     * @throws Exception
310
-     */
311
-    final public function route()
312
-    {
313
-        $pathInfo = WebRequest::pathInfo();
314
-
315
-        list($pageClass, $action) = $this->getRouteFromPath($pathInfo);
316
-
317
-        /** @var IRoutedTask $page */
318
-        $page = new $pageClass();
319
-
320
-        // Dynamic creation, so we've got to be careful here. We can't use built-in language type protection, so
321
-        // let's use our own.
322
-        if (!($page instanceof IRoutedTask)) {
323
-            throw new Exception('Expected a page, but this is not a page.');
324
-        }
325
-
326
-        // OK, I'm happy at this point that we know we're running a page, and we know it's probably what we want if it
327
-        // inherits PageBase and has been created from the routing map.
328
-        $page->setRoute($action);
329
-
330
-        return $page;
331
-    }
332
-
333
-    /**
334
-     * @param $pathInfo
335
-     *
336
-     * @return array
337
-     */
338
-    protected function getRouteFromPath($pathInfo)
339
-    {
340
-        if (count($pathInfo) === 0) {
341
-            // No pathInfo, so no page to load. Load the main page.
342
-            return $this->getDefaultRoute();
343
-        }
344
-        elseif (count($pathInfo) === 1) {
345
-            // Exactly one path info segment, it's got to be a page.
346
-            $classSegment = $pathInfo[0];
347
-
348
-            return $this->routeSinglePathSegment($classSegment);
349
-        }
350
-
351
-        // OK, we have two or more segments now.
352
-        if (count($pathInfo) > 2) {
353
-            // Let's handle more than two, and collapse it down into two.
354
-            $requestedAction = array_pop($pathInfo);
355
-            $classSegment = implode('/', $pathInfo);
356
-        }
357
-        else {
358
-            // Two path info segments.
359
-            $classSegment = $pathInfo[0];
360
-            $requestedAction = $pathInfo[1];
361
-        }
362
-
363
-        $routeMap = $this->routePathSegments($classSegment, $requestedAction);
364
-
365
-        if ($routeMap[0] === Page404::class) {
366
-            $routeMap = $this->routeSinglePathSegment($classSegment . '/' . $requestedAction);
367
-        }
368
-
369
-        return $routeMap;
370
-    }
371
-
372
-    /**
373
-     * @param $classSegment
374
-     *
375
-     * @return array
376
-     */
377
-    final protected function routeSinglePathSegment($classSegment)
378
-    {
379
-        $routeMap = $this->getRouteMap();
380
-        if (array_key_exists($classSegment, $routeMap)) {
381
-            // Route exists, but we don't have an action in path info, so default to main.
382
-            $pageClass = $routeMap[$classSegment]['class'];
383
-            $action = 'main';
384
-
385
-            return array($pageClass, $action);
386
-        }
387
-        else {
388
-            // Doesn't exist in map. Fall back to 404
389
-            $pageClass = Page404::class;
390
-            $action = "main";
391
-
392
-            return array($pageClass, $action);
393
-        }
394
-    }
395
-
396
-    /**
397
-     * @param $classSegment
398
-     * @param $requestedAction
399
-     *
400
-     * @return array
401
-     */
402
-    final protected function routePathSegments($classSegment, $requestedAction)
403
-    {
404
-        $routeMap = $this->getRouteMap();
405
-        if (array_key_exists($classSegment, $routeMap)) {
406
-            // Route exists, but we don't have an action in path info, so default to main.
407
-
408
-            if (isset($routeMap[$classSegment]['actions'])
409
-                && array_search($requestedAction, $routeMap[$classSegment]['actions']) !== false
410
-            ) {
411
-                // Action exists in allowed action list. Allow both the page and the action
412
-                $pageClass = $routeMap[$classSegment]['class'];
413
-                $action = $requestedAction;
414
-
415
-                return array($pageClass, $action);
416
-            }
417
-            else {
418
-                // Valid page, invalid action. 404 our way out.
419
-                $pageClass = Page404::class;
420
-                $action = 'main';
421
-
422
-                return array($pageClass, $action);
423
-            }
424
-        }
425
-        else {
426
-            // Class doesn't exist in map. Fall back to 404
427
-            $pageClass = Page404::class;
428
-            $action = 'main';
429
-
430
-            return array($pageClass, $action);
431
-        }
432
-    }
433
-
434
-    /**
435
-     * @return array
436
-     */
437
-    protected function getRouteMap()
438
-    {
439
-        return $this->routeMap;
440
-    }
441
-
442
-    /**
443
-     * @return callable
444
-     */
445
-    protected function getDefaultRoute()
446
-    {
447
-        return array(PageMain::class, "main");
448
-    }
58
+	/**
59
+	 * This is the core routing table for the application. The basic idea is:
60
+	 *
61
+	 *      array(
62
+	 *          "foo" =>
63
+	 *              array(
64
+	 *                  "class"   => PageFoo::class,
65
+	 *                  "actions" => array("bar", "other")
66
+	 *              ),
67
+	 * );
68
+	 *
69
+	 * Things to note:
70
+	 *     - If no page is requested, we go to PageMain. PageMain can't have actions defined.
71
+	 *
72
+	 *     - If a page is defined and requested, but no action is requested, go to that page's main() method
73
+	 *     - If a page is defined and requested, and an action is defined and requested, go to that action's method.
74
+	 *     - If a page is defined and requested, and an action NOT defined and requested, go to Page404 and it's main()
75
+	 *       method.
76
+	 *     - If a page is NOT defined and requested, go to Page404 and it's main() method.
77
+	 *
78
+	 *     - Query parameters are ignored.
79
+	 *
80
+	 * The key point here is request routing with validation that this is allowed, before we start hitting the
81
+	 * filesystem through the AutoLoader, and opening random files. Also, so that we validate the action requested
82
+	 * before we start calling random methods through the web UI.
83
+	 *
84
+	 * Examples:
85
+	 * /internal.php                => returns instance of PageMain, routed to main()
86
+	 * /internal.php?query          => returns instance of PageMain, routed to main()
87
+	 * /internal.php/foo            => returns instance of PageFoo, routed to main()
88
+	 * /internal.php/foo?query      => returns instance of PageFoo, routed to main()
89
+	 * /internal.php/foo/bar        => returns instance of PageFoo, routed to bar()
90
+	 * /internal.php/foo/bar?query  => returns instance of PageFoo, routed to bar()
91
+	 * /internal.php/foo/baz        => returns instance of Page404, routed to main()
92
+	 * /internal.php/foo/baz?query  => returns instance of Page404, routed to main()
93
+	 * /internal.php/bar            => returns instance of Page404, routed to main()
94
+	 * /internal.php/bar?query      => returns instance of Page404, routed to main()
95
+	 * /internal.php/bar/baz        => returns instance of Page404, routed to main()
96
+	 * /internal.php/bar/baz?query  => returns instance of Page404, routed to main()
97
+	 *
98
+	 * Take care when changing this - a lot of places rely on the array key for redirects and other links. If you need
99
+	 * to change the key, then you'll likely have to update a lot of files.
100
+	 *
101
+	 * @var array
102
+	 */
103
+	private $routeMap = array(
104
+
105
+		//////////////////////////////////////////////////////////////////////////////////////////////////
106
+		// Login and registration
107
+		'logout'                      =>
108
+			array(
109
+				'class'   => PageLogout::class,
110
+				'actions' => array(),
111
+			),
112
+		'login'                       =>
113
+			array(
114
+				'class'   => PageLogin::class,
115
+				'actions' => array(),
116
+			),
117
+		'forgotPassword'              =>
118
+			array(
119
+				'class'   => PageForgotPassword::class,
120
+				'actions' => array('reset'),
121
+			),
122
+		'register'                    =>
123
+			array(
124
+				'class'   => PageRegisterOption::class,
125
+				'actions' => array(),
126
+			),
127
+		'register/standard'           =>
128
+			array(
129
+				'class'   => PageRegisterStandard::class,
130
+				'actions' => array('done'),
131
+			),
132
+
133
+		//////////////////////////////////////////////////////////////////////////////////////////////////
134
+		// Discovery
135
+		'search'                      =>
136
+			array(
137
+				'class'   => PageSearch::class,
138
+				'actions' => array(),
139
+			),
140
+		'logs'                        =>
141
+			array(
142
+				'class'   => PageLog::class,
143
+				'actions' => array(),
144
+			),
145
+
146
+		//////////////////////////////////////////////////////////////////////////////////////////////////
147
+		// Administration
148
+		'bans'                        =>
149
+			array(
150
+				'class'   => PageBan::class,
151
+				'actions' => array('set', 'remove'),
152
+			),
153
+		'userManagement'              =>
154
+			array(
155
+				'class'   => PageUserManagement::class,
156
+				'actions' => array(
157
+					'approve',
158
+					'decline',
159
+					'rename',
160
+					'editUser',
161
+					'suspend',
162
+					'editRoles',
163
+				),
164
+			),
165
+		'siteNotice'                  =>
166
+			array(
167
+				'class'   => PageSiteNotice::class,
168
+				'actions' => array(),
169
+			),
170
+		'emailManagement'             =>
171
+			array(
172
+				'class'   => PageEmailManagement::class,
173
+				'actions' => array('create', 'edit', 'view'),
174
+			),
175
+
176
+		//////////////////////////////////////////////////////////////////////////////////////////////////
177
+		// Personal preferences
178
+		'preferences'                 =>
179
+			array(
180
+				'class'   => PagePreferences::class,
181
+				'actions' => array('changePassword'),
182
+			),
183
+		'oauth'                       =>
184
+			array(
185
+				'class'   => PageOAuth::class,
186
+				'actions' => array('detach', 'attach'),
187
+			),
188
+
189
+		//////////////////////////////////////////////////////////////////////////////////////////////////
190
+		// Welcomer configuration
191
+		'welcomeTemplates'            =>
192
+			array(
193
+				'class'   => PageWelcomeTemplateManagement::class,
194
+				'actions' => array('select', 'edit', 'delete', 'add', 'view'),
195
+			),
196
+
197
+		//////////////////////////////////////////////////////////////////////////////////////////////////
198
+		// Statistics
199
+		'statistics'                  =>
200
+			array(
201
+				'class'   => StatsMain::class,
202
+				'actions' => array(),
203
+			),
204
+		'statistics/fastCloses'       =>
205
+			array(
206
+				'class'   => StatsFastCloses::class,
207
+				'actions' => array(),
208
+			),
209
+		'statistics/inactiveUsers'    =>
210
+			array(
211
+				'class'   => StatsInactiveUsers::class,
212
+				'actions' => array(),
213
+			),
214
+		'statistics/monthlyStats'     =>
215
+			array(
216
+				'class'   => StatsMonthlyStats::class,
217
+				'actions' => array(),
218
+			),
219
+		'statistics/reservedRequests' =>
220
+			array(
221
+				'class'   => StatsReservedRequests::class,
222
+				'actions' => array(),
223
+			),
224
+		'statistics/templateStats'    =>
225
+			array(
226
+				'class'   => StatsTemplateStats::class,
227
+				'actions' => array(),
228
+			),
229
+		'statistics/topCreators'      =>
230
+			array(
231
+				'class'   => StatsTopCreators::class,
232
+				'actions' => array(),
233
+			),
234
+		'statistics/users'            =>
235
+			array(
236
+				'class'   => StatsUsers::class,
237
+				'actions' => array('detail'),
238
+			),
239
+
240
+		//////////////////////////////////////////////////////////////////////////////////////////////////
241
+		// Zoom page
242
+		'viewRequest'                 =>
243
+			array(
244
+				'class'   => PageViewRequest::class,
245
+				'actions' => array(),
246
+			),
247
+		'viewRequest/reserve'         =>
248
+			array(
249
+				'class'   => PageReservation::class,
250
+				'actions' => array(),
251
+			),
252
+		'viewRequest/breakReserve'    =>
253
+			array(
254
+				'class'   => PageBreakReservation::class,
255
+				'actions' => array(),
256
+			),
257
+		'viewRequest/defer'           =>
258
+			array(
259
+				'class'   => PageDeferRequest::class,
260
+				'actions' => array(),
261
+			),
262
+		'viewRequest/comment'         =>
263
+			array(
264
+				'class'   => PageComment::class,
265
+				'actions' => array(),
266
+			),
267
+		'viewRequest/sendToUser'      =>
268
+			array(
269
+				'class'   => PageSendToUser::class,
270
+				'actions' => array(),
271
+			),
272
+		'viewRequest/close'           =>
273
+			array(
274
+				'class'   => PageCloseRequest::class,
275
+				'actions' => array(),
276
+			),
277
+		'viewRequest/drop'            =>
278
+			array(
279
+				'class'   => PageDropRequest::class,
280
+				'actions' => array(),
281
+			),
282
+		'viewRequest/custom'          =>
283
+			array(
284
+				'class'   => PageCustomClose::class,
285
+				'actions' => array(),
286
+			),
287
+		'editComment'                 =>
288
+			array(
289
+				'class'   => PageEditComment::class,
290
+				'actions' => array(),
291
+			),
292
+
293
+		//////////////////////////////////////////////////////////////////////////////////////////////////
294
+		// Misc stuff
295
+		'team'                        =>
296
+			array(
297
+				'class'   => PageTeam::class,
298
+				'actions' => array(),
299
+			),
300
+		'requestList'                 =>
301
+			array(
302
+				'class'   => PageExpandedRequestList::class,
303
+				'actions' => array(),
304
+			),
305
+	);
306
+
307
+	/**
308
+	 * @return IRoutedTask
309
+	 * @throws Exception
310
+	 */
311
+	final public function route()
312
+	{
313
+		$pathInfo = WebRequest::pathInfo();
314
+
315
+		list($pageClass, $action) = $this->getRouteFromPath($pathInfo);
316
+
317
+		/** @var IRoutedTask $page */
318
+		$page = new $pageClass();
319
+
320
+		// Dynamic creation, so we've got to be careful here. We can't use built-in language type protection, so
321
+		// let's use our own.
322
+		if (!($page instanceof IRoutedTask)) {
323
+			throw new Exception('Expected a page, but this is not a page.');
324
+		}
325
+
326
+		// OK, I'm happy at this point that we know we're running a page, and we know it's probably what we want if it
327
+		// inherits PageBase and has been created from the routing map.
328
+		$page->setRoute($action);
329
+
330
+		return $page;
331
+	}
332
+
333
+	/**
334
+	 * @param $pathInfo
335
+	 *
336
+	 * @return array
337
+	 */
338
+	protected function getRouteFromPath($pathInfo)
339
+	{
340
+		if (count($pathInfo) === 0) {
341
+			// No pathInfo, so no page to load. Load the main page.
342
+			return $this->getDefaultRoute();
343
+		}
344
+		elseif (count($pathInfo) === 1) {
345
+			// Exactly one path info segment, it's got to be a page.
346
+			$classSegment = $pathInfo[0];
347
+
348
+			return $this->routeSinglePathSegment($classSegment);
349
+		}
350
+
351
+		// OK, we have two or more segments now.
352
+		if (count($pathInfo) > 2) {
353
+			// Let's handle more than two, and collapse it down into two.
354
+			$requestedAction = array_pop($pathInfo);
355
+			$classSegment = implode('/', $pathInfo);
356
+		}
357
+		else {
358
+			// Two path info segments.
359
+			$classSegment = $pathInfo[0];
360
+			$requestedAction = $pathInfo[1];
361
+		}
362
+
363
+		$routeMap = $this->routePathSegments($classSegment, $requestedAction);
364
+
365
+		if ($routeMap[0] === Page404::class) {
366
+			$routeMap = $this->routeSinglePathSegment($classSegment . '/' . $requestedAction);
367
+		}
368
+
369
+		return $routeMap;
370
+	}
371
+
372
+	/**
373
+	 * @param $classSegment
374
+	 *
375
+	 * @return array
376
+	 */
377
+	final protected function routeSinglePathSegment($classSegment)
378
+	{
379
+		$routeMap = $this->getRouteMap();
380
+		if (array_key_exists($classSegment, $routeMap)) {
381
+			// Route exists, but we don't have an action in path info, so default to main.
382
+			$pageClass = $routeMap[$classSegment]['class'];
383
+			$action = 'main';
384
+
385
+			return array($pageClass, $action);
386
+		}
387
+		else {
388
+			// Doesn't exist in map. Fall back to 404
389
+			$pageClass = Page404::class;
390
+			$action = "main";
391
+
392
+			return array($pageClass, $action);
393
+		}
394
+	}
395
+
396
+	/**
397
+	 * @param $classSegment
398
+	 * @param $requestedAction
399
+	 *
400
+	 * @return array
401
+	 */
402
+	final protected function routePathSegments($classSegment, $requestedAction)
403
+	{
404
+		$routeMap = $this->getRouteMap();
405
+		if (array_key_exists($classSegment, $routeMap)) {
406
+			// Route exists, but we don't have an action in path info, so default to main.
407
+
408
+			if (isset($routeMap[$classSegment]['actions'])
409
+				&& array_search($requestedAction, $routeMap[$classSegment]['actions']) !== false
410
+			) {
411
+				// Action exists in allowed action list. Allow both the page and the action
412
+				$pageClass = $routeMap[$classSegment]['class'];
413
+				$action = $requestedAction;
414
+
415
+				return array($pageClass, $action);
416
+			}
417
+			else {
418
+				// Valid page, invalid action. 404 our way out.
419
+				$pageClass = Page404::class;
420
+				$action = 'main';
421
+
422
+				return array($pageClass, $action);
423
+			}
424
+		}
425
+		else {
426
+			// Class doesn't exist in map. Fall back to 404
427
+			$pageClass = Page404::class;
428
+			$action = 'main';
429
+
430
+			return array($pageClass, $action);
431
+		}
432
+	}
433
+
434
+	/**
435
+	 * @return array
436
+	 */
437
+	protected function getRouteMap()
438
+	{
439
+		return $this->routeMap;
440
+	}
441
+
442
+	/**
443
+	 * @return callable
444
+	 */
445
+	protected function getDefaultRoute()
446
+	{
447
+		return array(PageMain::class, "main");
448
+	}
449 449
 }
Please login to merge, or discard this patch.
Braces   +5 added lines, -10 removed lines patch added patch discarded remove patch
@@ -340,8 +340,7 @@  discard block
 block discarded – undo
340 340
         if (count($pathInfo) === 0) {
341 341
             // No pathInfo, so no page to load. Load the main page.
342 342
             return $this->getDefaultRoute();
343
-        }
344
-        elseif (count($pathInfo) === 1) {
343
+        } elseif (count($pathInfo) === 1) {
345 344
             // Exactly one path info segment, it's got to be a page.
346 345
             $classSegment = $pathInfo[0];
347 346
 
@@ -353,8 +352,7 @@  discard block
 block discarded – undo
353 352
             // Let's handle more than two, and collapse it down into two.
354 353
             $requestedAction = array_pop($pathInfo);
355 354
             $classSegment = implode('/', $pathInfo);
356
-        }
357
-        else {
355
+        } else {
358 356
             // Two path info segments.
359 357
             $classSegment = $pathInfo[0];
360 358
             $requestedAction = $pathInfo[1];
@@ -383,8 +381,7 @@  discard block
 block discarded – undo
383 381
             $action = 'main';
384 382
 
385 383
             return array($pageClass, $action);
386
-        }
387
-        else {
384
+        } else {
388 385
             // Doesn't exist in map. Fall back to 404
389 386
             $pageClass = Page404::class;
390 387
             $action = "main";
@@ -413,16 +410,14 @@  discard block
 block discarded – undo
413 410
                 $action = $requestedAction;
414 411
 
415 412
                 return array($pageClass, $action);
416
-            }
417
-            else {
413
+            } else {
418 414
                 // Valid page, invalid action. 404 our way out.
419 415
                 $pageClass = Page404::class;
420 416
                 $action = 'main';
421 417
 
422 418
                 return array($pageClass, $action);
423 419
             }
424
-        }
425
-        else {
420
+        } else {
426 421
             // Class doesn't exist in map. Fall back to 404
427 422
             $pageClass = Page404::class;
428 423
             $action = 'main';
Please login to merge, or discard this patch.
backup.php 1 patch
Indentation   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -7,7 +7,7 @@  discard block
 block discarded – undo
7 7
  ******************************************************************************/
8 8
 
9 9
 if (isset($_SERVER['REQUEST_METHOD'])) {
10
-    die();
10
+	die();
11 11
 } //Web clients die.
12 12
 
13 13
 // Get all the classes.
@@ -19,12 +19,12 @@  discard block
 block discarded – undo
19 19
 
20 20
 $arg = $argv['1'];
21 21
 if ($arg == "--monthly") {
22
-    echo "running monthly backups.\n";
23
-    $dateModifier = date("FY");
24
-    $cmdLine = "$BUtar $BUmonthdir/mBackup-$dateModifier.tar $BUdir/*.sql.gz; rm $BUdir/*.sql.gz";
25
-    echo "running command $cmdLine\n";
26
-    shell_exec($cmdLine);
27
-    die("done.");
22
+	echo "running monthly backups.\n";
23
+	$dateModifier = date("FY");
24
+	$cmdLine = "$BUtar $BUmonthdir/mBackup-$dateModifier.tar $BUdir/*.sql.gz; rm $BUdir/*.sql.gz";
25
+	echo "running command $cmdLine\n";
26
+	shell_exec($cmdLine);
27
+	die("done.");
28 28
 }
29 29
 
30 30
 echo "running nightly backups\n";
Please login to merge, or discard this patch.
smarty-plugins/modifier.date.php 2 patches
Indentation   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -16,16 +16,16 @@
 block discarded – undo
16 16
  */
17 17
 function smarty_modifier_date($input)
18 18
 {
19
-    if (gettype($input) === 'object'
20
-        && (get_class($input) === DateTime::class || get_class($input) === DateTimeImmutable::class)
21
-    ) {
22
-        /** @var $date DateTime|DateTimeImmutable */
23
-        $date = $input;
24
-        $dateString = $date->format('Y-m-d H:i:s');
19
+	if (gettype($input) === 'object'
20
+		&& (get_class($input) === DateTime::class || get_class($input) === DateTimeImmutable::class)
21
+	) {
22
+		/** @var $date DateTime|DateTimeImmutable */
23
+		$date = $input;
24
+		$dateString = $date->format('Y-m-d H:i:s');
25 25
 
26
-        return $dateString;
27
-    }
28
-    else {
29
-        return $input;
30
-    }
26
+		return $dateString;
27
+	}
28
+	else {
29
+		return $input;
30
+	}
31 31
 }
32 32
\ No newline at end of file
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -24,8 +24,7 @@
 block discarded – undo
24 24
         $dateString = $date->format('Y-m-d H:i:s');
25 25
 
26 26
         return $dateString;
27
-    }
28
-    else {
27
+    } else {
29 28
         return $input;
30 29
     }
31 30
 }
32 31
\ No newline at end of file
Please login to merge, or discard this patch.
smarty-plugins/modifier.relativedate.php 2 patches
Indentation   +57 added lines, -57 removed lines patch added patch discarded remove patch
@@ -16,68 +16,68 @@
 block discarded – undo
16 16
  */
17 17
 function smarty_modifier_relativedate($input)
18 18
 {
19
-    $now = new DateTime();
19
+	$now = new DateTime();
20 20
 
21
-    if (gettype($input) === 'object'
22
-        && (get_class($input) === DateTime::class || get_class($input) === DateTimeImmutable::class)
23
-    ) {
24
-        $then = $input;
25
-    }
26
-    else {
27
-        $then = new DateTime($input);
28
-    }
21
+	if (gettype($input) === 'object'
22
+		&& (get_class($input) === DateTime::class || get_class($input) === DateTimeImmutable::class)
23
+	) {
24
+		$then = $input;
25
+	}
26
+	else {
27
+		$then = new DateTime($input);
28
+	}
29 29
 
30
-    $secs = $now->getTimestamp() - $then->getTimestamp();
30
+	$secs = $now->getTimestamp() - $then->getTimestamp();
31 31
 
32
-    $second = 1;
33
-    $minute = 60 * $second;
34
-    $minuteCut = 60 * $second;
35
-    $hour = 60 * $minute;
36
-    $hourCut = 90 * $minute;
37
-    $day = 24 * $hour;
38
-    $dayCut = 48 * $hour;
39
-    $week = 7 * $day;
40
-    $weekCut = 14 * $day;
41
-    $month = 30 * $day;
42
-    $monthCut = 60 * $day;
43
-    $year = 365 * $day;
44
-    $yearCut = $year * 2;
32
+	$second = 1;
33
+	$minute = 60 * $second;
34
+	$minuteCut = 60 * $second;
35
+	$hour = 60 * $minute;
36
+	$hourCut = 90 * $minute;
37
+	$day = 24 * $hour;
38
+	$dayCut = 48 * $hour;
39
+	$week = 7 * $day;
40
+	$weekCut = 14 * $day;
41
+	$month = 30 * $day;
42
+	$monthCut = 60 * $day;
43
+	$year = 365 * $day;
44
+	$yearCut = $year * 2;
45 45
 
46
-    $pluralise = true;
46
+	$pluralise = true;
47 47
 
48
-    if ($secs <= 10) {
49
-        $output = "just now";
50
-        $pluralise = false;
51
-    }
52
-    elseif ($secs > 10 && $secs < $minuteCut) {
53
-        $output = round($secs / $second) . " second";
54
-    }
55
-    elseif ($secs >= $minuteCut && $secs < $hourCut) {
56
-        $output = round($secs / $minute) . " minute";
57
-    }
58
-    elseif ($secs >= $hourCut && $secs < $dayCut) {
59
-        $output = round($secs / $hour) . " hour";
60
-    }
61
-    elseif ($secs >= $dayCut && $secs < $weekCut) {
62
-        $output = round($secs / $day) . " day";
63
-    }
64
-    elseif ($secs >= $weekCut && $secs < $monthCut) {
65
-        $output = round($secs / $week) . " week";
66
-    }
67
-    elseif ($secs >= $monthCut && $secs < $yearCut) {
68
-        $output = round($secs / $month) . " month";
69
-    }
70
-    elseif ($secs >= $yearCut && $secs < $year * 10) {
71
-        $output = round($secs / $year) . " year";
72
-    }
73
-    else {
74
-        $output = "a long time ago";
75
-        $pluralise = false;
76
-    }
48
+	if ($secs <= 10) {
49
+		$output = "just now";
50
+		$pluralise = false;
51
+	}
52
+	elseif ($secs > 10 && $secs < $minuteCut) {
53
+		$output = round($secs / $second) . " second";
54
+	}
55
+	elseif ($secs >= $minuteCut && $secs < $hourCut) {
56
+		$output = round($secs / $minute) . " minute";
57
+	}
58
+	elseif ($secs >= $hourCut && $secs < $dayCut) {
59
+		$output = round($secs / $hour) . " hour";
60
+	}
61
+	elseif ($secs >= $dayCut && $secs < $weekCut) {
62
+		$output = round($secs / $day) . " day";
63
+	}
64
+	elseif ($secs >= $weekCut && $secs < $monthCut) {
65
+		$output = round($secs / $week) . " week";
66
+	}
67
+	elseif ($secs >= $monthCut && $secs < $yearCut) {
68
+		$output = round($secs / $month) . " month";
69
+	}
70
+	elseif ($secs >= $yearCut && $secs < $year * 10) {
71
+		$output = round($secs / $year) . " year";
72
+	}
73
+	else {
74
+		$output = "a long time ago";
75
+		$pluralise = false;
76
+	}
77 77
 
78
-    if ($pluralise) {
79
-        $output = (substr($output, 0, 2) <> "1 ") ? $output . "s ago" : $output . " ago";
80
-    }
78
+	if ($pluralise) {
79
+		$output = (substr($output, 0, 2) <> "1 ") ? $output . "s ago" : $output . " ago";
80
+	}
81 81
 
82
-    return $output;
82
+	return $output;
83 83
 }
84 84
\ No newline at end of file
Please login to merge, or discard this patch.
Braces   +9 added lines, -18 removed lines patch added patch discarded remove patch
@@ -22,8 +22,7 @@  discard block
 block discarded – undo
22 22
         && (get_class($input) === DateTime::class || get_class($input) === DateTimeImmutable::class)
23 23
     ) {
24 24
         $then = $input;
25
-    }
26
-    else {
25
+    } else {
27 26
         $then = new DateTime($input);
28 27
     }
29 28
 
@@ -48,29 +47,21 @@  discard block
 block discarded – undo
48 47
     if ($secs <= 10) {
49 48
         $output = "just now";
50 49
         $pluralise = false;
51
-    }
52
-    elseif ($secs > 10 && $secs < $minuteCut) {
50
+    } elseif ($secs > 10 && $secs < $minuteCut) {
53 51
         $output = round($secs / $second) . " second";
54
-    }
55
-    elseif ($secs >= $minuteCut && $secs < $hourCut) {
52
+    } elseif ($secs >= $minuteCut && $secs < $hourCut) {
56 53
         $output = round($secs / $minute) . " minute";
57
-    }
58
-    elseif ($secs >= $hourCut && $secs < $dayCut) {
54
+    } elseif ($secs >= $hourCut && $secs < $dayCut) {
59 55
         $output = round($secs / $hour) . " hour";
60
-    }
61
-    elseif ($secs >= $dayCut && $secs < $weekCut) {
56
+    } elseif ($secs >= $dayCut && $secs < $weekCut) {
62 57
         $output = round($secs / $day) . " day";
63
-    }
64
-    elseif ($secs >= $weekCut && $secs < $monthCut) {
58
+    } elseif ($secs >= $weekCut && $secs < $monthCut) {
65 59
         $output = round($secs / $week) . " week";
66
-    }
67
-    elseif ($secs >= $monthCut && $secs < $yearCut) {
60
+    } elseif ($secs >= $monthCut && $secs < $yearCut) {
68 61
         $output = round($secs / $month) . " month";
69
-    }
70
-    elseif ($secs >= $yearCut && $secs < $year * 10) {
62
+    } elseif ($secs >= $yearCut && $secs < $year * 10) {
71 63
         $output = round($secs / $year) . " year";
72
-    }
73
-    else {
64
+    } else {
74 65
         $output = "a long time ago";
75 66
         $pluralise = false;
76 67
     }
Please login to merge, or discard this patch.
includes/ExceptionHandler.php 2 patches
Indentation   +89 added lines, -89 removed lines patch added patch discarded remove patch
@@ -13,22 +13,22 @@  discard block
 block discarded – undo
13 13
 
14 14
 class ExceptionHandler
15 15
 {
16
-    /**
17
-     * Global exception handler
18
-     *
19
-     * Smarty would be nice to use, but it COULD BE smarty that throws the errors.
20
-     * Let's build something ourselves, and hope it works.
21
-     *
22
-     * @param $exception
23
-     *
24
-     * @category Security-Critical - has the potential to leak data when exception is thrown.
25
-     */
26
-    public static function exceptionHandler(Exception $exception)
27
-    {
28
-        /** @global $siteConfiguration SiteConfiguration */
29
-        global $siteConfiguration;
30
-
31
-        $errorDocument = <<<HTML
16
+	/**
17
+	 * Global exception handler
18
+	 *
19
+	 * Smarty would be nice to use, but it COULD BE smarty that throws the errors.
20
+	 * Let's build something ourselves, and hope it works.
21
+	 *
22
+	 * @param $exception
23
+	 *
24
+	 * @category Security-Critical - has the potential to leak data when exception is thrown.
25
+	 */
26
+	public static function exceptionHandler(Exception $exception)
27
+	{
28
+		/** @global $siteConfiguration SiteConfiguration */
29
+		global $siteConfiguration;
30
+
31
+		$errorDocument = <<<HTML
32 32
 <!DOCTYPE html>
33 33
 <html lang="en"><head>
34 34
 <meta charset="utf-8">
@@ -49,77 +49,77 @@  discard block
 block discarded – undo
49 49
 </div></body></html>
50 50
 HTML;
51 51
 
52
-        $errorData = self::getExceptionData($exception);
53
-        $errorData['server'] = $_SERVER;
54
-        $errorData['get'] = $_GET;
55
-        $errorData['post'] = $_POST;
56
-
57
-        $state = serialize($errorData);
58
-        $errorId = sha1($state);
59
-
60
-        // Save the error for later analysis
61
-        file_put_contents($siteConfiguration->getErrorLog() . '/' . $errorId . '.log', $state);
62
-
63
-        // clear and discard any content that's been saved to the output buffer
64
-        if (ob_get_level() > 0) {
65
-            ob_end_clean();
66
-        }
67
-
68
-        // push error ID into the document.
69
-        $message = str_replace('$1$', $errorId, $errorDocument);
70
-
71
-        if ($siteConfiguration->getDebuggingTraceEnabled()) {
72
-            ob_start();
73
-            var_dump($errorData);
74
-            $textErrorData = ob_get_contents();
75
-            ob_end_clean();
76
-
77
-            $message = str_replace('$2$', $textErrorData, $message);
78
-        }
79
-        else {
80
-            $message = str_replace('$2$', "", $message);
81
-        }
82
-
83
-        // While we *shouldn't* have sent headers by now due to the output buffering, PHPUnit does weird things.
84
-        // This is "only" needed for the tests, but it's a good idea to wrap this anyway.
85
-        if (!headers_sent()) {
86
-            header('HTTP/1.1 500 Internal Server Error');
87
-        }
88
-
89
-        // output the document
90
-        print $message;
91
-    }
92
-
93
-    /**
94
-     * @param int    $errorSeverity The severity level of the exception.
95
-     * @param string $errorMessage  The Exception message to throw.
96
-     * @param string $errorFile     The filename where the exception is thrown.
97
-     * @param int    $errorLine     The line number where the exception is thrown.
98
-     *
99
-     * @throws ErrorException
100
-     */
101
-    public static function errorHandler($errorSeverity, $errorMessage, $errorFile, $errorLine)
102
-    {
103
-        // call into the main exception handler above
104
-        throw new ErrorException($errorMessage, 0, $errorSeverity, $errorFile, $errorLine);
105
-    }
106
-
107
-    /**
108
-     * @param Exception $exception
109
-     *
110
-     * @return null|array
111
-     */
112
-    private static function getExceptionData($exception)
113
-    {
114
-        if ($exception == null) {
115
-            return null;
116
-        }
117
-
118
-        return array(
119
-            'exception' => get_class($exception),
120
-            'message'   => $exception->getMessage(),
121
-            'stack'     => $exception->getTraceAsString(),
122
-            'previous'  => self::getExceptionData($exception->getPrevious()),
123
-        );
124
-    }
52
+		$errorData = self::getExceptionData($exception);
53
+		$errorData['server'] = $_SERVER;
54
+		$errorData['get'] = $_GET;
55
+		$errorData['post'] = $_POST;
56
+
57
+		$state = serialize($errorData);
58
+		$errorId = sha1($state);
59
+
60
+		// Save the error for later analysis
61
+		file_put_contents($siteConfiguration->getErrorLog() . '/' . $errorId . '.log', $state);
62
+
63
+		// clear and discard any content that's been saved to the output buffer
64
+		if (ob_get_level() > 0) {
65
+			ob_end_clean();
66
+		}
67
+
68
+		// push error ID into the document.
69
+		$message = str_replace('$1$', $errorId, $errorDocument);
70
+
71
+		if ($siteConfiguration->getDebuggingTraceEnabled()) {
72
+			ob_start();
73
+			var_dump($errorData);
74
+			$textErrorData = ob_get_contents();
75
+			ob_end_clean();
76
+
77
+			$message = str_replace('$2$', $textErrorData, $message);
78
+		}
79
+		else {
80
+			$message = str_replace('$2$', "", $message);
81
+		}
82
+
83
+		// While we *shouldn't* have sent headers by now due to the output buffering, PHPUnit does weird things.
84
+		// This is "only" needed for the tests, but it's a good idea to wrap this anyway.
85
+		if (!headers_sent()) {
86
+			header('HTTP/1.1 500 Internal Server Error');
87
+		}
88
+
89
+		// output the document
90
+		print $message;
91
+	}
92
+
93
+	/**
94
+	 * @param int    $errorSeverity The severity level of the exception.
95
+	 * @param string $errorMessage  The Exception message to throw.
96
+	 * @param string $errorFile     The filename where the exception is thrown.
97
+	 * @param int    $errorLine     The line number where the exception is thrown.
98
+	 *
99
+	 * @throws ErrorException
100
+	 */
101
+	public static function errorHandler($errorSeverity, $errorMessage, $errorFile, $errorLine)
102
+	{
103
+		// call into the main exception handler above
104
+		throw new ErrorException($errorMessage, 0, $errorSeverity, $errorFile, $errorLine);
105
+	}
106
+
107
+	/**
108
+	 * @param Exception $exception
109
+	 *
110
+	 * @return null|array
111
+	 */
112
+	private static function getExceptionData($exception)
113
+	{
114
+		if ($exception == null) {
115
+			return null;
116
+		}
117
+
118
+		return array(
119
+			'exception' => get_class($exception),
120
+			'message'   => $exception->getMessage(),
121
+			'stack'     => $exception->getTraceAsString(),
122
+			'previous'  => self::getExceptionData($exception->getPrevious()),
123
+		);
124
+	}
125 125
 }
126 126
\ No newline at end of file
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -75,8 +75,7 @@
 block discarded – undo
75 75
             ob_end_clean();
76 76
 
77 77
             $message = str_replace('$2$', $textErrorData, $message);
78
-        }
79
-        else {
78
+        } else {
80 79
             $message = str_replace('$2$', "", $message);
81 80
         }
82 81
 
Please login to merge, or discard this patch.