JSON API - Version 1.0.4

Version Description

Minor bugfix/refactor release

Download this release

Release Info

Developer dphiffer
Plugin Icon wp plugin JSON API
Version 1.0.4
Comparing to
See all releases

Code changes from version 1.0.3 to 1.0.4

controllers/core.php CHANGED
@@ -11,7 +11,7 @@ class JSON_API_Core_Controller {
11
  if (!empty($json_api->query->controller)) {
12
  return $json_api->controller_info($json_api->query->controller);
13
  } else {
14
- $dir = dirname(dirname(__FILE__));
15
  $php = file_get_contents("$dir/json-api.php");
16
  if (preg_match('/^\s*Version:\s*(.+)$/m', $php, $matches)) {
17
  $version = $matches[1];
11
  if (!empty($json_api->query->controller)) {
12
  return $json_api->controller_info($json_api->query->controller);
13
  } else {
14
+ $dir = json_api_dir();
15
  $php = file_get_contents("$dir/json-api.php");
16
  if (preg_match('/^\s*Version:\s*(.+)$/m', $php, $matches)) {
17
  $version = $matches[1];
json-api.php CHANGED
@@ -3,21 +3,22 @@
3
  Plugin Name: JSON API
4
  Plugin URI: http://wordpress.org/extend/plugins/json-api/
5
  Description: A RESTful API for WordPress
6
- Version: 1.0.3
7
  Author: Dan Phiffer
8
  Author URI: http://phiffer.org/
9
  */
10
 
11
- $dir = dirname(__FILE__);
12
- require_once "$dir/singletons/query.php";
13
- require_once "$dir/singletons/introspector.php";
14
- require_once "$dir/singletons/response.php";
15
- require_once "$dir/models/post.php";
16
- require_once "$dir/models/comment.php";
17
- require_once "$dir/models/category.php";
18
- require_once "$dir/models/tag.php";
19
- require_once "$dir/models/author.php";
20
- require_once "$dir/models/attachment.php";
 
21
 
22
  function json_api_init() {
23
  global $json_api;
@@ -25,6 +26,10 @@ function json_api_init() {
25
  add_action('admin_notices', 'json_api_php_version_warning');
26
  return;
27
  }
 
 
 
 
28
  add_filter('rewrite_rules_array', 'json_api_rewrites');
29
  $json_api = new JSON_API();
30
  }
@@ -33,6 +38,10 @@ function json_api_php_version_warning() {
33
  echo "<div id=\"json-api-warning\" class=\"updated fade\"><p>Sorry, JSON API requires PHP version 5.0 or greater.</p></div>";
34
  }
35
 
 
 
 
 
36
  function json_api_activation() {
37
  // Add the rewrite rule on activation
38
  global $wp_rewrite;
@@ -58,372 +67,17 @@ function json_api_rewrites($wp_rules) {
58
  return array_merge($json_api_rules, $wp_rules);
59
  }
60
 
 
 
 
 
 
 
 
 
61
  // Add initialization and activation hooks
62
  add_action('init', 'json_api_init');
63
  register_activation_hook("$dir/json-api.php", 'json_api_activation');
64
  register_deactivation_hook("$dir/json-api.php", 'json_api_deactivation');
65
 
66
-
67
- class JSON_API {
68
-
69
- function __construct() {
70
- $this->query = new JSON_API_Query();
71
- $this->introspector = new JSON_API_Introspector();
72
- $this->response = new JSON_API_Response();
73
- add_action('template_redirect', array(&$this, 'template_redirect'));
74
- add_action('admin_menu', array(&$this, 'admin_menu'));
75
- add_action('update_option_json_api_base', array(&$this, 'flush_rewrite_rules'));
76
- add_action('pre_update_option_json_api_controllers', array(&$this, 'update_controllers'));
77
- }
78
-
79
- function template_redirect() {
80
- // Check to see if there's an appropriate API controller + method
81
- $controller = strtolower($this->query->get_controller());
82
- $available_controllers = $this->get_controllers();
83
- $enabled_controllers = explode(',', get_option('json_api_controllers', 'core'));
84
- $active_controllers = array_intersect($available_controllers, $enabled_controllers);
85
-
86
- if ($controller) {
87
-
88
- if (!in_array($controller, $active_controllers)) {
89
- $this->error("Unknown controller '$controller'.");
90
- }
91
-
92
- $controller_path = $this->controller_path($controller);
93
- if (file_exists($controller_path)) {
94
- require_once $controller_path;
95
- }
96
- $controller_class = $this->controller_class($controller);
97
-
98
- if (!class_exists($controller_class)) {
99
- $this->error("Unknown controller '$controller_class'.");
100
- }
101
-
102
- $this->controller = new $controller_class();
103
- $method = $this->query->get_method($controller);
104
-
105
- if ($method) {
106
-
107
- $this->response->setup();
108
-
109
- // Run action hooks for method
110
- do_action("json_api-{$controller}-$method");
111
-
112
- // Error out if nothing is found
113
- if ($method == '404') {
114
- $this->error('Not found');
115
- }
116
-
117
- // Run the method
118
- $result = $this->controller->$method();
119
-
120
- // Handle the result
121
- $this->response->respond($result);
122
-
123
- // Done!
124
- exit;
125
- }
126
- }
127
- }
128
-
129
- function admin_menu() {
130
- add_options_page('JSON API Settings', 'JSON API', 'manage_options', 'json-api', array(&$this, 'admin_options'));
131
- }
132
-
133
- function admin_options() {
134
- if (!current_user_can('manage_options')) {
135
- wp_die( __('You do not have sufficient permissions to access this page.') );
136
- }
137
-
138
- $available_controllers = $this->get_controllers();
139
- $active_controllers = explode(',', get_option('json_api_controllers', 'core'));
140
-
141
- if (count($active_controllers) == 1 && empty($active_controllers[0])) {
142
- $active_controllers = array();
143
- }
144
-
145
- if (!empty($_REQUEST['_wpnonce']) && wp_verify_nonce($_REQUEST['_wpnonce'], "update-options")) {
146
- if ((!empty($_REQUEST['action']) || !empty($_REQUEST['action2'])) &&
147
- (!empty($_REQUEST['controller']) || !empty($_REQUEST['controllers']))) {
148
- if (!empty($_REQUEST['action'])) {
149
- $action = $_REQUEST['action'];
150
- } else {
151
- $action = $_REQUEST['action2'];
152
- }
153
-
154
- if (!empty($_REQUEST['controllers'])) {
155
- $controllers = $_REQUEST['controllers'];
156
- } else {
157
- $controllers = array($_REQUEST['controller']);
158
- }
159
-
160
- foreach ($controllers as $controller) {
161
- if (in_array($controller, $available_controllers)) {
162
- if ($action == 'activate' && !in_array($controller, $active_controllers)) {
163
- $active_controllers[] = $controller;
164
- } else if ($action == 'deactivate') {
165
- $index = array_search($controller, $active_controllers);
166
- if ($index !== false) {
167
- unset($active_controllers[$index]);
168
- }
169
- }
170
- }
171
- }
172
- $this->save_option('json_api_controllers', implode(',', $active_controllers));
173
- }
174
- if (isset($_REQUEST['json_api_base'])) {
175
- $this->save_option('json_api_base', $_REQUEST['json_api_base']);
176
- }
177
- }
178
-
179
- ?>
180
- <div class="wrap">
181
- <div id="icon-options-general" class="icon32"><br /></div>
182
- <h2>JSON API Settings</h2>
183
- <form action="options-general.php?page=json-api" method="post">
184
- <?php wp_nonce_field('update-options'); ?>
185
- <h3>Controllers</h3>
186
- <?php $this->print_controller_actions(); ?>
187
- <table id="all-plugins-table" class="widefat">
188
- <thead>
189
- <tr>
190
- <th class="manage-column check-column" scope="col"><input type="checkbox" /></th>
191
- <th class="manage-column" scope="col">Controller</th>
192
- <th class="manage-column" scope="col">Description</th>
193
- </tr>
194
- </thead>
195
- <tfoot>
196
- <tr>
197
- <th class="manage-column check-column" scope="col"><input type="checkbox" /></th>
198
- <th class="manage-column" scope="col">Controller</th>
199
- <th class="manage-column" scope="col">Description</th>
200
- </tr>
201
- </tfoot>
202
- <tbody class="plugins">
203
- <?php
204
-
205
- foreach ($available_controllers as $controller) {
206
-
207
- $error = false;
208
- $active = in_array($controller, $active_controllers);
209
- $info = $this->controller_info($controller);
210
-
211
- if (is_string($info)) {
212
- $active = false;
213
- $error = true;
214
- $info = array(
215
- 'name' => $controller,
216
- 'description' => "<p><strong>Error</strong>: $info</p>",
217
- 'methods' => array(),
218
- 'url' => null
219
- );
220
- }
221
-
222
- ?>
223
- <tr class="<?php echo ($active ? 'active' : 'inactive'); ?>">
224
- <th class="check-column" scope="row">
225
- <input type="checkbox" name="controllers[]" value="<?php echo $controller; ?>" />
226
- </th>
227
- <td class="plugin-title">
228
- <strong><?php echo $info['name']; ?></strong>
229
- <div class="row-actions-visible">
230
- <?php
231
-
232
- if ($active) {
233
- echo '<a href="' . wp_nonce_url('options-general.php?page=json-api&amp;action=deactivate&amp;controller=' . $controller, 'update-options') . '" title="' . __('Deactivate this controller') . '" class="edit">' . __('Deactivate') . '</a>';
234
- } else if (!$error) {
235
- echo '<a href="' . wp_nonce_url('options-general.php?page=json-api&amp;action=activate&amp;controller=' . $controller, 'update-options') . '" title="' . __('Activate this controller') . '" class="edit">' . __('Activate') . '</a>';
236
- }
237
-
238
- if ($info['url']) {
239
- echo ' | ';
240
- echo '<a href="' . $info['url'] . '" target="_blank">Docs</a></div>';
241
- }
242
-
243
- ?>
244
- </td>
245
- <td class="desc">
246
- <p><?php echo $info['description']; ?></p>
247
- <p>
248
- <?php
249
-
250
- foreach($info['methods'] as $method) {
251
- $url = $this->get_method_url($controller, $method, array('dev' => 1));
252
- if ($active) {
253
- echo "<code><a href=\"$url\">$method</a></code> ";
254
- } else {
255
- echo "<code>$method</code> ";
256
- }
257
- }
258
-
259
- ?>
260
- </p>
261
- </td>
262
- </tr>
263
- <?php } ?>
264
- </tbody>
265
- </table>
266
- <?php $this->print_controller_actions('action2'); ?>
267
- <h3>Address</h3>
268
- <p>Specify a base URL for JSON API. For example, using <code>api</code> as your API base URL would enable the following <code><?php bloginfo('url'); ?>/api/get_recent_posts/</code>. If you assign a blank value the API will only be available by setting a <code>json</code> query variable.</p>
269
- <table class="form-table">
270
- <tr valign="top">
271
- <th scope="row">API base</th>
272
- <td><code><?php bloginfo('url'); ?>/</code><input type="text" name="json_api_base" value="<?php echo get_option('json_api_base', 'api'); ?>" size="15" /></td>
273
- </tr>
274
- </table>
275
- <?php if (!get_option('permalink_structure', '')) { ?>
276
- <br />
277
- <p><strong>Note:</strong> User-friendly permalinks are not currently enabled. <a target="_blank" class="button" href="options-permalink.php">Change Permalinks</a>
278
- <?php } ?>
279
- <p class="submit">
280
- <input type="submit" class="button-primary" value="<?php _e('Save Changes') ?>" />
281
- </p>
282
- </form>
283
- </div>
284
- <?php
285
- }
286
-
287
- function print_controller_actions($name = 'action') {
288
- ?>
289
- <div class="tablenav">
290
- <div class="alignleft actions">
291
- <select name="<?php echo $name; ?>">
292
- <option selected="selected" value="-1">Bulk Actions</option>
293
- <option value="activate">Activate</option>
294
- <option value="deactivate">Deactivate</option>
295
- </select>
296
- <input type="submit" class="button-secondary action" id="doaction" name="doaction" value="Apply">
297
- </div>
298
- <div class="clear"></div>
299
- </div>
300
- <div class="clear"></div>
301
- <?php
302
- }
303
-
304
- function get_method_url($controller, $method, $options = '') {
305
- $url = get_bloginfo('url');
306
- $base = get_option('json_api_base', 'api');
307
- $permalink_structure = get_option('permalink_structure', '');
308
- if (!empty($options) && is_array($options)) {
309
- $args = array();
310
- foreach ($options as $key => $value) {
311
- $args[] = urlencode($key) . '=' . urlencode($value);
312
- }
313
- $args = implode('&', $args);
314
- } else {
315
- $args = $options;
316
- }
317
- if ($controller != 'core') {
318
- $method = "$controller/$method";
319
- }
320
- if (!empty($base) && !empty($permalink_structure)) {
321
- if (!empty($args)) {
322
- $args = "?$args";
323
- }
324
- return "$url/$base/$method/$args";
325
- } else {
326
- return "$url?json=$method&$args";
327
- }
328
- }
329
-
330
- function save_option($id, $value) {
331
- $option_exists = (get_option($id, null) !== null);
332
- if ($option_exists) {
333
- update_option($id, $value);
334
- } else {
335
- add_option($id, $value);
336
- }
337
- }
338
-
339
- function get_controllers() {
340
- $controllers = array();
341
- $dh = opendir(dirname(__FILE__) . '/controllers');
342
- while ($file = readdir($dh)) {
343
- if (preg_match('/(.+)\.php$/', $file, $matches)) {
344
- $controllers[] = $matches[1];
345
- }
346
- }
347
- $controllers = apply_filters('json_api_controllers', $controllers);
348
- return array_map('strtolower', $controllers);
349
- }
350
-
351
- function controller_is_active($controller) {
352
- $active_controllers = explode(',', get_option('json_api_controllers', 'core'));
353
- return (in_array($controller, $active_controllers));
354
- }
355
-
356
- function update_controllers($controllers) {
357
- if (is_array($controllers)) {
358
- return implode(',', $controllers);
359
- } else {
360
- return $controllers;
361
- }
362
- }
363
-
364
- function controller_info($controller) {
365
- $path = $this->controller_path($controller);
366
- $class = $this->controller_class($controller);
367
- $response = array(
368
- 'name' => $controller,
369
- 'description' => '(No description available)',
370
- 'methods' => array()
371
- );
372
- if (file_exists($path)) {
373
- $source = file_get_contents($path);
374
- if (preg_match('/^\s*Controller name:(.+)$/im', $source, $matches)) {
375
- $response['name'] = trim($matches[1]);
376
- }
377
- if (preg_match('/^\s*Controller description:(.+)$/im', $source, $matches)) {
378
- $response['description'] = trim($matches[1]);
379
- }
380
- if (preg_match('/^\s*Controller URI:(.+)$/im', $source, $matches)) {
381
- $response['docs'] = trim($matches[1]);
382
- }
383
- if (!class_exists($class)) {
384
- require_once($path);
385
- }
386
- $response['methods'] = get_class_methods($class);
387
- return $response;
388
- } else if (is_admin()) {
389
- return "Cannot find controller class '$class' (filtered path: $path).";
390
- } else {
391
- $this->error("Unknown controller '$controller'.");
392
- }
393
- return $response;
394
- }
395
-
396
- function controller_class($controller) {
397
- return "json_api_{$controller}_controller";
398
- }
399
-
400
- function controller_path($controller) {
401
- $dir = dirname(__FILE__);
402
- $controller_class = $this->controller_class($controller);
403
- return apply_filters("{$controller_class}_path", "$dir/controllers/$controller.php");
404
- }
405
-
406
- function get_nonce_id($controller, $method) {
407
- $controller = strtolower($controller);
408
- $method = strtolower($method);
409
- return "json_api-$controller-$method";
410
- }
411
-
412
- function flush_rewrite_rules() {
413
- global $wp_rewrite;
414
- $wp_rewrite->flush_rules();
415
- }
416
-
417
- function error($message = 'Unknown error', $status = 'error') {
418
- $this->response->respond(array(
419
- 'error' => $message
420
- ), $status);
421
- }
422
-
423
- function include_value($key) {
424
- return $this->response->is_value_included($key);
425
- }
426
-
427
- }
428
-
429
  ?>
3
  Plugin Name: JSON API
4
  Plugin URI: http://wordpress.org/extend/plugins/json-api/
5
  Description: A RESTful API for WordPress
6
+ Version: 1.0.4
7
  Author: Dan Phiffer
8
  Author URI: http://phiffer.org/
9
  */
10
 
11
+ $dir = json_api_dir();
12
+ @include_once "$dir/singletons/api.php";
13
+ @include_once "$dir/singletons/query.php";
14
+ @include_once "$dir/singletons/introspector.php";
15
+ @include_once "$dir/singletons/response.php";
16
+ @include_once "$dir/models/post.php";
17
+ @include_once "$dir/models/comment.php";
18
+ @include_once "$dir/models/category.php";
19
+ @include_once "$dir/models/tag.php";
20
+ @include_once "$dir/models/author.php";
21
+ @include_once "$dir/models/attachment.php";
22
 
23
  function json_api_init() {
24
  global $json_api;
26
  add_action('admin_notices', 'json_api_php_version_warning');
27
  return;
28
  }
29
+ if (!class_exists('JSON_API')) {
30
+ add_action('admin_notices', 'json_api_class_warning');
31
+ return;
32
+ }
33
  add_filter('rewrite_rules_array', 'json_api_rewrites');
34
  $json_api = new JSON_API();
35
  }
38
  echo "<div id=\"json-api-warning\" class=\"updated fade\"><p>Sorry, JSON API requires PHP version 5.0 or greater.</p></div>";
39
  }
40
 
41
+ function json_api_class_warning() {
42
+ echo "<div id=\"json-api-warning\" class=\"updated fade\"><p>Oops, JSON_API class not found. If you've defined a JSON_API_DIR constant, double check that the path is correct.</p></div>";
43
+ }
44
+
45
  function json_api_activation() {
46
  // Add the rewrite rule on activation
47
  global $wp_rewrite;
67
  return array_merge($json_api_rules, $wp_rules);
68
  }
69
 
70
+ function json_api_dir() {
71
+ if (defined('JSON_API_DIR') && file_exists(JSON_API_DIR)) {
72
+ return JSON_API_DIR;
73
+ } else {
74
+ return dirname(__FILE__);
75
+ }
76
+ }
77
+
78
  // Add initialization and activation hooks
79
  add_action('init', 'json_api_init');
80
  register_activation_hook("$dir/json-api.php", 'json_api_activation');
81
  register_deactivation_hook("$dir/json-api.php", 'json_api_deactivation');
82
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  ?>
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i
4
  Tags: json, api, ajax, cms, admin, integration, moma
5
  Requires at least: 2.8
6
  Tested up to: 3.0
7
- Stable tag: 1.0.3
8
 
9
  A RESTful API for WordPress
10
 
@@ -53,6 +53,7 @@ See the [Other Notes](http://wordpress.org/extend/plugins/json-api/other_notes/)
53
  5. Extending JSON API
54
  5.1. Plugin hooks
55
  5.2. Developing JSON API controllers
 
56
 
57
  == 1. General Concepts ==
58
 
@@ -878,8 +879,36 @@ Here is an example of how you might use the introspector:
878
  );
879
  }
880
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
881
  == Changelog ==
882
 
 
 
 
 
 
 
 
883
  = 1.0.3 (2010-07-07): =
884
  * Added request argument `thumbnail_size` to support different sizes of featured images (see also: `add_image_size` WordPress function)
885
  * Added request argument `post_type` to support custom post types (props Mark Harris)
@@ -962,6 +991,9 @@ Here is an example of how you might use the introspector:
962
 
963
  == Upgrade Notice ==
964
 
 
 
 
965
  = 1.0.3 =
966
  Two new request arguments added: `thumbnail_size` and `post_type`
967
 
4
  Tags: json, api, ajax, cms, admin, integration, moma
5
  Requires at least: 2.8
6
  Tested up to: 3.0
7
+ Stable tag: 1.0.4
8
 
9
  A RESTful API for WordPress
10
 
53
  5. Extending JSON API
54
  5.1. Plugin hooks
55
  5.2. Developing JSON API controllers
56
+ 5.3. Configuration options
57
 
58
  == 1. General Concepts ==
59
 
879
  );
880
  }
881
 
882
+ = External controllers =
883
+
884
+ It is recommended that custom controllers are kept outside of `json-api/controllers` in order to avoid accidental deletion during upgrades or site migrations. To make your controller visible from an external plugin or theme directory you will need to use two filters: `json_api_controllers` and `json_api_[controller]_controller_path`. Move the `hello.php` file from the steps above into your theme's directory. Then add the following to your theme's `functions.php` file (if your theme doesn't have a file called `functions.php` you can create one).
885
+
886
+ function add_hello_controller($controllers) {
887
+ $controllers[] = 'hello';
888
+ }
889
+ add_filter('json_api_controllers', 'add_hello_controller');
890
+
891
+ function set_hello_controller_path() {
892
+ return "/path/to/theme/hello.php";
893
+ }
894
+ add_filter('json_api_hello_controller_path', 'set_hello_controller_path');
895
+
896
+ == 5.3. Configuration options ==
897
+
898
+ The following are constants you can define in your `wp-config.php` folder:
899
+
900
+ * `JSON_API_DIR` - set to the directory where JSON API plugin lives (in some cases this can be useful for `mu-plugins` with WordPress MU)
901
+ * `JSON_API_CONTROLLERS` - a comma-separated list of default controllers to enable (this is overridden by the JSON API settings page)
902
+
903
  == Changelog ==
904
 
905
+ = 1.0.4 (2010-07-07): =
906
+ * Fixed a bug where the order of attachments didn't match the gallery
907
+ * Added a section to the developer documentation for externalizing custom controllers
908
+ * Moved JSON_API class to its own file: `singletons/api.php`
909
+ * Created a new top-level function: `json_api_dir()`
910
+ * Improvements for WordPress MU: `JSON_API_DIR` and `JSON_API_CONTROLLERS` constants (props Jim McQuillan)
911
+
912
  = 1.0.3 (2010-07-07): =
913
  * Added request argument `thumbnail_size` to support different sizes of featured images (see also: `add_image_size` WordPress function)
914
  * Added request argument `post_type` to support custom post types (props Mark Harris)
991
 
992
  == Upgrade Notice ==
993
 
994
+ = 1.0.4 =
995
+ Minor bugfix/refactor release
996
+
997
  = 1.0.3 =
998
  Two new request arguments added: `thumbnail_size` and `post_type`
999
 
singletons/api.php ADDED
@@ -0,0 +1,371 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class JSON_API {
4
+
5
+ function __construct() {
6
+ $this->query = new JSON_API_Query();
7
+ $this->introspector = new JSON_API_Introspector();
8
+ $this->response = new JSON_API_Response();
9
+ add_action('template_redirect', array(&$this, 'template_redirect'));
10
+ add_action('admin_menu', array(&$this, 'admin_menu'));
11
+ add_action('update_option_json_api_base', array(&$this, 'flush_rewrite_rules'));
12
+ add_action('pre_update_option_json_api_controllers', array(&$this, 'update_controllers'));
13
+ }
14
+
15
+ function template_redirect() {
16
+ // Check to see if there's an appropriate API controller + method
17
+ $controller = strtolower($this->query->get_controller());
18
+ $available_controllers = $this->get_controllers();
19
+ $enabled_controllers = explode(',', get_option('json_api_controllers', 'core'));
20
+ $active_controllers = array_intersect($available_controllers, $enabled_controllers);
21
+
22
+ if ($controller) {
23
+
24
+ if (!in_array($controller, $active_controllers)) {
25
+ $this->error("Unknown controller '$controller'.");
26
+ }
27
+
28
+ $controller_path = $this->controller_path($controller);
29
+ if (file_exists($controller_path)) {
30
+ require_once $controller_path;
31
+ }
32
+ $controller_class = $this->controller_class($controller);
33
+
34
+ if (!class_exists($controller_class)) {
35
+ $this->error("Unknown controller '$controller_class'.");
36
+ }
37
+
38
+ $this->controller = new $controller_class();
39
+ $method = $this->query->get_method($controller);
40
+
41
+ if ($method) {
42
+
43
+ $this->response->setup();
44
+
45
+ // Run action hooks for method
46
+ do_action("json_api-{$controller}-$method");
47
+
48
+ // Error out if nothing is found
49
+ if ($method == '404') {
50
+ $this->error('Not found');
51
+ }
52
+
53
+ // Run the method
54
+ $result = $this->controller->$method();
55
+
56
+ // Handle the result
57
+ $this->response->respond($result);
58
+
59
+ // Done!
60
+ exit;
61
+ }
62
+ }
63
+ }
64
+
65
+ function admin_menu() {
66
+ add_options_page('JSON API Settings', 'JSON API', 'manage_options', 'json-api', array(&$this, 'admin_options'));
67
+ }
68
+
69
+ function admin_options() {
70
+ if (!current_user_can('manage_options')) {
71
+ wp_die( __('You do not have sufficient permissions to access this page.') );
72
+ }
73
+
74
+ $available_controllers = $this->get_controllers();
75
+ $active_controllers = explode(',', get_option('json_api_controllers', 'core'));
76
+
77
+ if (count($active_controllers) == 1 && empty($active_controllers[0])) {
78
+ $active_controllers = array();
79
+ }
80
+
81
+ if (!empty($_REQUEST['_wpnonce']) && wp_verify_nonce($_REQUEST['_wpnonce'], "update-options")) {
82
+ if ((!empty($_REQUEST['action']) || !empty($_REQUEST['action2'])) &&
83
+ (!empty($_REQUEST['controller']) || !empty($_REQUEST['controllers']))) {
84
+ if (!empty($_REQUEST['action'])) {
85
+ $action = $_REQUEST['action'];
86
+ } else {
87
+ $action = $_REQUEST['action2'];
88
+ }
89
+
90
+ if (!empty($_REQUEST['controllers'])) {
91
+ $controllers = $_REQUEST['controllers'];
92
+ } else {
93
+ $controllers = array($_REQUEST['controller']);
94
+ }
95
+
96
+ foreach ($controllers as $controller) {
97
+ if (in_array($controller, $available_controllers)) {
98
+ if ($action == 'activate' && !in_array($controller, $active_controllers)) {
99
+ $active_controllers[] = $controller;
100
+ } else if ($action == 'deactivate') {
101
+ $index = array_search($controller, $active_controllers);
102
+ if ($index !== false) {
103
+ unset($active_controllers[$index]);
104
+ }
105
+ }
106
+ }
107
+ }
108
+ $this->save_option('json_api_controllers', implode(',', $active_controllers));
109
+ }
110
+ if (isset($_REQUEST['json_api_base'])) {
111
+ $this->save_option('json_api_base', $_REQUEST['json_api_base']);
112
+ }
113
+ }
114
+
115
+ ?>
116
+ <div class="wrap">
117
+ <div id="icon-options-general" class="icon32"><br /></div>
118
+ <h2>JSON API Settings</h2>
119
+ <form action="options-general.php?page=json-api" method="post">
120
+ <?php wp_nonce_field('update-options'); ?>
121
+ <h3>Controllers</h3>
122
+ <?php $this->print_controller_actions(); ?>
123
+ <table id="all-plugins-table" class="widefat">
124
+ <thead>
125
+ <tr>
126
+ <th class="manage-column check-column" scope="col"><input type="checkbox" /></th>
127
+ <th class="manage-column" scope="col">Controller</th>
128
+ <th class="manage-column" scope="col">Description</th>
129
+ </tr>
130
+ </thead>
131
+ <tfoot>
132
+ <tr>
133
+ <th class="manage-column check-column" scope="col"><input type="checkbox" /></th>
134
+ <th class="manage-column" scope="col">Controller</th>
135
+ <th class="manage-column" scope="col">Description</th>
136
+ </tr>
137
+ </tfoot>
138
+ <tbody class="plugins">
139
+ <?php
140
+
141
+ foreach ($available_controllers as $controller) {
142
+
143
+ $error = false;
144
+ $active = in_array($controller, $active_controllers);
145
+ $info = $this->controller_info($controller);
146
+
147
+ if (is_string($info)) {
148
+ $active = false;
149
+ $error = true;
150
+ $info = array(
151
+ 'name' => $controller,
152
+ 'description' => "<p><strong>Error</strong>: $info</p>",
153
+ 'methods' => array(),
154
+ 'url' => null
155
+ );
156
+ }
157
+
158
+ ?>
159
+ <tr class="<?php echo ($active ? 'active' : 'inactive'); ?>">
160
+ <th class="check-column" scope="row">
161
+ <input type="checkbox" name="controllers[]" value="<?php echo $controller; ?>" />
162
+ </th>
163
+ <td class="plugin-title">
164
+ <strong><?php echo $info['name']; ?></strong>
165
+ <div class="row-actions-visible">
166
+ <?php
167
+
168
+ if ($active) {
169
+ echo '<a href="' . wp_nonce_url('options-general.php?page=json-api&amp;action=deactivate&amp;controller=' . $controller, 'update-options') . '" title="' . __('Deactivate this controller') . '" class="edit">' . __('Deactivate') . '</a>';
170
+ } else if (!$error) {
171
+ echo '<a href="' . wp_nonce_url('options-general.php?page=json-api&amp;action=activate&amp;controller=' . $controller, 'update-options') . '" title="' . __('Activate this controller') . '" class="edit">' . __('Activate') . '</a>';
172
+ }
173
+
174
+ if ($info['url']) {
175
+ echo ' | ';
176
+ echo '<a href="' . $info['url'] . '" target="_blank">Docs</a></div>';
177
+ }
178
+
179
+ ?>
180
+ </td>
181
+ <td class="desc">
182
+ <p><?php echo $info['description']; ?></p>
183
+ <p>
184
+ <?php
185
+
186
+ foreach($info['methods'] as $method) {
187
+ $url = $this->get_method_url($controller, $method, array('dev' => 1));
188
+ if ($active) {
189
+ echo "<code><a href=\"$url\">$method</a></code> ";
190
+ } else {
191
+ echo "<code>$method</code> ";
192
+ }
193
+ }
194
+
195
+ ?>
196
+ </p>
197
+ </td>
198
+ </tr>
199
+ <?php } ?>
200
+ </tbody>
201
+ </table>
202
+ <?php $this->print_controller_actions('action2'); ?>
203
+ <h3>Address</h3>
204
+ <p>Specify a base URL for JSON API. For example, using <code>api</code> as your API base URL would enable the following <code><?php bloginfo('url'); ?>/api/get_recent_posts/</code>. If you assign a blank value the API will only be available by setting a <code>json</code> query variable.</p>
205
+ <table class="form-table">
206
+ <tr valign="top">
207
+ <th scope="row">API base</th>
208
+ <td><code><?php bloginfo('url'); ?>/</code><input type="text" name="json_api_base" value="<?php echo get_option('json_api_base', 'api'); ?>" size="15" /></td>
209
+ </tr>
210
+ </table>
211
+ <?php if (!get_option('permalink_structure', '')) { ?>
212
+ <br />
213
+ <p><strong>Note:</strong> User-friendly permalinks are not currently enabled. <a target="_blank" class="button" href="options-permalink.php">Change Permalinks</a>
214
+ <?php } ?>
215
+ <p class="submit">
216
+ <input type="submit" class="button-primary" value="<?php _e('Save Changes') ?>" />
217
+ </p>
218
+ </form>
219
+ </div>
220
+ <?php
221
+ }
222
+
223
+ function print_controller_actions($name = 'action') {
224
+ ?>
225
+ <div class="tablenav">
226
+ <div class="alignleft actions">
227
+ <select name="<?php echo $name; ?>">
228
+ <option selected="selected" value="-1">Bulk Actions</option>
229
+ <option value="activate">Activate</option>
230
+ <option value="deactivate">Deactivate</option>
231
+ </select>
232
+ <input type="submit" class="button-secondary action" id="doaction" name="doaction" value="Apply">
233
+ </div>
234
+ <div class="clear"></div>
235
+ </div>
236
+ <div class="clear"></div>
237
+ <?php
238
+ }
239
+
240
+ function get_method_url($controller, $method, $options = '') {
241
+ $url = get_bloginfo('url');
242
+ $base = get_option('json_api_base', 'api');
243
+ $permalink_structure = get_option('permalink_structure', '');
244
+ if (!empty($options) && is_array($options)) {
245
+ $args = array();
246
+ foreach ($options as $key => $value) {
247
+ $args[] = urlencode($key) . '=' . urlencode($value);
248
+ }
249
+ $args = implode('&', $args);
250
+ } else {
251
+ $args = $options;
252
+ }
253
+ if ($controller != 'core') {
254
+ $method = "$controller/$method";
255
+ }
256
+ if (!empty($base) && !empty($permalink_structure)) {
257
+ if (!empty($args)) {
258
+ $args = "?$args";
259
+ }
260
+ return "$url/$base/$method/$args";
261
+ } else {
262
+ return "$url?json=$method&$args";
263
+ }
264
+ }
265
+
266
+ function save_option($id, $value) {
267
+ $option_exists = (get_option($id, null) !== null);
268
+ if ($option_exists) {
269
+ update_option($id, $value);
270
+ } else {
271
+ add_option($id, $value);
272
+ }
273
+ }
274
+
275
+ function get_controllers() {
276
+ $controllers = array();
277
+ $dir = json_api_dir();
278
+ $dh = opendir("$dir/controllers");
279
+ while ($file = readdir($dh)) {
280
+ if (preg_match('/(.+)\.php$/', $file, $matches)) {
281
+ $controllers[] = $matches[1];
282
+ }
283
+ }
284
+ $controllers = apply_filters('json_api_controllers', $controllers);
285
+ return array_map('strtolower', $controllers);
286
+ }
287
+
288
+ function controller_is_active($controller) {
289
+ if (defined('JSON_API_CONTROLLERS')) {
290
+ $default = JSON_API_CONTROLLERS;
291
+ } else {
292
+ $default = 'core';
293
+ }
294
+ $active_controllers = explode(',', get_option('json_api_controllers', $default));
295
+ return (in_array($controller, $active_controllers));
296
+ }
297
+
298
+ function update_controllers($controllers) {
299
+ if (is_array($controllers)) {
300
+ return implode(',', $controllers);
301
+ } else {
302
+ return $controllers;
303
+ }
304
+ }
305
+
306
+ function controller_info($controller) {
307
+ $path = $this->controller_path($controller);
308
+ $class = $this->controller_class($controller);
309
+ $response = array(
310
+ 'name' => $controller,
311
+ 'description' => '(No description available)',
312
+ 'methods' => array()
313
+ );
314
+ if (file_exists($path)) {
315
+ $source = file_get_contents($path);
316
+ if (preg_match('/^\s*Controller name:(.+)$/im', $source, $matches)) {
317
+ $response['name'] = trim($matches[1]);
318
+ }
319
+ if (preg_match('/^\s*Controller description:(.+)$/im', $source, $matches)) {
320
+ $response['description'] = trim($matches[1]);
321
+ }
322
+ if (preg_match('/^\s*Controller URI:(.+)$/im', $source, $matches)) {
323
+ $response['docs'] = trim($matches[1]);
324
+ }
325
+ if (!class_exists($class)) {
326
+ require_once($path);
327
+ }
328
+ $response['methods'] = get_class_methods($class);
329
+ return $response;
330
+ } else if (is_admin()) {
331
+ return "Cannot find controller class '$class' (filtered path: $path).";
332
+ } else {
333
+ $this->error("Unknown controller '$controller'.");
334
+ }
335
+ return $response;
336
+ }
337
+
338
+ function controller_class($controller) {
339
+ return "json_api_{$controller}_controller";
340
+ }
341
+
342
+ function controller_path($controller) {
343
+ $dir = json_api_dir();
344
+ $controller_class = $this->controller_class($controller);
345
+ return apply_filters("{$controller_class}_path", "$dir/controllers/$controller.php");
346
+ }
347
+
348
+ function get_nonce_id($controller, $method) {
349
+ $controller = strtolower($controller);
350
+ $method = strtolower($method);
351
+ return "json_api-$controller-$method";
352
+ }
353
+
354
+ function flush_rewrite_rules() {
355
+ global $wp_rewrite;
356
+ $wp_rewrite->flush_rules();
357
+ }
358
+
359
+ function error($message = 'Unknown error', $status = 'error') {
360
+ $this->response->respond(array(
361
+ 'error' => $message
362
+ ), $status);
363
+ }
364
+
365
+ function include_value($key) {
366
+ return $this->response->is_value_included($key);
367
+ }
368
+
369
+ }
370
+
371
+ ?>
singletons/introspector.php CHANGED
@@ -207,7 +207,12 @@ class JSON_API_Introspector {
207
  }
208
 
209
  public function get_attachments($post_id) {
210
- $wp_attachments = get_children("post_type=attachment&post_parent=$post_id");
 
 
 
 
 
211
  $attachments = array();
212
  if (!empty($wp_attachments)) {
213
  foreach ($wp_attachments as $wp_attachment) {
207
  }
208
 
209
  public function get_attachments($post_id) {
210
+ $wp_attachments = get_children(array(
211
+ 'post_type' => 'attachment',
212
+ 'post_parent' => $post_id,
213
+ 'orderby' => 'menu_order',
214
+ 'order' => 'ASC'
215
+ ));
216
  $attachments = array();
217
  if (!empty($wp_attachments)) {
218
  foreach ($wp_attachments as $wp_attachment) {
singletons/response.php CHANGED
@@ -31,7 +31,7 @@ class JSON_API_Response {
31
  } else {
32
  // Use PEAR's Services_JSON encoder otherwise
33
  if (!class_exists('Services_JSON')) {
34
- $dir = dirname(dirname(__FILE__));
35
  require_once "$dir/library/JSON.php";
36
  }
37
  $json = new Services_JSON();
31
  } else {
32
  // Use PEAR's Services_JSON encoder otherwise
33
  if (!class_exists('Services_JSON')) {
34
+ $dir = json_api_dir();
35
  require_once "$dir/library/JSON.php";
36
  }
37
  $json = new Services_JSON();