'2.0', 'path' => drupal_get_path('module', 'views_json') . '/views', ); } /** * Implements hook_views_pre_render(). */ function views_json_views_pre_render(&$view) { if (isset($view->plugin_name) && $view->plugin_name == 'views_json') { // Support for Video field. if (!empty($view->result)) { // Process each View result. foreach ($view->result as $row => $result) { // Only process the entity fields defined by the View. foreach ($view->field as $field_name => $field) { if ($field instanceof views_handler_field_field) { if ($field->field_info['type'] == 'video') { // Get the Video URL. $video = $field->get_value($view->result[$row]); $url = file_create_url($video[0]['uri']); $render_array = array( '#type' => 'markup', '#markup' => filter_xss($url), ); // Substitute embed code with URL. @todo Add support for escaped embed codes. $view->result[$row]->{'field_' . $field_name}[0]['rendered'] = $render_array; } } } } } } } /** * We almost duplicate the content_handler_field_multiple::render function * to get the multiple rendered field values in an array * @param $field * @param $values * @return unknown_type */ function _views_json_render_multiple_field($field, $values) { $options = $field->options; // If this is not a grouped field, use content_handler_field::render(). if (!$field->defer_query) { return $field->render($values); } // We're down to a single node here, so we can retrieve the actual field // definition for the node type being considered. $content_field = content_fields($field->content_field['field_name'], $values->{$field->aliases['type']}); $vid = $values->{$field->field_alias}; if (isset($field->field_values[$vid])) { // Gather items, respecting the 'Display n values starting from m' settings. $count_skipped = 0; $items = array(); foreach ($field->field_values[$vid] as $item) { if (empty($options['multiple']['multiple_from']) || ($count_skipped >= $options['multiple']['multiple_from'])) { if (empty($options['multiple']['multiple_number']) || (count($items) < $options['multiple']['multiple_number'])) { // Grab the nid - needed for render_link(). $nid = $item['_nid']; unset($item['_nid']); $items[] = $item; } else { break; } } $count_skipped++; } // Build a pseudo-node from the retrieved values. $node = drupal_clone($values); // content_format and formatters will need a 'type'. $node->type = $values->{$field->aliases['type']}; $node->nid = $values->{$field->aliases['nid']}; $node->vid = $values->{$field->aliases['vid']}; // Some formatters need to behave differently depending on the build_mode // (for instance: preview), so we provide one. $node->build_mode = NODE_BUILD_NORMAL; // Render items. $formatter_name = $options['format']; if ($items && ($formatter = _content_get_formatter($formatter_name, $content_field['type']))) { $rendered = array(); if (content_handle('formatter', 'multiple values', $formatter) == CONTENT_HANDLE_CORE) { // Single-value formatter. $n = 0; foreach ($items as $item) { $output = content_format($content_field, $item, $formatter_name, $node); if (!empty($output)) { $rendered[++$n] = $field->render_link($output, (object) array('nid' => $nid)); } } } else { // Multiple values formatter. $output = content_format($content_field, $items, $formatter_name, $values); if (!empty($output)) { $rendered[++$n] = $field->render_link($output, (object) array('nid' => $nid)); } } if (count($rendered) > 1) { // TODO: could we use generic field display ? //return theme('content_view_multiple_field', $rendered, $content_field, $values); return $rendered; } elseif ($rendered) { return $rendered[1]; } } } return ''; } /** * Takes each field from a row object and renders the field as determined by the field's theme * * @param $view * View the row belongs to * @param $row * Row object * @return array * Object containing all the raw and rendered fields */ function _views_json_render_fields($view, $row) { $field_ids = array_keys($view->field); $fields_info = $view->display_handler->get_option('fields'); $rendered_fields = array(); foreach ($field_ids as $id) { $field = $view->field[$id]; $field_is_multiple = FALSE; $field_raw = array(); if ((isset($field->options['multiple']['group'])) && isset($field->field_values)) { $field_output = _views_json_render_multiple_field($field, $row); $n = 0; if (is_array($field_output)) { foreach ($field->field_values[$row->{$field->field_alias}] as $item) { $field_raw[++$n] = $item["value"]; } $field_is_multiple = TRUE; } else { $field_raw = $view->field[$field->options['id']]->advanced_render($row); } } else { $field_output = $view->field[$field->options['id']]->advanced_render($row); $field_raw = (isset($view->field[$id]->field_alias) && isset($row->{$view->field[$id]->field_alias})) ? $row->{$view->field[$id]->field_alias} : NULL; // Check if this is field is the entity's label. if (empty($field->base_table)) { $entity_info = entity_get_info($field->table); if (isset($entity_info['entity keys']['label'])) { $label_field = $entity_info['entity keys']['label']; if ($field->real_field == $label_field) { // Decode html entities in label field as views does this by default for those fields. $field_output = html_entity_decode($field_output, ENT_QUOTES); $field_output = mb_check_encoding($field_output, 'UTF-8') ? $field_output : utf8_encode($field_output); } } } } $img_match = array(); $src_match = array(); if (isset($field->options['type'])) { if (is_array($field_output) && $field->options['type'] == 'image') { foreach ($field_output as $i => $f) { if (preg_match("/]+>/i", $f, $img_match)) { if (preg_match('/(src)="([^"]*)"/i', $img_match[0], $src_match)) { $field_output[$i]['src'] = $src_match[2]; $field_output[$i]['alt'] = ''; $field_output[$i]['title'] = ''; if (preg_match('/(alt)="([^"]*)"/i', $img_match[0], $alt_match)) { $field_output[$i]['alt'] = $alt_match[2]; } if (preg_match('/(title)="([^"]*)"/i', $img_match[0], $alt_match)) { $field_output[$i]['title'] = $alt_match[2]; } } } } } else { if ($field->options['type'] == 'image') { // if field's type was an image. we just get the path. if (preg_match_all("/]+>/i", $field_output, $img_matches)) { $field_output = array(); if (sizeof($img_matches[0]) > 1) { $field_is_multiple = TRUE; foreach ($img_matches[0] as $i => $img_match) { if (preg_match('/(src)="([^"]*)"/i', $img_match, $src_match)) { $field_output[$i]['src'] = $src_match[2]; $field_output[$i]['alt'] = ''; $field_output[$i]['title'] = ''; if (preg_match('/(alt)="([^"]*)"/i', $img_match, $alt_match)) { $field_output[$i]['alt'] = $alt_match[2]; } if (preg_match('/(title)="([^"]*)"/i', $img_match, $alt_match)) { $field_output[$i]['title'] = $alt_match[2]; } } } } else { if (preg_match('/(src)="([^"]*)"/i', $img_matches[0][0], $src_match)) { $field_output['src'] = $src_match[2]; $field_output['alt'] = ''; $field_output['title'] = ''; if (preg_match('/(alt)="([^"]*)"/i', $img_matches[0][0], $alt_match)) { $field_output['alt'] = $alt_match[2]; } if (preg_match('/(title)="([^"]*)"/i', $img_matches[0][0], $alt_match)) { $field_output['title'] = $alt_match[2]; } } } } } } } if (empty($field->options['exclude'])) { if (empty($field->options['exclude']) && !($field->options['hide_empty'] && (empty($field_output)))) { $object = new stdClass(); $object->id = $id; // Respect the 'empty' value if empty and "No results text" is given. if (empty($field_output) && $field->options['empty']) { $object->content = $field->options['empty']; } else { $object->content = $field_output; } $object->raw = $field_raw; $object->class = drupal_clean_css_identifier(strtolower($id));//views_css_safe($id); if (isset($view->style_options['translate_labels']) && $view->style_options['translate_labels']) { $label = $view->field[$id]->label(); } elseif (isset($fields_info) && isset($fields_info[$id]['label'])) { $label = $fields_info[$id]['label']; } else { $label = $field->label(); } $object->label = check_plain($label); $object->is_multiple = $field_is_multiple; $rendered_fields[$id] = $object; } } } return $rendered_fields; } /** * Strips illegal characters for an identifier from a JSON string. * * @param $input * Identifier string to process. * @return * Identifier string with illegal characters stripped away. */ function _views_json_check_label($input) { $output = str_replace(array( '{', '}', '[', ']', ':', ',', '"', "'", chr(47), chr(92) ), '', $input); $output = preg_replace( '/[\x{80}-\x{A0}' . // Non-printable ISO-8859-1 + NBSP '\x{01}-\x{1F}' . // Non-printable ASCII characters '\x{0}]/u', // NULL byte '', $output); return check_plain(strip_tags($output)); } /** * Gets JSON data from a View rendered in the JSON data document style. * * This is useful for when working with a JSON view in code. * * @param $name * The name of the view. * @param $display_id * The display of the view to use. * @param $args * The arguments to pass to the view. * @param $raw * If TRUE, the JSON data is returned as a string. Otherwise, an object * representation is returned. * @return * The JSON data in the form of an object or a string or NULL otherwise. */ function views_json_get($name, $display_id = 'default', $args = array(), $raw = FALSE) { $view = views_get_view($name); if (!is_object($view)) { return NULL; } $preview = $view->preview($display_id, $args); $start_pos = strpos($preview, '{'); $finish_pos = strrpos($preview, '}'); $length = $finish_pos - $start_pos + 1; $json = trim(substr($preview, $start_pos, $length)); if ($raw) { return $json; } return json_decode($json); } /** * Render a view's output as JSON. * * The function will directly output a JSON string instead of returning it. * * @param $items * The collection of items to encode into JSON. * @param $options * Render options. */ /** * Encodes JSON in a pretty-printed fashion. * * @deprecated The $option parameter in PHP 5.4.0 json_encode() deprecates this function. * * @see _views_json_json_encode */ function _views_json_encode_formatted($v, $options, $depth = 0) { $base_indent = '  '; $eol = '
'; $indent = str_repeat($base_indent, $depth); // This is based on the drupal_to_js() function. switch (gettype($v)) { case 'boolean': // Lowercase is necessary! return $v ? 'true' : 'false'; case 'integer': case 'double': return $v; case 'resource': case 'string': $search = array( '"', chr(92), chr(8), chr(12), chr(13) . chr(10), chr(10), chr(13), chr(9) ); $replace = array('\"', '\\', '\b', '\f', '\n', '\n', '\r', '\t'); $output = str_replace($search, $replace, $v); // Convert string to numeric if need. if (!empty($options['numeric_strings']) && is_numeric($output)) { return (strpos($output, '.') !== FALSE) ? floatval($output) : intval($output); } /* * $output = str_replace(array("\r", "\n", "<", ">", "&"), array('\r', '\n', '\x3c', '\x3e', '\x26'), addslashes($output)); /* */ return '"' . check_plain($output) . '"'; case 'array': // Arrays in JSON can't be associative. If the array is empty or if it // has sequential whole number keys starting with 0, it's not associative // so we can go ahead and convert it as an array. if (empty($v) || array_keys($v) === range(0, sizeof($v) - 1)) { $output = array(); foreach ($v as $val) { $output[] = $indent . $base_indent . _views_json_encode_formatted($val, $options, $depth + 1); } return '[' . (!empty($output) ? $eol . implode(',' . $eol, $output) . $eol . $indent : '') . ']'; } // Otherwise, fall through to convert the array as an object. case 'object': $output = array(); foreach ($v as $key => $val) { $output[] = $indent . $base_indent . _views_json_encode_formatted(strval($key), $options) . ' : ' . _views_json_encode_formatted($val, $options, $depth + 1); } return '{' . (!empty($output) ? $eol . implode(',' . $eol, $output) . $eol . $indent : '') . '}'; default: return 'null'; } } function _views_json_debug_stop($var, $location) { print("Location:$location\n"); var_dump($var); module_Invoke_all('exit'); exit; } /** * Backwards-compatible JSON encoder. * * Provides backwars-compatible support for more JSON encoding formats. * Uses PHP's native JSON encoding when PHP 5.3.0 or greater is detected. * Fallbacks to manual encoding/escaping when PHP 5.2.x and below is detected. * * @param array $rows * Results from template_preprocess_views_views_json_style_simple(). * @param int $bitmask * Integer to use as the $bitmask parameter for json_encode(). */ function _views_json_json_encode($rows, $bitmask = NULL) { if(defined('PHP_MAJOR_VERSION') && PHP_MAJOR_VERSION >= 5 && PHP_MINOR_VERSION >= 3) { $json = json_encode($rows, $bitmask); // Encoding features not supported before 5.4.x. if (PHP_MINOR_VERSION <= 4) { $json = str_replace(array('\/'), array('/'), $json); } } // For php 5.2 and below else { $json = json_encode($rows); // Fix for issue #1613344. $json = str_replace(array('\/'), array('/'), $json); } return $json; }