Skip to content

Instantly share code, notes, and snippets.

@Mizpah
Created November 27, 2014 08:19
Show Gist options
  • Save Mizpah/349b838548c7815c87ea to your computer and use it in GitHub Desktop.
Save Mizpah/349b838548c7815c87ea to your computer and use it in GitHub Desktop.
FieldException: Attempt to create field name <em class="placeholder">logged_item_type</em> which already exists and is active. in field_create_field() (line 85 of /Users/martindean/Sites/drupal-core/modules/field/field.crud.inc).
<?php
/**
* @file
* Contains content installed by the module.
*
* Created by PhpStorm.
* User: martindean
* Date: 26/11/14
* Time: 05:14
*/
/**
* Implements hook_install().
*/
function genima_log_install() {
// Save all new node types (from all modules).
node_types_rebuild();
// Get all node types.
$types = node_type_get_types();
// Add existing body field to OUR node type.
node_add_body_field($types['logged_item']);
// Call our function to add custom fields during install.
add_custom_fields();
}
/**
* Custom function to add fields.
*
* Uses data read from our custom arrays in _genima_log_installed_fields(),
* and genima_log_installed_instances().
* @todo this will need some sort of logic to distinguish between bundles?
*/
function add_custom_fields() {
// A custom function to add fields, not a drupal hook.
foreach (_genima_log_installed_fields() as $field) {
field_create_field($field);
}
foreach (_genima_log_installed_instances() as $fieldinstance) {
$fieldinstance['entity_type'] = 'node';
$fieldinstance['bundle'] = 'logged_item';
// Actually loop through and do the work.
field_create_instance($fieldinstance);
}
}
/**
* Implements hook_uninstall().
* @todo Insert a confirm during on uninstall, showing node count to remove.
* @todo account for new fields.
*/
function genima_log_uninstall() {
$genimanodetype = 'logged_item';
// Get all node ID's of our content type.
$sql = 'SELECT nid FROM {node} n WHERE n.type = :type';
$result = db_query($sql, array(':type' => $genimanodetype));
$nodeids = array();
foreach ($result as $row) {
$nodeids[] = $row->nid;
}
// Use the collected ID's to delete multiple nodes.
node_delete_multiple($nodeids);
// Add custom field deletion.
delete_custom_fields();
// Now delete the content type.
node_type_delete($genimanodetype);
// Batch fields in 500's.
field_purge_batch(500);
}
/**
* Custom function to delete fields.
*
* Called in genima_log_uninstall().
*/
function delete_custom_fields() {
foreach (array_keys(_genima_log_installed_fields()) as $field) {
field_delete_field($field);
}
$instances = field_info_instances('node', 'logged_item');
foreach ($instances as $instance_name => $fieldinstance) {
field_delete_instance($fieldinstance);
}
}
/**
* Implements hook_installed_fields().
*
* A private instance, just for this module, this is then invoked from the
* add_custom_fields() function.
*/
function _genima_log_installed_fields() {
// Private function, only for this module.
// use get_t(); as t() is unavailable during install.
$t = get_t();
return array(
'logged_item_type_field' => array(
'field_name' => 'logged_item_type',
'label' => $t('Type of log entry'),
'type' => 'text',
),
'bug_status_field' => array(
'field_name' => 'bug_status',
'label' => $t('Bug status'),
'type' => 'text',
),
);
}
/**
* Implements hook_installed_instances().
*
* A private instance, just for this module, this is then invoked from the
* add_custom_fields() function.
*/
function _genima_log_installed_instances() {
// Private function, only for this module.
$t = get_t();
return array(
// Add log type field instance and settings.
'logged_item_type_instance' => array(
'field_name' => 'genima_log_type',
'type' => 'text',
'label' => $t('Type of log entry'),
'widget' => array(
'type' => 'text_textfield',
),
'display' => array(
'logged_item_type_display' => array(
'label' => $t('Type of log entry'),
'type' => 'text',
),
),
),
// Add bug field instance and settings.,
'bug_status_instance' => array(
'field_name' => 'genima_bug_status',
'type' => 'text',
'label' => $t('Status of bug'),
'widget' => array(
'type' => 'text_textfield',
),
'display' => array(
'bug_status_display' => array(
'label' => $t('Status of bug'),
'type' => 'text',
),
),
),
);
}
<?php
/**
* @file
* Creates a simple system for recording and viewing changes to a drupal site in
* in development, and post deploy.
*/
/**
* Implements hook_help().
*
* Displays help and module information.
*/
function genima_log_help($path, $arg) {
// Defines drupal help files and paths.
switch ($path) {
case "admin/help#genima_log":
return '<p>' . t("Displays logged information about current development and bugs") . '</p>';
}
}
/**
* Implements hook_node_info().
*/
function genima_log_node_info() {
// Returns an array defining a new node type.
return array(
'logged_item' => array(
'name' => t('Logged Item'),
'base' => 'node_content',
'description' => t('A content type for logging items for use in Genima Log'),
'help' => t('Add logged items, messages and statement for review by others'),
'has_title' => TRUE,
'title_label' => t('Logged Entry'),
),
'bug' => array(
'name' => t('bug'),
'base' => 'node_content',
'description' => t('A content type for logging bugs for use in Genima Log'),
'help' => t('Add logged items, actions, notes, bugs and fixes here'),
'has_title' => TRUE,
'title_label' => t('Bug'),
),
);
}
/**
* Implements hook_form().
*/
function genima_log_form($node, &$form_state) {
// Shows the form used to create/edit the logged item nodes.
return node_content_form($node, $form_state);
// Returns the title field as the has_title attribute is set.
}
/**
* Implements hook_block_info().
* @todo Sort out permissions and block content
*/
function genima_log_block_info() {
// Create a block to display content.
$blocks['genima_log'] = array(
// The name that will appear in the block list.
'info' => t('Recently Logged'),
// Default setting.
'cache' => DRUPAL_CACHE_PER_ROLE,
);
return $blocks;
}
The above module worked just fine, when it was only one content type.
Since adding another, I am pretty sure I need to change lines 39,40 & 79 of the installer.
However I am not sure of the right way to make this work with multiple content types.
Some form of loop that can get the budle details from the original array? (note I am a begginner in php, I normally configure and theme, as opposed to code!)
I started thinking that surely there is a known pattern, where the .install (and uninstall) file is generic and fields are defined in .inc files and hook_node_info ?
(Eventually this will be two taxonomies, 4 content types, multiple different fields per content type, and sample data, including term reference fields)
Any comments and help appreciated!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment