Creación programática de un tipo de contenido con campo de archivo en un módulo personalizado

9

Estoy escribiendo un módulo personalizado, lo que he hecho antes, pero esta es la primera vez que intento crear un tipo de contenido con campos. Implementé hook_node_info y el Tipo de contenido se muestra en la lista de Tipos de contenido en el menú desplegable de admin_menu, sin embargo, cuando busco admin/structure/typesno aparece en la lista.

Implementé hook_install y agarré un código que encontré en otra pregunta SO. Tengo el código imprime información de depuración en mi registro de errores y parece que todo funciona, pero cuando busco el Tipo de contenido de estructura no muestra el campo que agregué.

Aquí hay ganchos:

function mymod_node_info() {
  return array(
    'mymod_content' => array(
      'name' => t('My Mod'),
      'base' => 'mymod_content',
      'description' => t('A Description'),
    )
  );
}

function mymod_install() {
    error_log('mymod_install');
    $types = node_type_get_types();

    if ( ! field_info_field('field_mymod_myfile') ) {
        $field = array(
            'field_name' => 'field_mymod_myfile',
            'type' => 'file',
        );
        $created_field = field_create_field($field);
        error_log('---- field_create_field -----');
        error_log(var_export($created_field, true));
    }

    $instance = array(
        'field_name' => 'field_mymod_myfile',
        'entity_type' => 'mymod_content',
        'bundle' => 'mymod_content',
        'required' => TRUE,
    );
    $created_instance = field_create_instance($instance);
    error_log('---- field_create_instance -----');
    error_log(var_export($created_instance, true));
}

Puedo ver una tabla llamada field_data_field_mymod_myfileen la base de datos, así que sé que la primera parte funcionó. Sin embargo, la tabla está vacía.

El registro de errores muestra que el field_create_instance()método devolvió esto:

array (
  'field_name' => 'field_mymod_myfile',
  'entity_type' => 'mymod_content',
  'bundle' => 'mymod_content',
  'required' => true,
  'field_id' => '5',
)

¿Por qué mi campo no aparece en este tipo de contenido?

Kenny Wyland
fuente
1
¿no te gustan las características? Creo que es más fácil crear el Tipo de contenido con FieldUI y luego exportar la Característica a una "Característica" (módulo) personalizada. ... simplemente haciendo que las matrices usen el hook_info que tienes aquí, y las matrices para las definiciones de campo. Podría verificar su trabajo de esa manera.
tenken

Respuestas:

7

Esto no es tanto una respuesta como una expansión de la respuesta anterior.

Encontré estos dos enlaces muy útiles para descubrir qué necesita el sistema para agregar campos personalizados a su tipo de nodo de módulo personalizado.

Lo mejor: http://www.sitepoint.com/creating-a-new-drupal-node-type/

Buena información adicional: http://public-action.org/content/drupal-7-field-api-drupal-7-adding-custom-content-type-custom-fields-field-api

El problema que tuve fue que estos (y todos los demás ejemplos que puedo encontrar en línea) son ejemplos muy específicos sin suficiente documentación para ayudarme a encontrar una solución a mi propio caso de uso.

Lo que ayudó fue el comentario de Tenken al OP sobre el uso del módulo Características para obtener los arreglos para los campos personalizados.

Así que descargué el módulo Características y lo habilité: https://drupal.org/project/features

Luego creé los campos en mi tipo de contenido, usando la interfaz de administración en Drupal como lo haría normalmente, que quería que creara el módulo. Luego busqué Estructura> Características> Crear característica y puse un nombre falso (usé "prueba") para la característica y luego en el área de componentes, haga clic en "Instancias de campo" y marque las casillas de los campos personalizados. Todos los campos se denominan algo como nodo- [nombre de máquina de tipo de nodo] - [nombre de campo], así que en mi caso, ya que quería un campo de imagen, era node-novel_section-field_image.

Después de seleccionar los campos personalizados para mi tipo de nodo, simplemente hice clic en "Descargar característica" y guardé el archivo .tar en mi escritorio, lo abrí, abrí la carpeta "prueba" y luego miré test.features.field_base.inc y probé. features.field_instance.inc para obtener las matrices que necesitaba para mis campos.

Luego utilicé la estructura descrita en ese primer enlace que publiqué y después funcionó perfectamente. Para mi.

No pude encontrar ninguna documentación sobre las estructuras de matriz necesarias para cosas como campos de imagen y campos de referencia de taxonomía y parecía que todos los demás tutoriales y solicitudes de ayuda en línea se centran en cosas específicas como campos de texto.

Espero que cualquiera que tenga el mismo problema que yo haya tenido vea esto y pueda hacer que su configuración funcione utilizando estos ejemplos y el módulo de Características como lo hice yo.

Gracias a Tenken por señalar esta funcionalidad del módulo Características, nunca la había usado y no sabía que lo haría.

Jason Gray
fuente
4

Este código que se creará nuevo tipo de contenido que debe agregar al archivo .install.

Agregando hook_install ():

