CCK: Allows administrators to define new content types.'); } if (preg_match('!^admin/node/types/.*/display$!', $section)) { return t("Configure how this content type's fields and field labels should be displayed when it's viewed in teaser and full-page mode."); } if (strpos($section, 'node/add') === 0) { $types = content_types(); foreach ($types as $type_name => $type) { if ($section == 'node/add#'. $type_name) { return t($types[$type_name]['description']); } if ($section == 'node/add/'. $type_name) { return t($types[$type_name]['help']); } } } } /** * Implementation of hook_perm(). */ function content_perm() { $perms = array('administer content types'); foreach (content_types() as $name => $type) { $perms[] = 'create '. $name .' content'; $perms[] = 'edit own '. $name .' content'; $perms[] = 'edit '. $name .' content'; } return $perms; } /** * Implementation of hook_init(). */ function content_init() { // ensure we are not serving a cached page if (function_exists('drupal_set_content')) { // we don't do this in hook_menu to ensure the files are already included when // views_menu is executed if (module_exist('views')) { include_once('./'. drupal_get_path('module', 'content') .'/content_views.inc'); } // according to http://drupal.org/node/60526, this should not go in hook_menu if (module_exist('pathauto')) { include_once('./'. drupal_get_path('module', 'content') .'/content_pathauto.inc'); } } } /** * Implementation of hook_menu(). */ function content_menu($may_cache) { if (!$may_cache) { // Only include administrative callbacks if we are viewing an admin page. if (arg(0) == 'admin') { include_once('./'. drupal_get_path('module', 'content') .'/content_admin.inc'); } theme_add_style(drupal_get_path('module', 'content') .'/content.css'); } $items = array(); $access = user_access('administer content types'); if ($may_cache) { $items[] = array( 'path' => 'admin/node/types', 'title' => t('content types'), 'callback' => '_content_admin_type_overview', 'access' => $access, ); $items[] = array( 'path' => 'admin/node/types/list', 'title' => t('list'), 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10, ); $items[] = array( 'path' => 'admin/node/types/add', 'title' => t('add content type'), 'callback' => '_content_admin_type_edit', 'access' => $access, 'type' => MENU_LOCAL_TASK, ); $items[] = array( 'path' => 'admin/node/types/fields', 'title' => t('fields'), 'callback' => '_content_admin_type_fields', 'access' => $access, 'type' => MENU_LOCAL_TASK, ); $types = content_types(); foreach ($types as $type_name => $type) { $items[] = array( 'path' => 'node/add/'. $type_name, 'title' => t($type['label']), 'access' => user_access('create '. $type_name .' content'), ); } } else { if (arg(0) == 'admin' && arg(1) == 'node' && arg(2) == 'types' && arg(3)) { $type = content_types(arg(3)); if ($type) { $items[] = array( 'path' => 'admin/node/types/'. arg(3), 'title' => t($type['label']), 'callback' => '_content_admin_type_edit', 'access' => $access, 'callback arguments' => array(arg(3)), 'type' => MENU_CALLBACK, ); $items[] = array( 'path' => 'admin/node/types/'. arg(3) .'/delete', 'title' => t('delete'), 'callback' => '_content_admin_type_delete', 'access' => $access, 'callback arguments' => array(arg(3)), 'type' => MENU_CALLBACK, ); $items[] = array( 'path' => 'admin/node/types/'. arg(3) .'/duplicate', 'title' => t('duplicate'), 'callback' => '_content_admin_type_edit', 'access' => $access, 'callback arguments' => array('', arg(3)), 'type' => MENU_CALLBACK, ); $items[] = array( 'path' => 'admin/node/types/'. arg(3) .'/edit', 'title' => t('edit'), 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10, ); $items[] = array( 'path' => 'admin/node/types/'. arg(3) .'/fields', 'title' => t('manage fields'), 'callback' => '_content_admin_field_overview', 'access' => $access, 'callback arguments' => array(arg(3)), 'type' => MENU_LOCAL_TASK, 'weight' => 0, ); $items[] = array( 'path' => 'admin/node/types/'. arg(3) .'/display', 'title' => t('display fields'), 'callback' => 'content_admin_display_overview_form', 'access' => $access, 'callback arguments' => array(arg(3)), 'type' => MENU_LOCAL_TASK, 'weight' => 1, ); $items[] = array( 'path' => 'admin/node/types/'. arg(3) .'/add_field', 'title' => t('add field'), 'callback' => '_content_admin_field_add', 'access' => $access, 'callback arguments' => array(arg(3)), 'type' => MENU_LOCAL_TASK, 'weight' => 3, ); if (arg(4) == 'fields' && arg(5) && isset($type['fields'][arg(5)])) { $items[] = array( 'path' => 'admin/node/types/'. arg(3) .'/fields/'. arg(5), 'title' => t($type['fields'][arg(5)]['widget']['label']), 'callback' => '_content_admin_field', 'access' => $access, 'callback arguments' => array(arg(3), arg(5)), 'type' => MENU_CALLBACK, ); $items[] = array( 'path' => 'admin/node/types/'. arg(3) .'/fields/'. arg(5) .'/remove', 'title' => t('remove field'), 'callback' => '_content_admin_field_remove', 'access' => $access, 'callback arguments' => array(arg(3), arg(5)), 'type' => MENU_CALLBACK, ); } } } } return $items; } /** * Implementation of hook_node_info(). */ function content_node_info() { $types = array(); foreach (content_types() as $name => $type) { $types[$name] = array('name' => t($type['label']), 'base' => 'content'); } return $types; } /** * Implementation of hook_access(). */ function content_access($op, $node) { global $user; $type = is_string($node) ? $node : (is_array($node) ? $node['type'] : $node->type); if ($op == 'create') { return user_access('create '. $type .' content'); } if ($op == 'update' || $op == 'delete') { if ((user_access('edit own '. $type .' content') && $user->uid == $node->uid) || user_access('edit '. $type .' content')) { return TRUE; } } } /** * Implementation of hook_load(). * * When loading one of the content.module nodes, we need to let each field handle * its own loading. This can make for a number of queries in some cases, so we * cache the loaded object structure and invalidate it during the update process. */ function content_load($node) { $cid = 'content:'. $node->nid .':'. $node->vid; if ($cached = cache_get($cid)) { return unserialize($cached->data); } else { $default_additions = _content_field_invoke_default('load', $node); if ($default_additions) { foreach ($default_additions as $key => $value) { $node->$key = $value; } } $additions = _content_field_invoke('load', $node); if ($additions) { foreach ($additions as $key => $value) { $default_additions[$key] = $value; } } cache_set($cid, serialize($default_additions), CACHE_PERMANENT); return $default_additions; } } /** * Implementation of hook_form(). * * Each field defines its own component of the content entry form, via its * chosen widget. */ function content_form(&$node, &$param) { $form = array(); $type = content_types($node->type); // Set form parameters so we can accept file uploads. $form['#attributes'] = array("enctype" => "multipart/form-data"); $form['title'] = array( '#type' => 'textfield', '#title' => t($type['title_label']), '#required' => TRUE, '#default_value' => $node->title, ); _content_widget_invoke('prepare form values', $node); $form = array_merge($form, _content_widget_invoke('form', $node)); return $form; } /** * Implementation of hook_validate(). * * Both widgets and fields have a chance to raise error flags when a node is * being validated. */ function content_validate(&$node) { _content_widget_invoke('validate', $node); _content_widget_invoke('process form values', $node); _content_field_invoke('validate', $node); _content_field_invoke_default('validate', $node); } /** * Implementation of hook_submit(). * * At submit time, the widget does whatever data massaging is necessary so that * the field has the content in the expected format and can commit the changes * to the database. */ function content_submit(&$node) { _content_widget_invoke('submit', $node); _content_widget_invoke('process form values', $node); _content_field_invoke('submit', $node); _content_field_invoke_default('submit', $node); } /** * Implementation of hook_insert(). */ function content_insert(&$node) { _content_field_invoke('insert', $node); _content_field_invoke_default('insert', $node); } /** * Implementation of hook_update(). */ function content_update(&$node) { _content_field_invoke('update', $node); _content_field_invoke_default('update', $node); cache_clear_all('content:'. $node->nid .':'. $node->vid); } /** * Implementation of hook_delete(). */ function content_delete(&$node) { _content_field_invoke('delete', $node); _content_field_invoke_default('delete', $node); db_query('DELETE FROM {node_'. $node->type .'} WHERE nid = %d', $node->nid); cache_clear_all('content:'. $node->nid, TRUE); } /** * Implementation of hook_view(). */ function content_view(&$node, $teaser = FALSE, $page = FALSE) { if ($node->in_preview) { _content_widget_invoke('process form values', $node); } $node->body = implode('', _content_field_view($node, FALSE, $page)); $node->teaser = implode('', _content_field_view($node, TRUE, $page)); $node->readmore = (strlen($node->teaser) < strlen($node->body)); } /** * Implementation of hook_nodeapi(). * * When a revision is deleted, make sure the appropriate cache item is cleared. */ function content_nodeapi(&$node, $op, $teaser, $page) { switch ($op) { case 'delete revision': if (content_types($node->type)) { _content_field_invoke('delete revision', $node); _content_field_invoke_default('delete revision', $node); cache_clear_all('content:'. $node->nid .':'. $node->vid); db_query('DELETE FROM {node_'. $node->type .'} WHERE vid = %d', $node->vid); } break; } } /** * Implementation of hook_field(). Handles common field housekeeping. * * This implementation is special, as content.module does not define any field * types. Instead, this function gets called after the type-specific hook, and * takes care of the database interface for field types that do not choose to * do their own storage. */ function content_field($op, &$node, $field, &$node_field, $teaser, $page) { $db_info = content_database_info($field); switch ($op) { case 'load': $column_names = array(); foreach ($db_info['columns'] as $column => $attributes) { $column_names[] = $attributes['column'] .' AS '. $column; } if ($field['multiple']) { $result = db_query('SELECT '. implode(', ', $column_names) .' FROM {'. $db_info['table'] .'} WHERE vid = %d ORDER BY delta', $node->vid); $values = array(); while ($value = db_fetch_array($result)) { $values[] = $value; } $additions = array($field['field_name'] => $values); } else { $result = db_query('SELECT '. implode(', ', $column_names) .' FROM {'. $db_info['table'] .'} WHERE vid = %d', $node->vid); $additions = array($field['field_name'] => array(db_fetch_array($result))); } return $additions; case 'insert': foreach ($node_field as $delta => $item) { $data = array(); $column_names = array(); $column_placeholders = array(); $column_assignments = array(); foreach ($db_info['columns'] as $column => $attributes) { $column_names[] = $attributes['column']; if ($item[$column] == '' && !$attributes['not null'] && !$field['required']) { $column_placeholders[] = '%s'; $column_assignments[] = $attributes['column'] .' = %s'; $item[$column] = 'NULL'; } else { switch ($attributes['type']) { case 'int': case 'mediumint': case 'tinyint': case 'bigint': $column_placeholders[] = '%d'; $column_assignments[] = $attributes['column'] .' = %d'; break; case 'float': $column_placeholders[] = '%f'; $column_assignments[] = $attributes['column'] .' = %f'; break; default: $column_placeholders[] = "'%s'"; $column_assignments[] = $attributes['column'] ." = '%s'"; } } $data[] = $item[$column]; } $data[] = $node->vid; $data[] = $node->nid; if ($field['multiple']) { $data[] = $delta; } if ($field['multiple']) { db_query('INSERT INTO {'. $db_info['table'] .'} ('. implode(', ', $column_names) .', vid, nid, delta) VALUES ('. implode(', ', $column_placeholders) .', %d, %d, %d)', $data); } else { if (db_result(db_query('SELECT COUNT(*) FROM {'. $db_info['table'] .'} WHERE vid = %d AND nid = %d', $node->vid, $node->nid))) { db_query('UPDATE {'. $db_info['table'] .'} SET '. implode(', ', $column_assignments) .' WHERE vid = %d AND nid = %d', $data); } else { db_query('INSERT INTO {'. $db_info['table'] .'} ('. implode(', ', $column_names) .', vid, nid) VALUES ('. implode(', ', $column_placeholders) .', %d, %d)', $data); } } } return; case 'update': if ($field['multiple']) { // Delete and insert, rather than update, in case a field was added. db_query('DELETE FROM {'. $db_info['table'] .'} WHERE vid = %d', $node->vid); } foreach ($node_field as $delta => $item) { $data = array(); $column_names = array(); $column_placeholders = array(); $column_assignments = array(); foreach ($db_info['columns'] as $column => $attributes) { $column_names[] = $attributes['column']; if ($item[$column] == '' && !$attributes['not null'] && !$field['required']) { $column_placeholders[] = '%s'; $column_assignments[] = $attributes['column'] .' = %s'; $item[$column] = 'NULL'; } else { switch ($attributes['type']) { case 'int': case 'mediumint': case 'tinyint': case 'bigint': $column_placeholders[] = '%d'; $column_assignments[] = $attributes['column'] .' = %d'; break; case 'float': $column_placeholders[] = '%f'; $column_assignments[] = $attributes['column'] .' = %f'; break; default: $column_placeholders[] = "'%s'"; $column_assignments[] = $attributes['column'] ." = '%s'"; } } $data[] = $item[$column]; } $data[] = $node->vid; $data[] = $node->nid; if ($field['multiple']) { $data[] = $delta; } if ($field['multiple']) { db_query('INSERT INTO {'. $db_info['table'] .'} ('. implode(', ', $column_names) .', vid, nid, delta) VALUES ('. implode(', ', $column_placeholders) .', %d, %d, %d)', $data); } else { if (db_result(db_query('SELECT COUNT(*) FROM {'. $db_info['table'] .'} WHERE vid = %d AND nid = %d', $node->vid, $node->nid))) { db_query('UPDATE {'. $db_info['table'] .'} SET '. implode(', ', $column_assignments) .' WHERE vid = %d AND nid = %d', $data); } else { db_query('INSERT INTO {'. $db_info['table'] .'} ('. implode(', ', $column_names) .', vid, nid) VALUES ('. implode(', ', $column_placeholders) .', %d, %d)', $data); } } } return; case 'delete': // Delete using nid rather than vid to purge all revisions. db_query('DELETE FROM {'. $db_info['table'] .'} WHERE nid = %d', $node->nid); return; case 'delete revision': db_query('DELETE FROM {'. $db_info['table'] .'} WHERE vid = %d', $node->vid); return; } } /** * Invoke a field hook. * * For each operation, both this function and _content_field_invoke_default() are * called so that the default database handling can occur. */ function _content_field_invoke($op, &$node, $teaser = NULL, $page = NULL) { $type_name = is_string($node) ? $node : (is_array($node) ? $node['type'] : $node->type); $type = content_types($type_name); $field_types = _content_field_types(); $return = array(); foreach ($type['fields'] as $field) { $node_field = isset($node->$field['field_name']) ? $node->$field['field_name'] : array(); $module = $field_types[$field['type']]['module']; $function = $module .'_field'; if (function_exists($function)) { $result = $function($op, $node, $field, $node_field, $teaser, $page); if (is_array($result)) { $return = array_merge($return, $result); } else if (isset($result)) { $return[] = $result; } } // test for values in $node_field in case modules added items on insert if (isset($node->$field['field_name']) || count($node_field)) { $node->$field['field_name'] = $node_field; } } return $return; } /** * Invoke content.module's version of a field hook. */ function _content_field_invoke_default($op, &$node, $teaser = NULL, $page = NULL) { $type_name = is_string($node) ? $node : (is_array($node) ? $node['type'] : $node->type); $type = content_types($type_name); $field_types = _content_field_types(); $return = array(); foreach ($type['fields'] as $field) { $node_field = isset($node->$field['field_name']) ? $node->$field['field_name'] : array(); $db_info = content_database_info($field); if (count($db_info['columns'])) { $result = content_field($op, $node, $field, $node_field, $teaser, $page); if (is_array($result)) { $return = array_merge($return, $result); } else if (isset($result)) { $return[] = $result; } } if (isset($node->$field['field_name'])) { $node->$field['field_name'] = $node_field; } } return $return; } /** * Format field output based on display settings. */ function _content_field_view(&$node, $teaser = NULL, $page = NULL) { $type_name = is_string($node) ? $node : (is_array($node) ? $node['type'] : $node->type); $type = content_types($type_name); $field_types = _content_field_types(); $context = $teaser ? 'teaser' : 'full'; $return = array(); if (count($type['fields'])) { foreach ($type['fields'] as $field) { $node_field = isset($node->$field['field_name']) ? $node->$field['field_name'] : array(); $formatter = isset($field['display_settings'][$context]['format']) ? $field['display_settings'][$context]['format'] : 'default'; $value = ''; if ($formatter != 'hidden') { $module = $field_types[$field['type']]['module']; $callbacks = module_invoke($module, 'field_settings', 'callbacks', $field); if (isset($callbacks['view']) && $callbacks['view']) { $function = $module .'_field'; if (function_exists($function)) { $value = $function('view', $node, $field, $node_field, $teaser, $page); } } if (empty($value)) { foreach ($node_field as $delta => $item) { $node_field[$delta]['view'] = content_format($field, $item, $formatter, $node); } $value = theme('field', $node, $field, $node_field, $teaser, $page); } } $return[$field['field_name']] = $value; // test for values in $node_field in case modules added items if (isset($node->$field['field_name']) || count($node_field)) { $node->$field['field_name'] = $node_field; } } } return $return; } /** * Invoke a widget hook. */ function _content_widget_invoke($op, &$node) { $type_name = is_string($node) ? $node : (is_array($node) ? $node['type'] : $node->type); $type = content_types($type_name); $widget_types = _content_widget_types(); $return = array(); foreach ($type['fields'] as $field) { $node_field = isset($node->$field['field_name']) ? $node->$field['field_name'] : array(); $module = $widget_types[$field['widget']['type']]['module']; $function = $module .'_widget'; if (function_exists($function)) { $result = $function($op, $node, $field, $node_field); if (is_array($result) && $op == 'form') { $result[$field['field_name']]['#weight'] = $field['widget']['weight']; } if (is_array($result)) { $return = array_merge($return, $result); } else if (isset($result)) { $return[] = $result; } } // test for values in $node_field in case modules added items on insert if (is_object($node) && (isset($node->$field['field_name']) || count($node_field))) { $node->$field['field_name'] = $node_field; } } return $return; } /** * Return a list of all content types. * * @param $content_type_name * If set, return information on just this type. */ function content_types($content_type_name = NULL) { $info = _content_type_info(); if (isset($content_type_name)) { if (isset($info['content types'][$content_type_name])) { return $info['content types'][$content_type_name]; } else { return NULL; } } return $info['content types']; } /** * Return a list of all fields. * * @param $field_name * If set, return information on just this field. * @param $content_type_name * If set, return information of the field within the context of this content * type. */ function content_fields($field_name = NULL, $content_type_name = NULL) { $info = _content_type_info(); if (isset($field_name)) { if (isset($info['fields'][$field_name])) { if (isset($content_type_name)) { if (isset($info['content types'][$content_type_name]['fields'][$field_name])) { return $info['content types'][$content_type_name]['fields'][$field_name]; } else { return NULL; } } else { return $info['fields'][$field_name]; } } else { return NULL; } } return $info['fields']; } /** * Return a list of field types. */ function _content_field_types() { $info = _content_type_info(); return $info['field types']; } /** * Return a list of widget types. */ function _content_widget_types() { $info = _content_type_info(); return $info['widget types']; } /** * Collate all information on content types, fields, and related structures. * * @param $reset * If TRUE, clear the cache and fetch the information from the database again. */ function _content_type_info($reset = FALSE) { static $info; if ($reset || !isset($info)) { if ($cached = cache_get('content_type_info')) { $info = unserialize($cached->data); } else { $info = array( 'field types' => array(), 'widget types' => array(), 'fields' => array(), 'content types' => array(), ); foreach (module_list() as $module) { $module_field_types = module_invoke($module, 'field_info'); if ($module_field_types) { foreach ($module_field_types as $name => $field_info) { $info['field types'][$name] = $field_info; $info['field types'][$name]['module'] = $module; $info['field types'][$name]['formatters'] = array(); } } $module_widgets = module_invoke($module, 'widget_info'); if ($module_widgets) { foreach ($module_widgets as $name => $widget_info) { $info['widget types'][$name] = $widget_info; $info['widget types'][$name]['module'] = $module; } } } foreach (module_list() as $module) { $module_formatters = module_invoke($module, 'field_formatter_info'); if ($module_formatters) { foreach ($module_formatters as $name => $formatter_info) { foreach ($formatter_info['field types'] as $field_type) { $info['field types'][$field_type]['formatters'][$name] = $formatter_info; $info['field types'][$field_type]['formatters'][$name]['module'] = $module; } } } } $field_result = db_query('SELECT * FROM {node_field} nf'); while ($field = db_fetch_array($field_result)) { $global_settings = $field['global_settings'] ? unserialize($field['global_settings']) : array(); unset($field['global_settings']); // Preventative error handling for PHP5 if field nodule hasn't created an arrray. if (is_array($global_settings)) { $field = array_merge($field, $global_settings); } $instance_info = db_fetch_array(db_query("SELECT type_name, label FROM {node_field_instance} WHERE field_name = '%s'", $field['field_name'])); $field['widget']['label'] = $instance_info['label']; $field['type_name'] = $instance_info['type_name']; $info['fields'][$field['field_name']] = $field; } $type_result = db_query('SELECT * FROM {node_type_content} nt ORDER BY nt.type_name ASC'); while ($type = db_fetch_array($type_result)) { $type['fields'] = array(); $field_result = db_query("SELECT nfi.field_name, nfi.weight, nfi.label, nfi.widget_type, nfi.widget_settings, nfi.display_settings, nfi.description FROM {node_field_instance} nfi WHERE nfi.type_name = '%s' ORDER BY nfi.weight ASC, nfi.label ASC", $type['type_name']); while ($field = db_fetch_array($field_result)) { // Overwrite global field information with specific information $field = array_merge($info['fields'][$field['field_name']], $field); $widget_settings = $field['widget_settings'] ? unserialize($field['widget_settings']) : array(); unset($field['widget_settings']); $field['widget'] = $widget_settings; $field['widget']['type'] = $field['widget_type']; unset($field['widget_type']); $field['widget']['weight'] = $field['weight']; unset($field['weight']); $field['widget']['label'] = $field['label']; unset($field['label']); $field['widget']['description'] = $field['description']; unset($field['description']); $field['type_name'] = $type['type_name']; $field['display_settings'] = $field['display_settings'] ? unserialize($field['display_settings']) : array(); $type['fields'][$field['field_name']] = $field; } $info['content types'][$type['type_name']] = $type; } cache_set('content_type_info', serialize($info), CACHE_PERMANENT); } } return $info; } /** * Clear the cache of content_types; called in several places when content * information is changed. */ function content_clear_type_cache() { cache_clear_all('content_type_info'); _content_type_info(TRUE); if (module_exist('views')) { views_invalidate_cache(); } } /** * Retrieve the database storage location(s) for a field. * * @param $field * The field whose database information is requested. * @return * An array with the keys: * "table": The name of the database table where the field data is stored. * "columns": An array of columns stored for this field. Each is a collection * of information returned from hook_field_settings('database columns'), * with the addition of a "column" attribute which holds the name of the * database column that stores the data. */ function content_database_info($field) { $field_types = _content_field_types(); $module = $field_types[$field['type']]['module']; $columns = module_invoke($module, 'field_settings', 'database columns', $field); $db_info = array(); if ($field['db_storage'] == CONTENT_DB_STORAGE_PER_FIELD) { $db_info['table'] = 'node_data_'. $field['field_name']; } else { $db_info['table'] = 'node_'. $field['type_name']; } if (is_array($columns) && count($columns)) { $db_info['columns'] = $columns; foreach ($columns as $column_name => $attributes) { $db_info['columns'][$column_name]['column'] = $field['field_name'] .'_'. $column_name; } } else { $db_info['columns'] = array(); } return $db_info; } /** * Manipulate a 2D array to reverse rows and columns. * * The default data storage for fields is delta first, column names second. * This is sometimes inconvenient for field modules, so this function can be * used to present the data in an alternate format. * * @param $array * The array to be transposed. It must be at least two-dimensional, and * the subarrays must all have the same keys or behavior is undefined. * * @return * The transposed array. */ function content_transpose_array_rows_cols($array) { $result = array(); if (is_array($array)) { foreach ($array as $key1 => $value1) { if (is_array($value1)) { foreach ($value1 as $key2 => $value2) { if (!isset($result[$key2])) { $result[$key2] = array(); } $result[$key2][$key1] = $value2; } } } } return $result; } /** * Format a field item for display. * * @param $field * Either a field array or the name of the field. * @param $item * The field item to be formatted (such as $node->field_foo[0]). * @param $formatter * The name of the formatter to use. * @param $node * Optionally, the containing node object for context purposes. * * @return * A string containing the contents of the field item sanitized for display. * It will have been passed through the necessary check_plain() or check_markup() * functions as necessary. */ function content_format($field, $item, $formatter = 'default', $node = NULL) { if (!is_array($field)) { $field = content_fields($field); } $field_types = _content_field_types(); $formatters = $field_types[$field['type']]['formatters']; if (!isset($formatters[$formatter])) { $formatter = 'default'; } return module_invoke($formatters[$formatter]['module'], 'field_formatter', $field, $item, $formatter, $node); } /** * Format an individual field for display. * * @param $node * The node being displayed (provided for context). * @param $field * The field that is to be displayed (for information about the label, field * type, and so forth). * @param $items * The actual items to theme. This will be a linear array, each element of * which has a "view" property which contains the filtered, formatted contents * of the item. * @param $teaser * Whether the node is being displayed as a teaser or full version. * @param $page * Whether the node is being displayed as a full web page. * * @return * An HTML string containing the fully themed field. */ function theme_field(&$node, &$field, &$items, $teaser, $page) { $label = isset($field['display_settings']['label']['format']) ? $field['display_settings']['label']['format'] : 'above'; $items_output = ''; foreach ($items as $delta => $item) { if (!empty($item['view']) || $item['view'] === "0") { $items_output .= '