AjaxDispatcher::performAction()   C
last analyzed

Complexity

Conditions 10
Paths 32

Size

Total Lines 56
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 40
nc 32
nop 1
dl 0
loc 56
rs 6.7741
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Handle ajax requests and send them to the proper handler.
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License along
16
 * with this program; if not, write to the Free Software Foundation, Inc.,
17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
 * http://www.gnu.org/copyleft/gpl.html
19
 *
20
 * @file
21
 * @ingroup Ajax
22
 */
23
24
/**
25
 * @defgroup Ajax Ajax
26
 */
27
28
/**
29
 * Object-Oriented Ajax functions.
30
 * @ingroup Ajax
31
 */
32
class AjaxDispatcher {
33
	/**
34
	 * The way the request was made, either a 'get' or a 'post'
35
	 * @var string $mode
36
	 */
37
	private $mode;
38
39
	/**
40
	 * Name of the requested handler
41
	 * @var string $func_name
42
	 */
43
	private $func_name;
44
45
	/** Arguments passed
46
	 * @var array $args
47
	 */
48
	private $args;
49
50
	/**
51
	 * @var Config
52
	 */
53
	private $config;
54
55
	/**
56
	 * Load up our object with user supplied data
57
	 */
58
	function __construct( Config $config ) {
0 ignored issues
show
Coding Style introduced by
__construct uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
__construct uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
59
		$this->config = $config;
60
61
		$this->mode = "";
62
63
		if ( !empty( $_GET["rs"] ) ) {
64
			$this->mode = "get";
65
		}
66
67
		if ( !empty( $_POST["rs"] ) ) {
68
			$this->mode = "post";
69
		}
70
71
		switch ( $this->mode ) {
72 View Code Duplication
			case 'get':
73
				$this->func_name = isset( $_GET["rs"] ) ? $_GET["rs"] : '';
74
				if ( !empty( $_GET["rsargs"] ) ) {
75
					$this->args = $_GET["rsargs"];
76
				} else {
77
					$this->args = [];
78
				}
79
				break;
80 View Code Duplication
			case 'post':
81
				$this->func_name = isset( $_POST["rs"] ) ? $_POST["rs"] : '';
82
				if ( !empty( $_POST["rsargs"] ) ) {
83
					$this->args = $_POST["rsargs"];
84
				} else {
85
					$this->args = [];
86
				}
87
				break;
88
			default:
89
				return;
90
				# Or we could throw an exception:
91
				# throw new MWException( __METHOD__ . ' called without any data (mode empty).' );
92
		}
93
	}
94
95
	/**
96
	 * Pass the request to our internal function.
97
	 * BEWARE! Data are passed as they have been supplied by the user,
98
	 * they should be carefully handled in the function processing the
99
	 * request.
100
	 *
101
	 * @param User $user
102
	 */
103
	function performAction( User $user ) {
104
		if ( empty( $this->mode ) ) {
105
			return;
106
		}
107
108
		if ( !in_array( $this->func_name, $this->config->get( 'AjaxExportList' ) ) ) {
109
			wfDebug( __METHOD__ . ' Bad Request for unknown function ' . $this->func_name . "\n" );
110
			wfHttpError(
111
				400,
112
				'Bad Request',
113
				"unknown function " . $this->func_name
114
			);
115
		} elseif ( !User::isEveryoneAllowed( 'read' ) && !$user->isAllowed( 'read' ) ) {
116
			wfHttpError(
117
				403,
118
				'Forbidden',
119
				'You are not allowed to view pages.' );
120
		} else {
121
			wfDebug( __METHOD__ . ' dispatching ' . $this->func_name . "\n" );
122
			try {
123
				$result = call_user_func_array( $this->func_name, $this->args );
124
125
				if ( $result === false || $result === null ) {
126
					wfDebug( __METHOD__ . ' ERROR while dispatching ' .
127
						$this->func_name . "(" . var_export( $this->args, true ) . "): " .
128
						"no data returned\n" );
129
130
					wfHttpError( 500, 'Internal Error',
131
						"{$this->func_name} returned no data" );
132
				} else {
133
					if ( is_string( $result ) ) {
134
						$result = new AjaxResponse( $result );
135
					}
136
137
					// Make sure DB commit succeeds before sending a response
138
					wfGetLBFactory()->commitMasterChanges( __METHOD__ );
0 ignored issues
show
Deprecated Code introduced by
The function wfGetLBFactory() has been deprecated with message: since 1.27, use MediaWikiServices::getDBLoadBalancerFactory() instead.

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
139
140
					$result->sendHeaders();
141
					$result->printText();
142
143
					wfDebug( __METHOD__ . ' dispatch complete for ' . $this->func_name . "\n" );
144
				}
145
			} catch ( Exception $e ) {
146
				wfDebug( __METHOD__ . ' ERROR while dispatching ' .
147
					$this->func_name . "(" . var_export( $this->args, true ) . "): " .
148
					get_class( $e ) . ": " . $e->getMessage() . "\n" );
149
150
				if ( !headers_sent() ) {
151
					wfHttpError( 500, 'Internal Error',
152
						$e->getMessage() );
153
				} else {
154
					print $e->getMessage();
155
				}
156
			}
157
		}
158
	}
159
}
160