├── README.markdown
└── system
└── expressionengine
└── third_party
└── json
├── libraries
├── Json_Template.php
└── Jsonp.php
└── pi.json.php
/README.markdown:
--------------------------------------------------------------------------------
1 | # JSON #
2 |
3 | Output ExpressionEngine data in JSON format.
4 |
5 | ## Requirements
6 |
7 | - ExpressionEngine 2.6+
8 |
9 | For older versions of EE use JSON version [1.0.3](https://github.com/rsanchez/json/tree/v1.0.3).
10 |
11 | ## Installation
12 |
13 | * Copy the /system/expressionengine/third_party/json/ folder to your /system/expressionengine/third_party/ folder
14 |
15 | ## Global Parameters
16 |
17 | ### `xhr="yes"`
18 |
19 | Set xhr to yes to only output data when an XMLHttpRequest is detected. Do not set this to yes if you are using JSONP, as JSONP requests are not true XHMLHttpRequests.
20 |
21 | ### `terminate="yes"`
22 |
23 | Set terminate to yes to terminate the template and output your json immediately, with Content-Type headers.
24 |
25 | ### `fields="title|url_title"`
26 |
27 | Specify which fields you wish to have in the array. Separate multiple fields by a pipe character. If you do not specify fields, you will get all of the default fields' data. The primary key (`entry_id` for entries, `member_id` for members) will always be present and cannot be suppressed by this parameter.
28 |
29 | ### `content_type="text/javascript"`
30 |
31 | Set a custom Content-Type header. The default is "application/json", or "application/javascript" if using JSONP. Headers are only sent when terminate is set to "yes".
32 |
33 | ### `jsonp="yes"`
34 |
35 | Set jsonp to yes to enable a JSONP response. You must also specify a valid callback. You are encouraged to set terminate to yes when using JSONP.
36 |
37 | ### `callback="yourCallbackFunction"`
38 |
39 | Set a callback function for your JSONP request. Since query strings do not work out-of-the-box in EE, you may want to consider using a URL segment to specify your callback, ie. callback="{segment_3}", rather than the standard ?callback=foo method.
40 |
41 | ### `date_format="U"`
42 |
43 | Use a different date format. Note: always returns dates as string.
44 |
45 | ### `root_node="items"`
46 |
47 | By default, JSON will output a simple array of items. Use this parameter to make the response into a JSON object whose specified property is the array of items.
48 |
49 | Using this parameter will turn this:
50 |
51 | ```
52 | [
53 | {
54 | "title": "Foo",
55 | "entry_id": 1
56 | },
57 | {
58 | "title": "Bar",
59 | "entry_id": 2
60 | }
61 | ]
62 | ```
63 |
64 | Into this:
65 |
66 | ```
67 | {
68 | "items": [
69 | {
70 | "title": "Foo",
71 | "entry_id": 1
72 | },
73 | {
74 | "title": "Bar",
75 | "entry_id": 2
76 | }
77 | ]
78 | }
79 | ```
80 |
81 | ### `item_root_node="item"`
82 |
83 | By default, each item in the response array is a simple object. Using this parameter turns each item into a JSON object whose specified property is the item object.
84 |
85 | Using this parameter will turn this:
86 |
87 | ```
88 | [
89 | {
90 | "title": "Foo",
91 | "entry_id": 1
92 | },
93 | {
94 | "title": "Bar",
95 | "entry_id": 2
96 | },
97 | ]
98 | ```
99 |
100 | Into this:
101 |
102 | ```
103 | [
104 | {
105 | "item": {
106 | "title": "Foo",
107 | "entry_id": 1
108 | }
109 | },
110 | {
111 | "item": {
112 | "title": "Bar",
113 | "entry_id": 2
114 | }
115 | }
116 | ]
117 | ```
118 |
119 | ## Dates
120 |
121 | By default, the date fields are in unix timestamp format, accurate to milliseconds. Use the Javascript Date object in combination with date field data:
122 |
123 | ```
124 | for (i in data) {
125 | var entryDate = new Date(data[i].entry_date);
126 | }
127 | ```
128 |
129 | If you require a different output format for the date fields, set the date_format= parameter. This uses the php date() function. common formats include "U" (unix timestamp in seconds), "c" (ISO 8601) or "Y-m-d H:i" (2011-12-24 19:06).
130 |
131 | ## json:entries
132 |
133 | ```
134 | {exp:json:entries channel="news"}
135 | ```
136 |
137 | json:entries is a single tag, not a tag pair. Use channel:entries parameters to filter your entries.
138 |
139 | #### json:entries Default Fields
140 |
141 | ```
142 | title
143 | url_title
144 | entry_id
145 | channel_id
146 | author_id
147 | status
148 | entry_date
149 | edit_date
150 | expiration_date
151 | Plus all of the custom fields associated with that channel
152 | ```
153 |
154 | #### json:entries Parameters
155 |
156 | See [channel:entries parameters](http://expressionengine.com/user_guide/modules/channel/parameters.html).
157 |
158 | ##### `show_categories="yes"`
159 |
160 | This will add categories to the entries response
161 |
162 | ##### `show_category_group="1|2"`
163 |
164 | When paired with show_categories="yes", this will display only categories from the specified groups.
165 |
166 | #### json:entries Custom Fields
167 |
168 | Most custom fields will just return the raw column data from the `exp_channel_data` database table. The following fieldtypes will provide custom data. You *must* specify the `channel` parameter to get custom fields.
169 |
170 | ##### Matrix
171 |
172 | The data will include an array of Matrix rows, including the row_id and the column names:
173 |
174 | ```
175 | your_matrix_field: [
176 | {
177 | row_id: 1,
178 | my_col_name: "foo",
179 | other_col_name: "bar"
180 | },
181 | {
182 | row_id: 2,
183 | my_col_name: "baz",
184 | other_col_name: "qux"
185 | }
186 | ]
187 | ```
188 |
189 | ##### Grid
190 |
191 | The data will include an array of Grid rows, including the row_id and the column names:
192 |
193 | ```
194 | your_grid_field: [
195 | {
196 | row_id: 1,
197 | my_col_name: "foo",
198 | other_col_name: "bar"
199 | },
200 | {
201 | row_id: 2,
202 | my_col_name: "baz",
203 | other_col_name: "qux"
204 | }
205 | ]
206 | ```
207 |
208 | ##### Relationships
209 |
210 | The data will include an array of related entry IDs:
211 |
212 | ```
213 | your_relationships_field: [1, 2]
214 | ```
215 |
216 | ##### Playa
217 |
218 | The data will include an array of related entry IDs:
219 |
220 | ```
221 | your_playa_field: [1, 2]
222 | ```
223 |
224 | ##### Assets
225 |
226 | ```
227 | your_assets_field: [
228 | {
229 | "file_id": 1,
230 | "url": "http://yoursite.com/uploads/flower.jpg",
231 | "subfolder": "",
232 | "filename": "flower",
233 | "extension": "jpg",
234 | "date_modified": 1389459034000,
235 | "kind": "image",
236 | "width": "300",
237 | "height": "300",
238 | "size": "65 KB",
239 | "title": null,
240 | "date": 1389459034000,
241 | "alt_text": null,
242 | "caption": null,
243 | "author": null,
244 | "desc": null,
245 | "location": null,
246 | "manipulations": {
247 | "medium": "http://yoursite.com/uploads/_medium/flower.jpg",
248 | "large": "http://yoursite.com/uploads/_large/flower.jpg"
249 | }
250 | },
251 | {
252 | "file_id": 2,
253 | "url": "http://yoursite.com/uploads/dog.jpg",
254 | "subfolder": "",
255 | "filename": "dog",
256 | "extension": "jpg",
257 | "date_modified": 1389466147000,
258 | "kind": "image",
259 | "width": "300",
260 | "height": "300",
261 | "size": "75 KB",
262 | "title": null,
263 | "date": 1389466147000,
264 | "alt_text": null,
265 | "caption": null,
266 | "author": null,
267 | "desc": null,
268 | "location": null,
269 | "manipulations": {
270 | "medium": "http://yoursite.com/uploads/_medium/dog.jpg",
271 | "large": "http://yoursite.com/uploads/_large/dog.jpg"
272 | }
273 | }
274 | ]
275 | ```
276 |
277 | *NOTE: image manipulation urls are only available to Assets files store locally, not on Amazon S3 or Google Storage.*
278 |
279 | ##### Channel Files
280 |
281 | ```
282 | your_channel_files_field: [
283 | {
284 | "file_id": 1,
285 | "url": "http://yoursite.com/uploads/flower.jpg",
286 | "filename": "flower.jpg",
287 | "extension": "jpg",
288 | "kind": "image\/jpeg",
289 | "size": "65 KB",
290 | "title": "flower",
291 | "date": 1389459034000,
292 | "author": 1,
293 | "desc": "Lorem ipsum",
294 | "primary": true,
295 | "downloads": 10,
296 | "custom1": null,
297 | "custom2": null,
298 | "custom3": null,
299 | "custom4": null,
300 | "custom5": null
301 | },
302 | {
303 | "file_id": 2,
304 | "url": "http://yoursite.com/uploads/dog.jpg",
305 | "filename": "dog.jpg",
306 | "extension": "jpg",
307 | "kind": "image\/jpeg",
308 | "size": "75 KB",
309 | "title": "dog",
310 | "date": 1389466147000,
311 | "author": 1,
312 | "desc": "Lorem ipsum",
313 | "primary": false,
314 | "downloads": 0,
315 | "custom1": null,
316 | "custom2": null,
317 | "custom3": null,
318 | "custom4": null,
319 | "custom5": null
320 | }
321 | ]
322 | ```
323 |
324 | ##### Date
325 |
326 | The data will be the Unix timestamp, accurate to milliseconds. This is because the native JavaScript Date object accepts a millisecond-based timestamp in its constructor.
327 |
328 | ```
329 | your_date_field: 1385661660000
330 | ```
331 |
332 | ## json:search
333 |
334 | ```
335 | {exp:json:search search_id="{segment_3}"}
336 | ```
337 |
338 | json:search must be paired with {exp:search:simple_form} or {exp:search:advanced_form}.
339 |
340 | #### json:search Parameters
341 |
342 | See [channel:entries parameters](http://expressionengine.com/user_guide/modules/channel/parameters.html).
343 |
344 | ##### `search_id="{segment_3}"`
345 |
346 | The native search forms will append a search_id automatically to the result_page when you submit a form.
347 |
348 | #### json:search Example
349 |
350 | ```
351 | {exp:search:simple_form channel="site" form_id="search" return_page="site/json"}
352 |
353 |
354 | {/exp:search:simple_form}
355 |
356 |
371 | ```
372 |
373 | ## json:members
374 |
375 | ```
376 | {exp:json:members member_id="1|2"}
377 | ```
378 |
379 | json:members is a single tag, not a tag pair.
380 |
381 | #### json:members Parameters
382 |
383 | ##### `member_id="1"`
384 |
385 | Specify which members, by member_id, to output. Separate multiple member_id's with a pipe character. Use `member_id="CURRENT_USER"` to get member data for just the current user.
386 |
387 | ##### `username="admin"`
388 |
389 | Specify which members, by username, to output. Separate multiple usernames with a pipe character.
390 |
391 | ##### `group_id="1"`
392 |
393 | Specify which members, by group_id, to output. Separate multiple group_id's
394 |
395 | ##### `limit="1"`
396 |
397 | Set a limit for records to retrieve.
398 |
399 |
400 | ## Advanced Examples
401 |
402 | ### JSONP
403 |
404 | If you're doing cross-domain AJAX, you will probably want to use JSONP.
405 |
406 | This is the JSON template:
407 |
408 | ```
409 | {exp:json:entries channel="site" jsonp="yes" callback="{segment_3}"}
410 | ```
411 |
412 | And the request itself:
413 |
414 | ```
415 | $.ajax({
416 | url: "http://yoursite.com/group/template/yourCallbackFunction",
417 | dataType: "jsonp",
418 | jsonp: false
419 | });
420 | function yourCallbackFunction(data) {
421 | console.log(data);
422 | }
423 | ```
424 |
425 | You'll see here that we appended the callback function to the url as a segment, rather than use the traditional ?callback=function syntax. This is because query strings do not work out of the box with EE. If you have gotten query strings to work with EE you can use the traditional approach:
426 |
427 | ```
428 | {exp:json:entries channel="site" jsonp="yes" callback=""}
429 | ```
430 |
431 | The request:
432 |
433 | ```
434 | $.ajax({
435 | url: "http://yoursite.com/group/template",
436 | dataType: "jsonp",
437 | jsonpCallback: "yourCallbackFunction"
438 | });
439 | function yourCallbackFunction(data) {
440 | console.log(data);
441 | }
442 | ```
443 |
444 | ## Changelog
445 |
446 | ### v1.1.8
447 |
448 | - Added `json_plugin_entries_end` and `json_plugin_members_end` hooks
449 | - Improved Wygwam support
450 | - Fixed intermittent disappearing `ee()->TMPL` object
451 |
452 | ### v1.1.7
453 |
454 | - Added `offset` support for members
455 |
456 | ### v1.1.6
457 |
458 | - Add Channel Files support.
459 |
460 | ### v1.1.5
461 |
462 | - Add `root_node` and `item_root_node` parameters.
463 |
464 | ### v1.1.4
465 |
466 | - Add manipulations to Assets fields
467 |
468 | ### v1.1.3
469 |
470 | - Fix bug where show_categories parameter did not work
471 |
472 | ### v1.1.2
473 |
474 | - Fix bug where `fields` parameter was not being honored
475 | - Fix bug causing fatal MySQL error when using the `fixed_order` parameter
476 |
477 | ### v1.1.1
478 |
479 | - Fix WSOD on Plugins page
480 | - Fix PHP errors when an Assests field has no selection(s)
481 |
482 | ### v1.1.0
483 |
484 | - Added support for the following fieldtypes: Assets, Grid, Playa, Relationships
485 | - Change IDs (entry_id, author_id, etc.) and Dates to integers
486 | - Added `show_categories` and `show_category_group` parameters to `{exp:json:entries}`
487 | - Added `{exp:json:search}`
488 | - Added JSONP support
489 | - Added `date_format` parameter
490 | - Added `content_type` parameter
491 |
492 | ## Upgrading from 1.0.x
493 |
494 | - IDs (entry_id, author_id, etc.) and Dates are returned as integers
495 | - The following fieldtypes have different output: Playa, Assets. Please see docs above for an example of their output.
496 |
--------------------------------------------------------------------------------
/system/expressionengine/third_party/json/libraries/Json_Template.php:
--------------------------------------------------------------------------------
1 | TMPL =& ee()->TMPL;
22 |
23 | // Override the "real" TMPL object
24 | ee()->TMPL =& $this;
25 | }
26 |
27 | public function __destruct()
28 | {
29 | // Restore the "real" TMPL object
30 | ee()->TMPL =& $this->TMPL;
31 | }
32 |
33 | public function parse_variables($tagdata, $variables, $enable_backspace = TRUE)
34 | {
35 | $output = parent::parse_variables($tagdata, $variables, $enable_backspace);
36 | $this->variables = $variables;
37 | return $output;
38 | }
39 |
40 | public function parse_variables_row($tagdata, $variables, $solo = TRUE)
41 | {
42 | $this->variables = $variables;
43 | return parent::parse_variables_row($tagdata, $variables, $solo);
44 | }
45 | }
--------------------------------------------------------------------------------
/system/expressionengine/third_party/json/libraries/Jsonp.php:
--------------------------------------------------------------------------------
1 | false,
33 | 'hello' => true,
34 | 'alert()' => false,
35 | 'test()' => false,
36 | 'a-b' => false,
37 | '23foo' => false,
38 | 'foo23' => true,
39 | '$210' => true,
40 | '_bar' => true,
41 | 'some_var' => true,
42 | '$' => true,
43 | 'somevar' => true,
44 | 'function' => false,
45 | ' somevar' => false,
46 | '$.ajaxHandler' => true,
47 | '$.23' => false,
48 | 'array_of_functions[42]' => true,
49 | 'array_of_functions[42][1]' => true,
50 | '$.ajaxHandler[42][1].foo' => true,
51 | 'array_of_functions[42]foo[1]' => false,
52 | 'array_of_functions[]' => false,
53 | 'array_of_functions["key"]' => true,
54 | 'myFunction[123].false' => false,
55 | 'myFunction .tester' => false,
56 | '_function' => true,
57 | 'petersCallback1412331422[12]' => true,
58 | ':myFunction' => false
59 | );
60 |
61 | /**
62 | * Is valid callback
63 | *
64 | * @param string $callback
65 | *
66 | * @return boolean
67 | */
68 | function isValidCallback($callback)
69 | {
70 | $reserved = array(
71 | 'break',
72 | 'do',
73 | 'instanceof',
74 | 'typeof',
75 | 'case',
76 | 'else',
77 | 'new',
78 | 'var',
79 | 'catch',
80 | 'finally',
81 | 'return',
82 | 'void',
83 | 'continue',
84 | 'for',
85 | 'switch',
86 | 'while',
87 | 'debugger',
88 | 'function',
89 | 'this',
90 | 'with',
91 | 'default',
92 | 'if',
93 | 'throw',
94 | 'delete',
95 | 'in',
96 | 'try',
97 | 'class',
98 | 'enum',
99 | 'extends',
100 | 'super',
101 | 'const',
102 | 'export',
103 | 'import',
104 | 'implements',
105 | 'let',
106 | 'private',
107 | 'public',
108 | 'yield',
109 | 'interface',
110 | 'package',
111 | 'protected',
112 | 'static',
113 | 'null',
114 | 'true',
115 | 'false'
116 | );
117 |
118 | foreach(explode('.', $callback) as $identifier) {
119 | if(!preg_match('/^[a-zA-Z_$][0-9a-zA-Z_$]*(?:\[(?:".+"|\'.+\'|\d+)\])*?$/', $identifier)) {
120 | return false;
121 | }
122 | if(in_array($identifier, $reserved)) {
123 | return false;
124 | }
125 | }
126 |
127 | return true;
128 | }
129 |
130 | /**
131 | * Test callback strings
132 | *
133 | * @param string $callback
134 | *
135 | * @return void
136 | *
137 | * @access private
138 | */
139 | private function _test($callback, $valid)
140 | {
141 | $vocal = $valid ? 'valid' : 'invalid';
142 | if($this->isValidCallback($callback) === $valid) {
143 | echo '"'.$callback.'" passed as '.$vocal.'.', "\n";
144 | return true;
145 | }
146 | else {
147 | echo '"'.$callback.'" failed as '.$vocal.'.', "\n";
148 | return false;
149 | }
150 | }
151 |
152 | /**
153 | * Run all tests
154 | *
155 | * @return void
156 | *
157 | * @access public
158 | */
159 | function runTests()
160 | {
161 | echo 'Testing ', count($this->_tests), ' callback methods:', "\n\n";
162 | $passed = 0;
163 | foreach($this->_tests as $callback => $valid) {
164 | $passed = self::_test($callback, $valid) ? $passed+1 : $passed;
165 | }
166 | echo "\n", $passed, ' of ', count($this->_tests), ' tests passed.';
167 | }
168 | }
--------------------------------------------------------------------------------
/system/expressionengine/third_party/json/pi.json.php:
--------------------------------------------------------------------------------
1 | 'JSON',
5 | 'pi_version' => '1.1.8',
6 | 'pi_author' => 'Rob Sanchez',
7 | 'pi_author_url' => 'https://github.com/rsanchez',
8 | 'pi_description' => 'Output ExpressionEngine data in JSON format.',
9 | 'pi_usage' => '
10 | {exp:json:entries channel="news"}
11 |
12 | {exp:json:entries channel="products" search:product_size="10"}
13 |
14 | {exp:json:members member_id="1"}',
15 | );
16 |
17 | class Json
18 | {
19 | /* settings */
20 | protected $content_type = 'application/json';
21 | protected $terminate = FALSE;
22 | protected $xhr = FALSE;
23 | protected $fields = array();
24 | protected $date_format = FALSE;
25 | protected $jsonp = FALSE;
26 | protected $callback;
27 |
28 | /* caches */
29 | public $entries;
30 | public $entries_entry_ids;
31 | public $entries_custom_fields;
32 | protected $entries_matrix_rows;
33 | protected $entries_matrix_cols;
34 | protected $entries_grid_rows;
35 | protected $entries_grid_cols;
36 | protected $entries_rel_data;
37 | protected $entries_relationship_data;
38 | protected $entries_playa_data;
39 | protected $entries_channel_files_data;
40 | protected $image_manipulations = array();
41 |
42 | public function entries($entry_ids = null)
43 | {
44 | $this->initialize('entries');
45 |
46 | //exit if ajax request is required and not found
47 | if ($this->check_xhr_required())
48 | {
49 | return '';
50 | }
51 |
52 | //instantiate channel module object
53 | if (empty($this->channel))
54 | {
55 | require_once PATH_MOD.'channel/mod.channel'.EXT;
56 |
57 | $this->channel = new Channel;
58 | }
59 |
60 | $this->channel->initialize();
61 |
62 | $order_by_string = '';
63 |
64 | if (is_array($entry_ids))
65 | {
66 | $this->entries_entry_ids = $entry_ids;
67 | $order_by_string = 'FIELD(t.entry_id,'.implode(',', $entry_ids).')';
68 | }
69 | else
70 | {
71 | //run through the channel module process to grab the entries
72 | $this->channel->uri = ($this->channel->query_string != '') ? $this->channel->query_string : 'index.php';
73 |
74 | if ($this->channel->enable['custom_fields'] === TRUE)
75 | {
76 | $this->channel->fetch_custom_channel_fields();
77 | }
78 |
79 | $save_cache = FALSE;
80 |
81 | if (ee()->config->item('enable_sql_caching') == 'y')
82 | {
83 | if (FALSE == ($this->channel->sql = $this->channel->fetch_cache()))
84 | {
85 | $save_cache = TRUE;
86 | }
87 | else
88 | {
89 | if (ee()->TMPL->fetch_param('dynamic') != 'no')
90 | {
91 | if (preg_match("#(^|\/)C(\d+)#", $this->channel->query_string, $match) OR in_array($this->channel->reserved_cat_segment, explode("/", $this->channel->query_string)))
92 | {
93 | $this->channel->cat_request = TRUE;
94 | }
95 | }
96 | }
97 | }
98 |
99 | if ( ! $this->channel->sql)
100 | {
101 | $this->channel->build_sql_query();
102 | }
103 |
104 | if (preg_match('/t\.entry_id IN \(([\d,]+)\)/', $this->channel->sql, $match))
105 | {
106 | $this->entries_entry_ids = explode(',', $match[1]);
107 | }
108 |
109 | if (preg_match('/ORDER BY (.*)?/', $this->channel->sql, $match))
110 | {
111 | $order_by_string = $match[1];
112 | }
113 | }
114 |
115 | if ($this->entries_entry_ids)
116 | {
117 | $this->entries_custom_fields = ee()->db->select('channel_fields.*, channels.channel_id')
118 | ->from('channel_fields')
119 | ->join('channels', 'channel_fields.group_id = channels.field_group')
120 | ->where('channels.site_id', ee()->config->item('site_id'))
121 | ->where_in('channels.channel_name', explode('|', ee()->TMPL->fetch_param('channel')))
122 | ->get()
123 | ->result_array();
124 |
125 | $default_fields = array(
126 | 't.title',
127 | 't.url_title',
128 | 't.entry_id',
129 | 't.channel_id',
130 | 't.author_id',
131 | 't.status',
132 | 't.entry_date',
133 | 't.edit_date',
134 | 't.expiration_date',
135 | );
136 |
137 | $select = array();
138 |
139 | if ( ! empty($this->fields))
140 | {
141 | foreach ($default_fields as $field)
142 | {
143 | $key = substr($field, 2);
144 |
145 | if (in_array($key, $this->fields))
146 | {
147 | $select[] = $field;
148 | }
149 | }
150 | }
151 | else
152 | {
153 | $select = $default_fields;
154 | }
155 |
156 | foreach ($this->entries_custom_fields as &$field)
157 | {
158 | if (empty($this->fields) || in_array($field['field_name'], $this->fields))
159 | {
160 | $select[] = 'wd.'.ee()->db->protect_identifiers('field_id_'.$field['field_id']).' AS '.ee()->db->protect_identifiers($field['field_name']);
161 | }
162 | }
163 |
164 | //we need entry_id, always grab it
165 | if ( ! in_array('t.entry_id', $select))
166 | {
167 | $select[] = 't.entry_id';
168 | }
169 |
170 | ee()->db->select(implode(', ', $select), FALSE)
171 | ->from('channel_titles t')
172 | ->join('channel_data wd', 't.entry_id = wd.entry_id')
173 | ->where_in('t.entry_id', $this->entries_entry_ids);
174 |
175 | if ($order_by_string)
176 | {
177 | if (strpos($order_by_string, 'w.') !== FALSE)
178 | {
179 | ee()->db->join('channels w', 't.channel_id = w.channel_id');
180 | }
181 |
182 | if (strpos($order_by_string, 'm.') !== FALSE)
183 | {
184 | ee()->db->join('members m', 'm.member_id = t.author_id');
185 | }
186 |
187 | if (strpos($order_by_string, 'md.') !== FALSE)
188 | {
189 | ee()->db->join('member_data md', 'm.member_id = md.member_id');
190 | }
191 |
192 | if (ee()->TMPL->fetch_param('display_by') === 'week' && strpos($order_by_string, 'yearweek') !== FALSE)
193 | {
194 | $yearweek = TRUE;
195 |
196 | $offset = ee()->localize->zones[ee()->config->item('server_timezone')] * 3600;
197 |
198 | $format = (ee()->TMPL->fetch_param('start_day') === 'Monday') ? '%x%v' : '%X%V';
199 |
200 | ee()->db->select("DATE_FORMAT(FROM_UNIXTIME(entry_date + $offset), '$format') AS yearweek", FALSE);
201 | }
202 |
203 | ee()->db->order_by($order_by_string, '', FALSE);
204 | }
205 |
206 | $query = $this->channel->query = ee()->db->get();
207 |
208 | $show_categories = ee()->TMPL->fetch_param('show_categories') === 'yes';
209 |
210 | if ($show_categories)
211 | {
212 | $this->channel->fetch_categories();
213 |
214 | if (ee()->TMPL->fetch_param('show_category_group'))
215 | {
216 | $show_category_group = explode('|', ee()->TMPL->fetch_param('show_category_group'));
217 | }
218 | }
219 |
220 | $this->entries = $query->result_array();
221 |
222 | $query->free_result();
223 |
224 | foreach ($this->entries as &$entry)
225 | {
226 | if (isset($yearweek))
227 | {
228 | unset($entry['yearweek']);
229 | }
230 |
231 | //format dates as javascript unix time (in microseconds!)
232 | if (isset($entry['entry_date']))
233 | {
234 | $entry['entry_date'] = $this->date_format($entry['entry_date']);
235 | }
236 |
237 | if (isset($entry['edit_date']))
238 | {
239 | $entry['edit_date'] = $this->date_format(strtotime($entry['edit_date']));
240 | }
241 |
242 | if (isset($entry['expiration_date']))
243 | {
244 | $entry['expiration_date'] = $this->date_format($entry['expiration_date']);
245 | }
246 |
247 | foreach ($this->entries_custom_fields as &$field)
248 | {
249 | //call our custom callback for this fieldtype if it exists
250 | if (isset($entry[$field['field_name']]) && is_callable(array($this, 'entries_'.$field['field_type'])))
251 | {
252 | $entry[$field['field_name']] = call_user_func(array($this, 'entries_'.$field['field_type']), $entry['entry_id'], $field, $entry[$field['field_name']], $entry);
253 | }
254 | }
255 |
256 | if ($show_categories)
257 | {
258 | $entry['categories'] = array();
259 |
260 | if (isset($this->channel->categories[$entry['entry_id']]))
261 | {
262 | foreach ($this->channel->categories[$entry['entry_id']] as $raw_category)
263 | {
264 | if ( ! empty($show_category_group) && ! in_array($raw_category[5], $show_category_group))
265 | {
266 | continue;
267 | }
268 |
269 | $category = array(
270 | 'category_id' => (int) $raw_category[0],
271 | 'parent_id' => (int) $raw_category[1],
272 | 'category_name' => $raw_category[2],
273 | 'category_image' => $raw_category[3],
274 | 'category_description' => $raw_category[4],
275 | 'category_group' => $raw_category[5],
276 | 'category_url_title' => $raw_category[6],
277 | );
278 |
279 | foreach ($this->channel->catfields as $cat_field)
280 | {
281 | $category[$cat_field['field_name']] = (isset($raw_category['field_id_'.$cat_field['field_id']])) ? $raw_category['field_id_'.$cat_field['field_id']] : '';
282 | }
283 |
284 | $entry['categories'][] = $category;
285 | }
286 | }
287 | }
288 |
289 | $entry['entry_id'] = (int) $entry['entry_id'];
290 |
291 | if (isset($entry['channel_id']))
292 | {
293 | $entry['channel_id'] = (int) $entry['channel_id'];
294 | }
295 |
296 | if (isset($entry['author_id']))
297 | {
298 | $entry['author_id'] = (int) $entry['author_id'];
299 | }
300 | }
301 | }
302 |
303 | ee()->load->library('javascript');
304 |
305 | ee()->load->library('typography');
306 |
307 | // ----------------------------------------
308 | // 'json_plugin_entries_end' hook.
309 | // - Enables additional manipulation of entry data
310 | // ----------------------------------------
311 |
312 | if (ee()->extensions->active_hook('json_plugin_entries_end') === TRUE)
313 | {
314 | ee()->extensions->call('json_plugin_entries_end', $this);
315 | if (ee()->extensions->end_script === TRUE) return;
316 | }
317 | // ----------------------------------------
318 |
319 | return $this->respond($this->entries, array(ee()->typography, 'parse_file_paths'));
320 | }
321 |
322 | protected function entries_matrix($entry_id, $field, $field_data)
323 | {
324 | if (is_null($this->entries_matrix_rows))
325 | {
326 | $query = ee()->db->where_in('entry_id', $this->entries_entry_ids)
327 | ->order_by('row_order')
328 | ->get('matrix_data');
329 |
330 | foreach ($query->result_array() as $row)
331 | {
332 | if ( ! isset($this->entries_matrix_rows[$row['entry_id']]))
333 | {
334 | $this->entries_matrix_rows[$row['entry_id']] = array();
335 | }
336 |
337 | if ( ! isset($this->entries_matrix_rows[$row['entry_id']][$row['field_id']]))
338 | {
339 | $this->entries_matrix_rows[$row['entry_id']][$row['field_id']] = array();
340 | }
341 |
342 | $this->entries_matrix_rows[$row['entry_id']][$row['field_id']][] = $row;
343 | }
344 |
345 | $query->free_result();
346 | }
347 |
348 | if (is_null($this->entries_matrix_cols))
349 | {
350 | $query = ee()->db->get('matrix_cols');
351 |
352 | foreach ($query->result_array() as $row)
353 | {
354 | $this->entries_matrix_cols[$row['col_id']] = $row;
355 | }
356 |
357 | $query->free_result();
358 | }
359 |
360 | $data = array();
361 |
362 | if (isset($this->entries_matrix_rows[$entry_id][$field['field_id']]))
363 | {
364 | $field_settings = unserialize(base64_decode($field['field_settings']));
365 |
366 | foreach ($this->entries_matrix_rows[$entry_id][$field['field_id']] as $matrix_row)
367 | {
368 | $row = array('row_id' => (int) $matrix_row['row_id']);
369 |
370 | foreach ($field_settings['col_ids'] as $col_id)
371 | {
372 | if (isset($this->entries_matrix_cols[$col_id]))
373 | {
374 | $row[$this->entries_matrix_cols[$col_id]['col_name']] = $matrix_row['col_id_'.$col_id];
375 | }
376 | }
377 |
378 | $data[] = $row;
379 | }
380 | }
381 |
382 | return $data;
383 | }
384 |
385 | protected function entries_grid($entry_id, $field, $field_data)
386 | {
387 | if ( ! isset($this->entries_grid_rows[$field['field_id']]))
388 | {
389 | $query = ee()->db->where_in('entry_id', $this->entries_entry_ids)
390 | ->order_by('row_order')
391 | ->get('channel_grid_field_'.$field['field_id']);
392 |
393 | foreach ($query->result_array() as $row)
394 | {
395 | if ( ! isset($this->entries_grid_rows[$field['field_id']][$row['entry_id']]))
396 | {
397 | $this->entries_grid_rows[$field['field_id']][$row['entry_id']] = array();
398 | }
399 |
400 | $this->entries_grid_rows[$field['field_id']][$row['entry_id']][] = $row;
401 | }
402 |
403 | $query->free_result();
404 | }
405 |
406 | if (is_null($this->entries_grid_cols))
407 | {
408 | $query = ee()->db->order_by('col_order', 'ASC')
409 | ->get('grid_columns');
410 |
411 | foreach ($query->result_array() as $row)
412 | {
413 | if ( ! isset($this->entries_grid_cols[$row['field_id']]))
414 | {
415 | $this->entries_grid_cols[$row['field_id']] = array();
416 | }
417 |
418 | $this->entries_grid_cols[$row['field_id']][$row['col_id']] = $row;
419 | }
420 |
421 | $query->free_result();
422 | }
423 |
424 | $data = array();
425 |
426 | if (isset($this->entries_grid_rows[$field['field_id']][$entry_id]) && isset($this->entries_grid_cols[$field['field_id']]))
427 | {
428 | foreach ($this->entries_grid_rows[$field['field_id']][$entry_id] as $grid_row)
429 | {
430 | $row = array('row_id' => (int) $grid_row['row_id']);
431 |
432 | foreach ($this->entries_grid_cols[$field['field_id']] as $col_id => $col)
433 | {
434 | $row[$col['col_name']] = $grid_row['col_id_'.$col_id];
435 | }
436 |
437 | $data[] = $row;
438 | }
439 | }
440 |
441 | return $data;
442 | }
443 |
444 | protected function entries_rel($entry_id, $field, $field_data)
445 | {
446 | if (is_null($this->entries_rel_data))
447 | {
448 | $query = ee()->db->select('rel_child_id, rel_id')
449 | ->where('rel_parent_id', $entry_id)
450 | ->get('relationships');
451 |
452 | $this->entries_rel_data = array();
453 |
454 | foreach ($query->result() as $row)
455 | {
456 | $this->entries_rel_data[$row->rel_id] = (int) $row->rel_child_id;
457 | }
458 |
459 | $query->free_result();
460 | }
461 |
462 | if ( ! isset($this->entries_rel_data[$field_data]))
463 | {
464 | return NULL;
465 | }
466 |
467 | return $this->entries_rel_data[$field_data];
468 | }
469 |
470 | protected function entries_relationship($entry_id, $field, $field_data)
471 | {
472 | if (is_null($this->entries_relationship_data))
473 | {
474 | $query = ee()->db->select('parent_id, child_id, field_id')
475 | ->where_in('parent_id', $this->entries_entry_ids)
476 | ->order_by('order', 'asc')
477 | ->get('relationships');
478 |
479 | foreach ($query->result_array() as $row)
480 | {
481 | if ( ! isset($this->entries_relationship_data[$row['parent_id']]))
482 | {
483 | $this->entries_relationship_data[$row['parent_id']] = array();
484 | }
485 |
486 | if ( ! isset($this->entries_relationship_data[$row['parent_id']][$row['field_id']]))
487 | {
488 | $this->entries_relationship_data[$row['parent_id']][$row['field_id']] = array();
489 | }
490 |
491 | $this->entries_relationship_data[$row['parent_id']][$row['field_id']][] = (int) $row['child_id'];
492 | }
493 |
494 | $query->free_result();
495 | }
496 |
497 | if (isset($this->entries_relationship_data[$entry_id][$field['field_id']]))
498 | {
499 | return $this->entries_relationship_data[$entry_id][$field['field_id']];
500 | }
501 |
502 | return array();
503 | }
504 |
505 | protected function entries_playa($entry_id, $field, $field_data)
506 | {
507 | if (is_null($this->entries_playa_data))
508 | {
509 | $query = ee()->db->select('parent_entry_id, child_entry_id, parent_field_id')
510 | ->where_in('parent_entry_id', $this->entries_entry_ids)
511 | ->order_by('rel_order', 'asc')
512 | ->get('playa_relationships');
513 |
514 | foreach ($query->result_array() as $row)
515 | {
516 | if ( ! isset($this->entries_playa_data[$row['parent_entry_id']]))
517 | {
518 | $this->entries_playa_data[$row['parent_entry_id']] = array();
519 | }
520 |
521 | if ( ! isset($this->entries_playa_data[$row['parent_entry_id']][$row['parent_field_id']]))
522 | {
523 | $this->entries_playa_data[$row['parent_entry_id']][$row['parent_field_id']] = array();
524 | }
525 |
526 | $this->entries_playa_data[$row['parent_entry_id']][$row['parent_field_id']][] = (int) $row['child_entry_id'];
527 | }
528 |
529 | $query->free_result();
530 | }
531 |
532 | if (isset($this->entries_playa_data[$entry_id][$field['field_id']]))
533 | {
534 | return $this->entries_playa_data[$entry_id][$field['field_id']];
535 | }
536 |
537 | return array();
538 | }
539 |
540 | protected function entries_channel_files($entry_id, $field, $field_data, $entry)
541 | {
542 | $this->entries_channel_files_data = array();
543 |
544 | $field_settings = unserialize(base64_decode($field['field_settings']));
545 | $field_settings = $field_settings['channel_files'];
546 |
547 | $query = ee()->db->select()
548 | ->where('entry_id', $entry_id)
549 | ->where('field_id', $field['field_id'])
550 | ->order_by('file_order', 'asc')
551 | ->get('channel_files');
552 |
553 | foreach ($query->result_array() as $row)
554 | {
555 | $field_data = array(
556 | 'file_id' => (int) $row['file_id'],
557 | 'url' => $row['filename'],
558 | 'filename' => $row['filename'],
559 | 'extension' => $row['extension'],
560 | 'kind' => $row['mime'],
561 | 'size' => $row['filesize'],
562 | 'title' => $row['title'],
563 | 'date' => $this->date_format($row['date']),
564 | 'author' => (int)$row['member_id'],
565 | 'desc' => $row['description'],
566 | 'primary' => (bool)$row['file_primary'],
567 | 'downloads' => (int)$row['downloads'],
568 | 'custom1' => (isset($row['cffield1']) ? $row['cffield1'] : null),
569 | 'custom2' => (isset($row['cffield2']) ? $row['cffield2'] : null),
570 | 'custom3' => (isset($row['cffield3']) ? $row['cffield3'] : null),
571 | 'custom4' => (isset($row['cffield4']) ? $row['cffield4'] : null),
572 | 'custom5' => (isset($row['cffield5']) ? $row['cffield5'] : null)
573 | );
574 |
575 | $fieldtype_specific_settings = $field_settings['locations'][$row['upload_service']];
576 |
577 | switch ($row['upload_service'])
578 | {
579 | case 'local':
580 | // get upload folder details from EE
581 | $query = ee()->db->select('url')
582 | ->where('id', $fieldtype_specific_settings['location'])
583 | ->get('exp_upload_prefs');
584 |
585 | $result = $query->row_array();
586 | $query->free_result();
587 |
588 | $base_url = $result['url'] . ($field_settings['entry_id_folder'] == 'yes' ? $entry_id . '/' : '');
589 | $field_data['url'] = $base_url . $field_data['url'];
590 | break;
591 | case 's3':
592 | if ($fieldtype_specific_settings['cloudfront_domain'] != '')
593 | {
594 | $domain = rtrim($fieldtype_specific_settings['cloudfront_domain'], '/');
595 | $domain = 'http://' . preg_replace('#https?://#', '', $domain);
596 | }
597 | else
598 | {
599 | $domain = "http://{$fieldtype_specific_settings['bucket']}.s3.amazonaws.com";
600 | }
601 |
602 |
603 | $dir = ($fieldtype_specific_settings['directory'] != '' ? rtrim($fieldtype_specific_settings['directory'], '/') . '/' : '');
604 |
605 | $base_url = "{$domain}/{$dir}{$entry_id}/";
606 | $field_data['url'] = $base_url . $field_data['url'];
607 | break;
608 | case 'cloudfiles':
609 | case 'ftp':
610 | case 'sftp':
611 | require_once PATH_THIRD.'channel_files/locations/cfile_location.php';
612 | require_once PATH_THIRD."channel_files/locations/{$row['upload_service']}/{$row['upload_service']}.php";
613 |
614 | $class_name = "CF_Location_{$row['upload_service']}";
615 | $cf = new $class_name($fieldtype_specific_settings);
616 | $dir = $entry_id;
617 | $entry_id_folder = (isset($fieldtype_specific_settings['entry_id_folder']) ? $fieldtype_specific_settings['entry_id_folder'] : null);;
618 | if (isset($entry_id_folder) && $fieldtype_specific_settings['entry_id_folder'] == 'no')
619 | {
620 | $dir = FALSE;
621 | }
622 |
623 | $field_data['url'] = $cf->parse_file_url($dir, $field_data['url']);
624 | break;
625 | default:
626 | break;
627 | }
628 |
629 | // make file size relevant
630 | $units = array('B', 'KB', 'MB', 'GB');
631 | $units_index = 0;
632 | while ($field_data['size'] >= 1024)
633 | {
634 | $field_data['size'] /= 1024;
635 | $units_index++;
636 | }
637 | $field_data['size'] = round($field_data['size']) . ' ' . $units[$units_index];
638 |
639 | $this->entries_channel_files_data[$row['field_id']][] = $field_data;
640 | }
641 |
642 | $query->free_result();
643 |
644 | if (isset($row['field_id'], $this->entries_channel_files_data[$row['field_id']]))
645 | {
646 | return $this->entries_channel_files_data[$row['field_id']];
647 | }
648 |
649 | return array();
650 | }
651 |
652 | protected function entries_date($entry_id, $field, $field_data)
653 | {
654 | return $this->date_format($field_data);
655 | }
656 |
657 | protected function entries_text($entry_id, $field, $field_data)
658 | {
659 | $field_settings = ee()->api_channel_fields->get_settings($field['field_id']);
660 |
661 | if ($field_settings['field_content_type'] === 'numeric' || $field_settings['field_content_type'] === 'decimal')
662 | {
663 | return floatval($field_data);
664 | }
665 |
666 | if ($field_settings['field_content_type'] === 'integer')
667 | {
668 | return intval($field_data);
669 | }
670 |
671 | return $field_data;
672 | }
673 |
674 | protected function entries_custom_field($entry_id, $field, $field_data, $entry, $tagdata = ' ')
675 | {
676 | ee()->load->add_package_path(ee()->api_channel_fields->ft_paths[$field['field_type']], FALSE);
677 |
678 | ee()->api_channel_fields->setup_handler($field['field_id']);
679 |
680 | ee()->api_channel_fields->apply('_init', array(array(
681 | 'row' => $entry,
682 | 'content_id' => $entry['entry_id'],
683 | 'content_type' => 'channel',
684 | )));
685 |
686 | $field_data = ee()->api_channel_fields->apply('pre_process', array($field_data));
687 |
688 | if (ee()->api_channel_fields->check_method_exists('replace_tag'))
689 | {
690 | require_once PATH_THIRD.'json/libraries/Json_Template.php';
691 |
692 | $ee_tmpl = ee()->TMPL;
693 | $template = new Json_Template();
694 |
695 | $field_data = ee()->api_channel_fields->apply('replace_tag', array($field_data, array(), $tagdata));
696 |
697 | if ($template->variables)
698 | {
699 | $field_data = $template->variables;
700 | }
701 |
702 | unset($template);
703 | ee()->TMPL = $ee_tmpl;
704 | }
705 |
706 | ee()->load->remove_package_path(ee()->api_channel_fields->ft_paths[$field['field_type']]);
707 |
708 | return $field_data;
709 | }
710 |
711 | protected function entries_wygwam($entry_id, $field, $field_data, $entry) {
712 | return $this->entries_custom_field($entry_id, $field, $field_data, $entry);
713 | }
714 |
715 | protected function entries_assets($entry_id, $field, $field_data, $entry)
716 | {
717 | $field_data = $this->entries_custom_field($entry_id, $field, $field_data, $entry);
718 |
719 | if ( ! is_array($field_data))
720 | {
721 | $field_data = array();
722 | }
723 |
724 | if (isset($field_data['absolute_total_files']) && $field_data['absolute_total_files'] === 0)
725 | {
726 | return array();
727 | }
728 |
729 | $fields = array(
730 | 'file_id',
731 | 'url',
732 | 'subfolder',
733 | 'filename',
734 | 'extension',
735 | 'date_modified',
736 | 'kind',
737 | 'width',
738 | 'height',
739 | 'size',
740 | 'title',
741 | 'date',
742 | 'alt_text',
743 | 'caption',
744 | 'author',
745 | 'desc',
746 | 'location',
747 | );
748 |
749 | foreach ($field_data as &$row)
750 | {
751 | $source_type = $row['source_type'];
752 | $filedir_id = $row['filedir_id'];
753 | //excise any other fields from this row
754 | $row = array_intersect_key($row, array_flip($fields));
755 | $row['file_id'] = (int) $row['file_id'];
756 | $row['date'] = $this->date_format($row['date']);
757 | $row['date_modified'] = $this->date_format($row['date_modified']);
758 |
759 | $row['manipulations'] = array();
760 |
761 | if ($source_type === 'ee')
762 | {
763 | if ( ! isset($this->image_manipulations[$filedir_id]))
764 | {
765 | ee()->load->model('file_model');
766 |
767 | $query = ee()->file_model->get_dimensions_by_dir_id($filedir_id);
768 |
769 | $this->image_manipulations[$filedir_id] = $query->result();
770 |
771 | $query->free_result();
772 | }
773 |
774 | foreach ($this->image_manipulations[$filedir_id] as $manipulation)
775 | {
776 | $row['manipulations'][$manipulation->short_name] = pathinfo($row['url'], PATHINFO_DIRNAME).'/_'.$manipulation->short_name.'/'.basename($row['url']);
777 | }
778 | }
779 | }
780 |
781 | return $field_data;
782 | }
783 |
784 | public function search()
785 | {
786 | $search_id = ee()->TMPL->fetch_param('search_id');
787 |
788 | if ( ! $search_id)
789 | {
790 | $search_id = end(ee()->uri->segment_array());
791 | }
792 |
793 | if ($search_id)
794 | {
795 | $query = ee()->db->where('search_id', $search_id)
796 | ->limit(1)
797 | ->get('exp_search');
798 |
799 | if ($query->num_rows() > 0)
800 | {
801 | $search = $query->row_array();
802 |
803 | $query->free_result();
804 |
805 | if (preg_match('/IN \(([\d,]+)\)/', $query->row('query'), $match))
806 | {
807 | ee()->TMPL->tagparams['entry_id'] = (strpos($match[1], ',') !== FALSE) ? str_replace(',', '|', $match[1]) : $match[1];
808 |
809 | return $this->entries();
810 | }
811 | }
812 | }
813 |
814 | $this->initialize();
815 |
816 | return $this->respond(array());
817 | }
818 |
819 | /**
820 | * Categories
821 | *
822 | * @TODO a work in progress, does not work yet
823 | *
824 | * @param array|null $params
825 | *
826 | * @return string
827 | */
828 | public function categories($params = NULL)
829 | {
830 | $this->initialize();
831 |
832 | if (is_null($params))
833 | {
834 | $params = ee()->TMPL->tagparams;
835 | }
836 |
837 | ee()->load->helper('array');
838 |
839 | $channel = element('channel', $params);
840 | $group_id = element('group_id', $params, element('category_group', $params));
841 | $cat_id = element('cat_id', $params, element('category_id', $params, element('show', $params)));
842 | $status = element('status', $params);
843 | $parent_only = element('parent_only', $params);
844 | $show_empty = element('show_empty', $params, TRUE);
845 | $joins = array();
846 |
847 | if ($channel)
848 | {
849 | ee()->db->join('channel_titles', 'channel_titles.entry_id = category_posts.entry_id');
850 | ee()->db->join('channels', 'channels.channel_id = channel_titles.channel_id');
851 | ee()->db->where_in('channels.channel_name', explode('|', $channel));
852 | $joins[] = 'channels';
853 | $joins[] = 'channel_titles';
854 | }
855 |
856 | if ($group_id)
857 | {
858 | ee()->db->where_in('categories.group_id', explode('|', $group_id));
859 | }
860 |
861 | if ($cat_id)
862 | {
863 | ee()->db->where_in('categories.cat_id', explode('|', $cat_id));
864 | }
865 |
866 | if ($status)
867 | {
868 | if ( ! in_array('channel_titles', $joins))
869 | {
870 | ee()->db->join('channel_titles', 'channel_titles.entry_id = category_posts.entry_id');
871 | }
872 |
873 | ee()->db->where_in('channel_titles.status', explode('|', $status));
874 | }
875 |
876 | if ($parent_only)
877 | {
878 | ee()->db->where('categories.parent_id', 0);
879 | }
880 |
881 | if ($show_empty)
882 | {
883 | ee()->db->where('count >', 0);
884 | }
885 | }
886 |
887 | /**
888 | * Members
889 | *
890 | * @return string
891 | */
892 | public function members()
893 | {
894 | $this->initialize();
895 |
896 | if ($this->check_xhr_required())
897 | {
898 | return '';
899 | }
900 |
901 | $default_fields = array(
902 | 'm.member_id',
903 | 'm.group_id',
904 | 'm.username',
905 | 'm.screen_name',
906 | 'm.email',
907 | 'm.signature',
908 | 'm.avatar_filename',
909 | 'm.avatar_width',
910 | 'm.avatar_height',
911 | 'm.photo_filename',
912 | 'm.photo_width',
913 | 'm.photo_height',
914 | 'm.url',
915 | 'm.location',
916 | 'm.occupation',
917 | 'm.interests',
918 | 'm.bio',
919 | 'm.join_date',
920 | 'm.last_visit',
921 | 'm.last_activity',
922 | 'm.last_entry_date',
923 | 'm.last_comment_date',
924 | 'm.last_forum_post_date',
925 | 'm.total_entries',
926 | 'm.total_comments',
927 | 'm.total_forum_topics',
928 | 'm.total_forum_posts',
929 | 'm.language',
930 | 'm.timezone',
931 | 'm.bday_d',
932 | 'm.bday_m',
933 | 'm.bday_y',
934 | );
935 |
936 | if (version_compare(APP_VER, '2.6', '<'))
937 | {
938 | $default_fields[] = 'm.daylight_savings';
939 | }
940 |
941 | $query = ee()->db->select('m_field_id, m_field_name')
942 | ->get('member_fields');
943 |
944 | $custom_fields = $query->result_array();
945 |
946 | $query->free_result();
947 |
948 | $select = array();
949 |
950 | if ( ! empty($this->fields))
951 | {
952 | foreach ($default_fields as $field)
953 | {
954 | $key = substr($field, 2);
955 |
956 | if (in_array($key, $this->fields))
957 | {
958 | $select[] = $field;
959 | }
960 | }
961 | }
962 | else
963 | {
964 | $select = $default_fields;
965 | }
966 |
967 | foreach ($custom_fields as &$field)
968 | {
969 | if (empty($this->fields) || in_array($field['m_field_name'], $this->fields))
970 | {
971 | $select[] = 'd.'.ee()->db->protect_identifiers('m_field_id_'.$field['m_field_id']).' AS '.ee()->db->protect_identifiers($field['m_field_name']);
972 | }
973 | }
974 |
975 | ee()->db->select(implode(', ', $select), FALSE)
976 | ->from('members m')
977 | ->join('member_data d', 'm.member_id = d.member_id');
978 |
979 | if ($member_ids = ee()->TMPL->fetch_param('member_id'))
980 | {
981 | if ($member_ids === 'CURRENT_USER')
982 | {
983 | $member_ids = ee()->session->userdata('member_id');
984 | }
985 |
986 | ee()->db->where_in('m.member_id', explode('|', $member_ids));
987 | }
988 | else if (ee()->TMPL->fetch_param('username'))
989 | {
990 | ee()->db->where_in('m.member_id', explode('|', ee()->TMPL->fetch_param('member_id')));
991 | }
992 |
993 | if (ee()->TMPL->fetch_param('group_id'))
994 | {
995 | ee()->db->where_in('m.group_id', explode('|', ee()->TMPL->fetch_param('group_id')));
996 | }
997 |
998 | if (ee()->TMPL->fetch_param('limit'))
999 | {
1000 | ee()->db->limit(ee()->TMPL->fetch_param('limit'));
1001 | }
1002 |
1003 | if (ee()->TMPL->fetch_param('offset'))
1004 | {
1005 | ee()->db->offset(ee()->TMPL->fetch_param('offset'));
1006 | }
1007 |
1008 | $query = ee()->db->get();
1009 |
1010 | $members = $query->result_array();
1011 |
1012 | $query->free_result();
1013 |
1014 | $date_fields = array(
1015 | 'join_date',
1016 | 'last_visit',
1017 | 'last_activity',
1018 | 'last_entry_date',
1019 | 'last_comment_date',
1020 | 'last_forum_post_date'
1021 | );
1022 |
1023 | foreach ($members as &$member)
1024 | {
1025 | foreach ($date_fields as $field)
1026 | {
1027 | if (isset($member[$field]))
1028 | {
1029 | $member[$field] = $this->date_format($member[$field]);
1030 | }
1031 | }
1032 | }
1033 |
1034 | // ----------------------------------------
1035 | // 'json_plugin_members_end' hook.
1036 | // - Enables additional manipulation of entry data
1037 | // ----------------------------------------
1038 |
1039 | if (ee()->extensions->active_hook('json_plugin_members_end') === TRUE)
1040 | {
1041 | $members = ee()->extensions->call('json_plugin_members_end', $members, $this);
1042 | if (ee()->extensions->end_script === TRUE) return;
1043 | }
1044 | // ----------------------------------------
1045 |
1046 | return $this->respond($members);
1047 | }
1048 |
1049 | protected function initialize($which = NULL)
1050 | {
1051 | switch($which)
1052 | {
1053 | case 'entries':
1054 | //initialize caches
1055 | $this->entries = array();
1056 | $this->entries_entry_ids = array();
1057 | $this->entries_custom_fields = array();
1058 | $this->entries_matrix_rows = NULL;
1059 | $this->entries_rel_data = NULL;
1060 | $this->entries_relationship_data = NULL;
1061 | $this->entries_playa_data = NULL;
1062 | $this->entries_channel_files_data = NULL;
1063 | break;
1064 | }
1065 |
1066 | $this->xhr = ee()->TMPL->fetch_param('xhr') === 'yes';
1067 |
1068 | $this->terminate = ee()->TMPL->fetch_param('terminate') === 'yes';
1069 |
1070 | $this->fields = (ee()->TMPL->fetch_param('fields')) ? explode('|', ee()->TMPL->fetch_param('fields')) : array();
1071 |
1072 | $this->date_format = ee()->TMPL->fetch_param('date_format');
1073 |
1074 | // get rid of EE formatted dates
1075 | if ($this->date_format && strstr($this->date_format, '%'))
1076 | {
1077 | $this->date_format = str_replace('%', '', $this->date_format);
1078 | }
1079 |
1080 | $this->jsonp = ee()->TMPL->fetch_param('jsonp') === 'yes';
1081 |
1082 | ee()->load->library('jsonp');
1083 |
1084 | $this->callback = (ee()->TMPL->fetch_param('callback') && ee()->jsonp->isValidCallback(ee()->TMPL->fetch_param('callback')))
1085 | ? ee()->TMPL->fetch_param('callback') : NULL;
1086 |
1087 | $this->content_type = ee()->TMPL->fetch_param('content_type', ($this->jsonp && $this->callback) ? 'application/javascript' : 'application/json');
1088 | }
1089 |
1090 | protected function check_xhr_required()
1091 | {
1092 | return $this->xhr && ! ee()->input->is_ajax_request();
1093 | }
1094 |
1095 | protected function date_format($date)
1096 | {
1097 | if ( ! $date)
1098 | {
1099 | return NULL;
1100 | }
1101 |
1102 | return ($this->date_format) ? date($this->date_format, $date) : $date * 1000;
1103 | }
1104 |
1105 | protected function respond(array $response, $callback = NULL)
1106 | {
1107 | ee()->load->library('javascript');
1108 |
1109 | if ($item_root_node = ee()->TMPL->fetch_param('item_root_node'))
1110 | {
1111 | $response_with_nodes = array();
1112 |
1113 | foreach($response as $item)
1114 | {
1115 | $response_with_nodes[] = array($item_root_node => $item);
1116 | }
1117 |
1118 | $response = $response_with_nodes;
1119 | }
1120 |
1121 | if ($root_node = ee()->TMPL->fetch_param('root_node'))
1122 | {
1123 | $response = array($root_node => $response);
1124 | }
1125 |
1126 | $response = function_exists('json_encode')
1127 | ? json_encode($response)
1128 | : ee()->javascript->generate_json($response, TRUE);
1129 |
1130 | if ( ! is_null($callback))
1131 | {
1132 | $response = call_user_func($callback, $response);
1133 | }
1134 |
1135 | if ($this->check_xhr_required())
1136 | {
1137 | $response = '';
1138 | }
1139 | else if ($this->jsonp && $this->callback)
1140 | {
1141 | $response = sprintf('%s(%s)', $this->callback, $response);
1142 | }
1143 |
1144 | if ($this->terminate)
1145 | {
1146 | @header('Content-Type: '.$this->content_type);
1147 |
1148 | exit($response);
1149 | }
1150 |
1151 | return $response;
1152 | }
1153 | }
1154 |
1155 | /* End of file pi.json.php */
1156 | /* Location: ./system/expressionengine/third_party/json/pi.json.php */
1157 |
--------------------------------------------------------------------------------