<?php
function your_module_name_install() {
  // use get_t() to get the name of our localization function for translation
  // during install, when t() is not available.
  $t = get_t();

  // Define the node type.
  $node_example = array(
    'type' => 'node_example',
    'name' => $t('Example Node'),
    'base' => 'node_content',
    'description' => $t('This is an example node type with a few fields.'),
    'body_label' => $t('Example Description')
  );

  // Complete the node type definition by setting any defaults not explicitly
  // declared above.
  // http://api.drupal.org/api/function/node_type_set_defaults/7
  $content_type = node_type_set_defaults($node_example);
  node_add_body_field($content_type);

  // Save the content type
  node_type_save($content_type);
}
?>

Debe hacer un mensaje de drupal y escribir este evento en el registro:

<?php
function your_module_name_install() {
  $t = get_t();
  $node_example = array(
    'type' => 'node_example',
    'name' => $t('Example Node'),
    'base' => 'node_content',
    'description' => $t('This is an example node type with a few fields.'),
    'body_label' => $t('Example Description')
  );
  $content_type = node_type_set_defaults($node_example);
  node_add_body_field($content_type);
// Check if we create content type or update.
  $status = node_type_save($content_type);
// Replacement rule for the messages.
  $t_args = array('%name' => $content_type->name);
  if ($status == SAVED_UPDATED) { // update case
    drupal_set_message($t('The content type %name has been updated.', $t_args));
  } 
  elseif ($status == SAVED_NEW) { // create case
    drupal_set_message($t('The content type %name has been added.', $t_args));
    watchdog('node', 'Added content type %name.', $t_args, WATCHDOG_NOTICE, l($t('view'), 'admin/structure/types')); 
  }
}
?>

Proporcione hook_uninstall () para eliminar su tipo de contenido :

<?php
function your_module_name_uninstall() {
  // Gather all the example content that might have been created while this
  // module was enabled.  Simple selects still use db_query().
  // http://api.drupal.org/api/function/db_query/7
  $sql = 'SELECT nid FROM {node} n WHERE n.type = :type';
  $result = db_query($sql, array(':type' => 'node_example'));
  $nids = array();
  foreach ($result as $row) {
    $nids[] = $row->nid;
  }
  // Delete all the nodes at once
  // http://api.drupal.org/api/function/node_delete_multiple/7
  node_delete_multiple($nids);
  // Delete our content type
  // http://api.drupal.org/api/function/node_type_delete/7
  node_type_delete('node_example');
}
?>
Nitesh Sethia
fuente
Gracias por una respuesta muy detallada, pero ¿cómo agrego un campo Archivo al tipo de contenido después de que se haya creado?
Kenny Wyland
Usé su código anterior y dice que se agregó el tipo de contenido, pero no apareceadmin/structure/types
Kenny Wyland
1
Para que esto funcione, debe implementar hook_form () en su módulo; de lo contrario, si busca en la tabla node_type en la base de datos, notará que su tipo recién creado está deshabilitado. La implementación de hook_form () parece activarlo (por qué es así, no tengo idea y no tiene mucho sentido). Esto aborda su segundo comentario por cierto.
user5013
1

Esta publicación está un poco desactualizada, pero si ayuda, he encontrado que este artículo es muy claro. Le muestra cómo crear un nuevo tipo de contenido paso a paso.

Enlace al tutorial

<?php

/**
 * Implements hook_install().
 */
function book_install()
{

    $t = get_t();

    // Step 1 - Define the custom content type

    $content_type = array(

        'type'          => 'book',
        'name'          => $t('Book'),
        'description'   => $t('Create a new book'),
        'title_label'   => $t('Book title'),
        'base'          => 'node_content',
        'custom'        => TRUE,

    );

    $node_type = node_type_set_defaults($content_type);

    node_type_save($node_type);

    // Step 2 - Create new fields

    $fields = array(

        // Author’s name

        'book_author_name'  => array(

            'field_name'    => 'book_author_name',
            'type'          => 'text',
            'cardinality'   => 1,

        ),

        // Description

        'book_description'  => array(

            'field_name'    => 'book_description',
            'type'          => 'text_long',
            'cardinality'   => 1,

        ),

    );

    foreach( $fields as $field ) {

        field_create_field($field);

    }

    // Step 3 - Attach fields to content type

    $instances = array(

        // Author’s name

        'book_author_name'  => array(

            'field_name'   => 'book_author_name',
            'label'        => $t('Author Name'),
            'required'     => TRUE,
            'widget'       => array(
                'type'  => 'text_textfield'
            ),

        ),

        // Description

        'book_description'  => array(

            'field_name'   => 'book_description',
            'label'        => $t('Description'),
            'required'     => TRUE,
            'widget'       => array(
                'type'  => 'text_textarea'
            ),

        ),

    );

    foreach( $instances as $instance ) { // Loop through our instances

        $instance['entity_type']   = 'node';
        $instance['bundle']        = 'book'; // Attach the instance to our content type

        field_create_instance($instance);

    }

}
Shlomi Nissan
fuente
Incluya una cita relevante en su respuesta
Pierre.Vriens