api_documentation_explorer()   F
last analyzed

Complexity

Conditions 12
Paths 384

Size

Total Lines 52
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 38
nc 384
nop 2
dl 0
loc 52
rs 3.8333
c 1
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
include_once '../../includes/easyparliament/init.php';
4
include_once './api_functions.php';
5
6
# XXX: Need to override error handling! XXX
7
8
if ($q_method = get_http_var('method')) {
9
    if (get_http_var('docs')) {
10
        $key = 'DOCS';
11
    } else {
12
        $key = get_http_var('key');
13
        if (!$key) {
14
            api_error('No API key provided. Please see https://www.theyworkforyou.com/api/key for more information.');
15
            exit;
16
        }
17
        $check = api_check_key($key);
18
        if (!$check) {
19
            api_error('Invalid API key.');
20
            exit;
21
        } elseif ($check === 'disabled') {
22
            api_error('Your API key has been disabled.');
23
            exit;
24
        }
25
    }
26
    $match = 0;
27
    foreach ($methods as $method => $data) {
28
        if (strtolower($q_method) == strtolower($method)) {
29
            if (isset($data['superuser']) && $data['superuser']) {
30
                $super_check = api_is_superuser_key($key);
31
                if (!$super_check) {
32
                    if (get_http_var('docs')) {
33
                        api_front_page();
34
                    } else {
35
                        api_error('Invalid API key.');
36
                        exit;
37
                    }
38
                }
39
            }
40
41
            api_log_call($key);
42
            $match++;
43
            if (get_http_var('docs')) {
44
                $_GET['verbose'] = 1;
45
                ob_start();
46
            }
47
            foreach ($data['parameters'] as $parameter) {
48
                if ($q_param = trim(get_http_var($parameter))) {
49
                    $match++;
50
                    include_once 'api_' . $method . '.php';
51
                    api_call_user_func_or_error('api_' . $method . '_' . $parameter, [$q_param], 'API call not yet functional', 'api');
52
                    break;
53
                }
54
            }
55
            if ($match == 1 && (get_http_var('output') || !get_http_var('docs'))) {
56
                if ($data['required']) {
57
                    api_error('No parameter provided to function "' .
58
                    _htmlspecialchars($q_method) .
59
                        '". Possible choices are: ' .
60
                        join(', ', $data['parameters']));
61
                } else {
62
                    include_once 'api_' . $method . '.php';
63
                    api_call_user_func_or_error('api_' . $method, [], 'API call not yet functional', 'api');
64
                    break;
65
                }
66
            }
67
            break;
68
        }
69
    }
70
    if (!$match) {
71
        api_log_call($key);
72
        $msg = 'Unknown function "' . _htmlspecialchars($q_method) .
73
            '". Possible functions are: ' .
74
            join(', ', array_keys($methods));
75
        if (get_http_var('output')) {
76
            api_error($msg);
77
        } else {
78
            api_front_page($msg);
79
        }
80
    } else {
81
        if (get_http_var('docs')) {
82
            $explorer = ob_get_clean();
83
            api_documentation_front($method, $explorer);
84
        }
85
    }
86
} elseif (get_http_var('docs')) {
87
    api_front_page();
88
} else {
89
    $subscription = new MySociety\TheyWorkForYou\Subscription($THEUSER);
90
    MySociety\TheyWorkForYou\Renderer::output('static/api-index', [
91
        'subscription' => $subscription->stripe,
92
    ]);
93
}
94
95
function api_documentation_front($method, $explorer) {
96
    global $PAGE, $this_page, $DATA, $THEUSER;
97
    $this_page = 'api_doc_front';
98
    $DATA->set_page_metadata($this_page, 'title', "$method function");
99
    $PAGE->page_start();
100
    $PAGE->stripe_start();
101
    include_once 'api_' . $method . '.php';
102
    print '<p align="center"><strong>https://www.theyworkforyou.com/api/' . $method . '</strong></p>';
103
    api_call_user_func_or_error('api_' . $method . '_front', [], 'No documentation yet', 'html');
104
    if ($method != 'getQuota') {
105
        api_documentation_explorer($method, $explorer);
106
    }
107
108
    $subscription = new MySociety\TheyWorkForYou\Subscription($THEUSER);
109
    $sidebar = api_sidebar($subscription);
110
    $PAGE->stripe_end([$sidebar]);
111
    $PAGE->page_end();
112
}
113
114
function api_documentation_explorer($method, $explorer) {
115
    global $methods;
116
    ?>
117
<h4>Explorer</h4>
118
<p>Try out this function without writing any code!</p>
119
<form method="get" action="?#output">
120
<p>
121
<?php foreach ($methods[$method]['parameters'] as $parameter) {
122
    print $parameter . ': <input type="text" name="' . $parameter . '" value="';
123
    if ($val = get_http_var($parameter)) {
124
        print _htmlspecialchars($val);
125
    }
126
    print '" size="30"><br>';
127
}
128
    ?>
129
Output:
130
<input id="output_json" type="radio" name="output" value="json"<?php if (get_http_var('output') == 'json' || !get_http_var('output')) {
131
    print ' checked';
132
}?>>
133
<label for="output_json" class="inline">JSON</label>
134
<input id="output_js" type="radio" name="output" value="js"<?php if (get_http_var('output') == 'js') {
135
    print ' checked';
136
}?>>
137
<label for="output_js" class="inline">JS</label>
138
<input id="output_xml" type="radio" name="output" value="xml"<?php if (get_http_var('output') == 'xml') {
139
    print ' checked';
140
}?>>
141
<label for="output_xml" class="inline">XML</label>
142
<input id="output_php" type="radio" name="output" value="php"<?php if (get_http_var('output') == 'php') {
143
    print ' checked';
144
}?>>
145
<label for="output_php" class="inline">Serialised PHP</label>
146
<input id="output_rabx" type="radio" name="output" value="rabx"<?php if (get_http_var('output') == 'rabx') {
147
    print ' checked';
148
}?>>
149
<label for="output_rabx" class="inline">RABX</label>
150
151
<input type="submit" value="Go">
152
</p>
153
</form>
154
<?php
155
    if ($explorer) {
156
        $qs = [];
157
        foreach ($methods[$method]['parameters'] as $parameter) {
158
            if (get_http_var($parameter)) {
159
                $qs[] = _htmlspecialchars(rawurlencode($parameter) . '=' . urlencode(get_http_var($parameter)));
160
            }
161
        }
162
        print '<h4><a name="output"></a>Output</h4>';
163
        print '<p>URL for this: <strong>https://www.theyworkforyou.com/api/';
164
        print $method . '?' . join('&amp;', $qs) . '&amp;output=' . _htmlspecialchars(get_http_var('output')) . '</strong></p>';
165
        print '<pre>' . _htmlspecialchars($explorer) . '</pre>';
166
    }
167
}
168
169
function api_front_page($error = '') {
170
    global $PAGE, $methods, $this_page, $THEUSER;
171
    $this_page = 'api_front';
172
    $PAGE->page_start();
173
    $PAGE->stripe_start();
174
    if ($error) {
175
        print "<p style='color: #cc0000'>$error</p>";
176
    }
177
178
    $subscription = new MySociety\TheyWorkForYou\Subscription($THEUSER);
179
180
    ?>
181
182
<p>
183
    Welcome to TheyWorkForYou’s API section. The API (Application Programming
184
    Interface) is a way of querying our database for information.
185
</p>
186
187
<?php if ($subscription->stripe) { ?>
188
<p align="center"><big>
189
    <a href="/api/key">Manage your keys and payments</a>
190
</big></p>
191
<?php } else { ?>
192
<p align="center"><big>
193
    To use the API you need to <a href="/api/key">get an API key</a>.
194
</big></p>
195
<?php } ?>
196
197
<p>
198
    The documentation for each individual API function is linked from this
199
    page: you can read what each function does, and test it out, without
200
    needing an API key or to write any code.
201
</p>
202
203
<p>
204
    <strong>Important note:</strong> Politicians’ contact details can’t be
205
    obtained via this API. If that’s what you’re looking for, see
206
    <a href="https://everypolitician.org/">EveryPolitician</a> instead.
207
    APIs and datasets for other mySociety services can be found on our
208
    data portal, <a href="https://data.mysociety.org">data.mysociety.org</a>.
209
</p>
210
211
<h3 id="plans">Pricing</h3>
212
213
<ul>
214
    <li>&pound;20 per month for 1,000 calls per month (free for charitable usage)<br/>
215
    <li>&pound;50 per month for 5,000 calls<br/>
216
    <li>&pound;100 per month for 10,000 calls<br/>
217
    <li>&pound;300 per month for unlimited calls
218
</ul>
219
220
<p>In addition, we offer a 50% discount on the above rates for charitable usage.
221
This means direct use by registered charities, or individuals pursuing a
222
non-profit project on an unpaid basis.</p>
223
224
<p>Please read our full <a href="/api/terms">terms of usage</a>, including
225
licence and attribution requirements.</p>
226
227
<?php if ($subscription->stripe) { ?>
228
<p align="center"><big>
229
    <a href="/api/key">Manage your keys and payments</a>
230
</big></p>
231
<?php } else { ?>
232
<p align="center"><big>
233
    To use the API you need to <a href="/api/key">get an API key</a>.
234
</big></p>
235
<?php } ?>
236
237
238
<hr>
239
240
<h2>Technical documentation</h2>
241
<p>
242
    All requests are made by GETting a particular URL with a number of
243
    parameters. <em>key</em> is required; <em>output</em> is optional, and
244
    defaults to <kbd>js</kbd>.
245
</p>
246
<p align="center">
247
    <strong>https://www.theyworkforyou.com/api/<em>function</em>?key=<em>key</em>&amp;output=<em>output</em>&amp;<em>other_variables</em></strong>
248
</p>
249
<p>
250
    The current version of the API is <em>1.0.0</em>. If we make changes to
251
    the API functions, we’ll increase the version number and make it an
252
    argument so you can still use the old version.
253
</p>
254
255
<table>
256
<tr valign="top">
257
<td width="60%">
258
259
<h3>Outputs</h3>
260
<p>The <em>output</em> argument can take any of the following values:
261
<ul>
262
<li><strong>xml</strong>. XML. The root element is twfy.</li>
263
<li><strong>php</strong>. Serialized PHP, that can be turned back into useful information with the unserialize() command. Quite useful in Python as well, using e.g. <a href="https://pypi.org/project/phpserialize/">phpserialize</a>.</li>
264
<li><strong>json</strong>. JSON data.</li>
265
<li><strong>js</strong>. A JavaScript object, with data in ISO-8859-1. You can
266
provide a callback function with the <em>callback</em> variable, and then that
267
function will be called with the data as its argument.</li>
268
<li><strong>rabx</strong>. “RPC over Anything But XML”.</li>
269
</ul>
270
271
</td><td>
272
273
<h3>Errors</h3>
274
275
<p>If there’s an error, either in the arguments provided or in trying to perform the request,
276
this is returned as a top-level error string, ie. in XML it returns
277
<code>&lt;twfy&gt;&lt;error&gt;ERROR&lt;/error&gt;&lt;/twfy&gt;</code>;
278
in JS <code>{"error":"ERROR"}</code>;
279
and in PHP and RABX a serialised array containing one entry with key <code>error</code>.
280
281
</td></tr></table>
282
283
<h3>Bindings</h3>
284
285
<p>These help you interface with the API more easily in a particular language:</p>
286
<ul>
287
<li><a href="https://github.com/rubenarakelyan/twfyapi-aspnet/">ASP.net</a> (thanks to Ruben Arakelyan)</li>
288
<li><a href="https://github.com/rhinocratic/twfy">Clojure</a> (thanks to Andrew Baxter)</li>
289
<li><a href="https://github.com/jamtho/twfy">Common Lisp</a> (thanks to James Thompson)</li>
290
<li><a href="https://github.com/rubenarakelyan/twfyapi-js">JavaScript</a> (thanks to Ruben Arakelyan)</li>
291
<li><a href="https://sourceforge.net/projects/twfyjavaapi">Java</a> (thanks to Mitch Kent)</li>
292
<li><a href="https://github.com/ifraixedes/node-theyworkforyou-api">Node</a> (thanks to Ivan Fraixedes)</li>
293
<li><a href="https://metacpan.org/pod/WebService::TWFY::API">Perl</a> (thanks to Spiros Denaxas)</li>
294
<li><a href="https://github.com/rubenarakelyan/twfyapi/">PHP</a> (thanks to Ruben Arakelyan)</li>
295
<li><a href="https://code.google.com/archive/p/twfython/">Python</a> (thanks to Paul Doran)</li>
296
<li><a href="https://github.com/conjugateprior/twfy">R</a> (thanks to Will Lowe)</li>
297
<li><a href="https://github.com/bruce/twfy">Ruby</a> (thanks to Bruce Williams and Martin Owen)</li>
298
</ul>
299
300
<p>If anyone wishes to write bindings for the API in any language, please
301
do so, let us know and we’ll link to it here. You might want to
302
<a href="https://groups.google.com/a/mysociety.org/forum/#!forum/theyworkforyou">join our mailing list</a>
303
to discuss things.</p>
304
305
<h3>Example</h3>
306
307
<ul>
308
<li><a href="javascript:function foo(r) {if (r.twfy.url)window.location=r.twfy.url;};(function () {var s=document.createElement('script');s.setAttribute('src','https://www.theyworkforyou.com/api/convertURL?key=Gbr9QgCDzHExFzRwPWGAiUJ5&callback=foo&url='+encodeURIComponent(window.location));s.setAttribute('type','text/javascript');document.getElementsByTagName('head')[0].appendChild(s);})()">Hansard prettifier</a> - drag this bookmarklet to your bookmarks bar, or bookmark it. Then if you ever find yourself on the official site, clicking this will try and take you to the equivalent page on TheyWorkForYou. (Tested in IE, Firefox, Opera.)</li>
309
</ul>
310
311
<h3>Bulk Analysis</h3>
312
313
<p>
314
If you are doing analysis over long periods of time, or generating statistical data then you might find our <a href="https://parser.theyworkforyou.com/">raw data</a>
315
more suitable that using the API.
316
</p>
317
318
<?php
319
        $sidebar = api_sidebar($subscription);
320
    $PAGE->stripe_end([$sidebar]);
321
    $PAGE->page_end();
322
}
323