Newer
Older
Jonathan Chaffer
committed
* Allows administrators to define new content types.
define('CONTENT_DB_STORAGE_PER_FIELD', 0);
define('CONTENT_DB_STORAGE_PER_CONTENT_TYPE', 1);
/**
* Implementation of hook_help().
*/
function content_help($section) {
switch ($section) {
case 'admin/modules#description':
Jonathan Chaffer
committed
return t('<strong>CCK:</strong> Allows administrators to define new content types.');
Karen Stevenson
committed
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 ($section == 'node/add#'. $type_name) {
if ($section == 'node/add/'. $type_name) {
}
}
}
}
/**
* Implementation of hook_perm().
*/
function content_perm() {
$perms = array('administer content types');
$perms[] = 'create '. $name .' content';
$perms[] = 'edit own '. $name .' content';
Karen Stevenson
committed
$perms[] = 'edit '. $name .' content';
/**
* 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');
Jonathan Chaffer
committed
$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,
);
Jonathan Chaffer
committed
$items[] = array(
'path' => 'admin/node/types/fields',
'title' => t('fields'),
'callback' => '_content_admin_type_fields',
'access' => $access,
'type' => MENU_LOCAL_TASK,
);
$items[] = array(
'path' => 'node/add/'. $type_name,
'access' => user_access('create '. $type_name .' content'),
);
}
}
else {
if (arg(0) == 'admin' && arg(1) == 'node' && arg(2) == 'types' && arg(3)) {
Jonathan Chaffer
committed
$items[] = array(
'path' => 'admin/node/types/'. arg(3),
'callback' => '_content_admin_type_edit',
'access' => $access,
Jonathan Chaffer
committed
'callback arguments' => array(arg(3)),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'admin/node/types/'. arg(3) .'/delete',
Jonathan Chaffer
committed
'title' => t('delete'),
'callback' => '_content_admin_type_delete',
'access' => $access,
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'admin/node/types/'. arg(3) .'/duplicate',
Jonathan Chaffer
committed
'title' => t('duplicate'),
'callback' => '_content_admin_type_edit',
'access' => $access,
Jonathan Chaffer
committed
'callback arguments' => array('', arg(3)),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'admin/node/types/'. arg(3) .'/edit',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items[] = array(
'path' => 'admin/node/types/'. arg(3) .'/fields',
'callback' => '_content_admin_field_overview',
'access' => $access,
Jonathan Chaffer
committed
'callback arguments' => array(arg(3)),
'type' => MENU_LOCAL_TASK,
Karen Stevenson
committed
'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',
Jonathan Chaffer
committed
'title' => t('add field'),
'callback' => '_content_admin_field_add',
'access' => $access,
Jonathan Chaffer
committed
'type' => MENU_LOCAL_TASK,
Karen Stevenson
committed
'weight' => 3,
$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,
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'admin/node/types/'. arg(3) .'/fields/'. arg(5) .'/remove',
'callback' => '_content_admin_field_remove',
'access' => $access,
'type' => MENU_CALLBACK,
);
}
}
}
}
return $items;
}
/**
Jonathan Chaffer
committed
* Implementation of hook_node_info().
Jonathan Chaffer
committed
function content_node_info() {
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') {
Karen Stevenson
committed
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.
$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;
}
}
if ($additions) {
foreach ($additions as $key => $value) {
$default_additions[$key] = $value;
}
}
cache_set($cid, serialize($default_additions), CACHE_PERMANENT);
return $default_additions;
*
* Each field defines its own component of the content entry form, via its
* chosen widget.
Jonathan Chaffer
committed
$form = array();
Jonathan Chaffer
committed
// Set form parameters so we can accept file uploads.
$form['#attributes'] = array("enctype" => "multipart/form-data");
$form['title'] = array(
'#type' => 'textfield',
'#required' => TRUE,
'#default_value' => $node->title,
);
_content_widget_invoke('prepare form values', $node);
$form = array_merge($form, _content_widget_invoke('form', $node));
Jonathan Chaffer
committed
return $form;
*
* Both widgets and fields have a chance to raise error flags when a node is
* being validated.
_content_widget_invoke('validate', $node);
_content_widget_invoke('process form values', $node);
Jonathan Chaffer
committed
_content_field_invoke('validate', $node);
Jonathan Chaffer
committed
/**
* 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.
Jonathan Chaffer
committed
*/
function content_submit(&$node) {
_content_widget_invoke('submit', $node);
_content_widget_invoke('process form values', $node);
_content_field_invoke('submit', $node);
Jonathan Chaffer
committed
}
Jonathan Chaffer
committed
/**
* Implementation of hook_insert().
*/
function content_insert(&$node) {
_content_field_invoke('insert', $node);
Jonathan Chaffer
committed
}
/**
* Implementation of hook_update().
*/
function content_update(&$node) {
_content_field_invoke('update', $node);
cache_clear_all('content:'. $node->nid .':'. $node->vid);
Jonathan Chaffer
committed
}
/**
* Implementation of hook_delete().
*/
function content_delete(&$node) {
_content_field_invoke('delete', $node);
db_query('DELETE FROM {node_'. $node->type .'} WHERE nid = %d', $node->nid);
cache_clear_all('content:'. $node->nid, TRUE);
Jonathan Chaffer
committed
}
/**
* Implementation of hook_view().
*/
function content_view(&$node, $teaser = FALSE, $page = FALSE) {
Jonathan Chaffer
committed
if ($node->in_preview) {
_content_widget_invoke('process form values', $node);
}
Karen Stevenson
committed
$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;
}
}
Jonathan Chaffer
committed
/**
* 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) {
Jonathan Chaffer
committed
$db_info = content_database_info($field);
Jonathan Chaffer
committed
switch ($op) {
case 'load':
$column_names = array();
Jonathan Chaffer
committed
foreach ($db_info['columns'] as $column => $attributes) {
Jonathan Chaffer
committed
$column_names[] = $attributes['column'] .' AS '. $column;
Jonathan Chaffer
committed
}
if ($field['multiple']) {
Jonathan Chaffer
committed
$result = db_query('SELECT '. implode(', ', $column_names) .' FROM {'. $db_info['table'] .'} WHERE vid = %d ORDER BY delta', $node->vid);
Jonathan Chaffer
committed
$values = array();
while ($value = db_fetch_array($result)) {
$values[] = $value;
}
$additions = array($field['field_name'] => $values);
}
else {
Jonathan Chaffer
committed
$result = db_query('SELECT '. implode(', ', $column_names) .' FROM {'. $db_info['table'] .'} WHERE vid = %d', $node->vid);
Jonathan Chaffer
committed
$additions = array($field['field_name'] => array(db_fetch_array($result)));
Jonathan Chaffer
committed
}
return $additions;
case 'insert':
Jonathan Chaffer
committed
foreach ($node_field as $delta => $item) {
Jonathan Chaffer
committed
$data = array();
Jonathan Chaffer
committed
$column_names = array();
$column_placeholders = array();
Jonathan Chaffer
committed
$column_assignments = array();
Jonathan Chaffer
committed
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'";
Jonathan Chaffer
committed
}
Jonathan Chaffer
committed
$data[] = $item[$column];
}
Jonathan Chaffer
committed
$data[] = $node->vid;
$data[] = $node->nid;
if ($field['multiple']) {
$data[] = $delta;
}
Jonathan Chaffer
committed
if ($field['multiple']) {
Jonathan Chaffer
committed
db_query('INSERT INTO {'. $db_info['table'] .'} ('. implode(', ', $column_names) .', vid, nid, delta) VALUES ('. implode(', ', $column_placeholders) .', %d, %d, %d)', $data);
Jonathan Chaffer
committed
}
else {
Jonathan Chaffer
committed
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);
}
Jonathan Chaffer
committed
}
}
return;
case 'update':
Jonathan Chaffer
committed
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);
}
Jonathan Chaffer
committed
Jonathan Chaffer
committed
foreach ($node_field as $delta => $item) {
Jonathan Chaffer
committed
$data = array();
Jonathan Chaffer
committed
$column_names = array();
$column_placeholders = array();
Jonathan Chaffer
committed
$column_assignments = array();
Jonathan Chaffer
committed
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 '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'";
Jonathan Chaffer
committed
}
Jonathan Chaffer
committed
$data[] = $item[$column];
}
Jonathan Chaffer
committed
$data[] = $node->vid;
$data[] = $node->nid;
if ($field['multiple']) {
$data[] = $delta;
}
Jonathan Chaffer
committed
if ($field['multiple']) {
Jonathan Chaffer
committed
db_query('INSERT INTO {'. $db_info['table'] .'} ('. implode(', ', $column_names) .', vid, nid, delta) VALUES ('. implode(', ', $column_placeholders) .', %d, %d, %d)', $data);
Jonathan Chaffer
committed
}
else {
Jonathan Chaffer
committed
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);
}
Jonathan Chaffer
committed
}
}
return;
case 'delete':
// Delete using nid rather than vid to purge all revisions.
Jonathan Chaffer
committed
db_query('DELETE FROM {'. $db_info['table'] .'} WHERE nid = %d', $node->nid);
Jonathan Chaffer
committed
return;
case 'delete revision':
db_query('DELETE FROM {'. $db_info['table'] .'} WHERE vid = %d', $node->vid);
return;
Jonathan Chaffer
committed
}
}
Jonathan Chaffer
committed
Jonathan Chaffer
committed
* Invoke a field hook.
Jonathan Chaffer
committed
*
* 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);
$field_types = _content_field_types();
$return = array();
$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);
Jonathan Chaffer
committed
if (is_array($result)) {
$return = array_merge($return, $result);
}
else if (isset($result)) {
$return[] = $result;
}
}
Karen Stevenson
committed
// 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();
Jonathan Chaffer
committed
$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;
}
Jonathan Chaffer
committed
}
if (isset($node->$field['field_name'])) {
$node->$field['field_name'] = $node_field;
}
Karen Stevenson
committed
/**
* Format field output based on display settings.
*/
function _content_field_view(&$node, $teaser = NULL, $page = NULL) {
Karen Stevenson
committed
$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);
}
Karen Stevenson
committed
}
if (empty($value)) {
foreach ($node_field as $delta => $item) {
$node_field[$delta]['view'] = content_format($field, $item, $formatter, $node);
Karen Stevenson
committed
}
$value = theme('field', $node, $field, $node_field, $teaser, $page);
Karen Stevenson
committed
}
}
$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;
}
Karen Stevenson
committed
}
}
return $return;
}
/**
*/
function _content_widget_invoke($op, &$node) {
$type_name = is_string($node) ? $node : (is_array($node) ? $node['type'] : $node->type);
$widget_types = _content_widget_types();
$return = array();
$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;
}
}
Karen Stevenson
committed
// 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;
}
* @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];
* @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;
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) {
Jonathan Chaffer
committed
$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;
Jonathan Chaffer
committed
$info['field types'][$name]['formatters'] = array();
Jonathan Chaffer
committed
$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;
}
}
}
Jonathan Chaffer
committed
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;
}
Jonathan Chaffer
committed
$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();
Karen Stevenson
committed
$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'];
Karen Stevenson
committed
$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);
}
}
}
/**
* Clear the cache of content_types; called in several places when content
* information is changed.
*/
function content_clear_type_cache() {
Jonathan Chaffer
committed
Jonathan Chaffer
committed
if (module_exist('views')) {
views_invalidate_cache();
}
}
Jonathan Chaffer
committed
/**
* 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);
Jonathan Chaffer
committed
$db_info = array();
if ($field['db_storage'] == CONTENT_DB_STORAGE_PER_FIELD) {
$db_info['table'] = 'node_data_'. $field['field_name'];
}
else {
Jonathan Chaffer
committed
$db_info['table'] = 'node_'. $field['type_name'];
Jonathan Chaffer
committed
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;
Jonathan Chaffer
committed
}
}
else {
$db_info['columns'] = array();
}
Jonathan Chaffer
committed
return $db_info;
}
Jonathan Chaffer
committed
/**
* Manipulate a 2D array to reverse rows and columns.
*
Jonathan Chaffer
committed
* 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.
Jonathan Chaffer
committed
*
* @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;
}
Jonathan Chaffer
committed
}
}
}
return $result;
}
Jonathan Chaffer
committed
/**
* 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])) {
Jonathan Chaffer
committed
$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) {
Yves Chedemois
committed
$label = isset($field['display_settings']['label']['format']) ? $field['display_settings']['label']['format'] : 'above';
$items_output = '';
Karen Stevenson
committed
foreach ($items as $delta => $item) {
Yves Chedemois
committed
if (!empty($item['view']) || $item['view'] === "0") {
Karen Stevenson
committed
$items_output .= '<div class="field-item">';
if ($label == 'inline') {
$items_output .= '<div class="field-label-inline'. ($delta ? '' : '-first') .'">';
$items_output .= $field['widget']['label'] .':</div> ' ;
}
$items_output .= $item['view'] .'</div>';
}
Karen Stevenson
committed
Yves Chedemois
committed
$output = '';
if (!empty($items_output)) {
Yves Chedemois
committed
$output .= '<div class="field field-type-'. strtr($field['type'], '_', '-') .' field-'. strtr($field['field_name'], '_', '-') .'">';
Karen Stevenson
committed
if ($label == 'above') {
$output .= '<div class="field-label">'. $field['widget']['label'] .':</div>';