Criando programaticamente um tipo de conteúdo com campo de arquivo em um módulo personalizado

9

Estou escrevendo um módulo personalizado, o que já fiz antes, mas é a primeira vez que tentei criar um tipo de conteúdo com campos. Eu implementei hook_node_info e o Tipo de conteúdo está aparecendo na lista de Tipos de conteúdo no menu suspenso do admin_menu, no entanto, quando eu o navego, admin/structure/typesele não está listado.

Eu implementei o hook_install e peguei algum código que encontrei em outra questão SO. Eu tenho o código para imprimir algumas informações de depuração no meu log de erros e parece que tudo funciona, mas quando eu navego para o Tipo de conteúdo da estrutura, ele não mostra o campo que eu adicionei.

Aqui estão os 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));
}

Eu posso ver uma tabela chamada field_data_field_mymod_myfileno banco de dados, então eu sei que a primeira parte funcionou. No entanto, a tabela está vazia.

O log de erros mostra que o field_create_instance()método retornou isso:

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

Por que meu campo não aparece nesse tipo de conteúdo?

Kenny Wyland
fonte
11
você não gosta de recursos? Acho mais fácil criar o Tipo de Conteúdo usando o FieldUI e depois exportar o Recurso para um "Recurso" personalizado (módulo). ... apenas fazendo as matrizes usarem o hook_info que você tem aqui - e as matrizes para definições de campo. Você pode verificar seu trabalho dessa maneira.
Tenken

Respostas:

7

Isso não é tanto uma resposta, mas uma expansão da resposta anterior.

Achei esses dois links muito úteis para descobrir o que o sistema precisa para adicionar campos personalizados ao seu tipo de nó de módulo personalizado.

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

Boas informações adicionais: http://public-action.org/content/drupal-7-field-api-drupal-7-adding-custom-content-type-custom-fields-field-api

O problema que tive foi que esses (e todos os outros exemplos que posso encontrar on-line) são exemplos muito específicos, sem documentação suficiente para me ajudar a descobrir uma solução para meu próprio caso de uso.

O que ajudou foi o comentário da tenken ao OP sobre o uso do módulo Recursos para obter as matrizes para os campos personalizados.

Então, baixei o módulo Recursos e o habilitei: https://drupal.org/project/features

Em seguida, criei os campos no meu tipo de conteúdo, usando a interface administrativa do Drupal, como você faria normalmente, que eu queria que o módulo criasse. Depois naveguei para Estrutura> Recursos> Criar recurso e coloquei um nome falso (usei "teste") para o recurso e, em seguida, na área de componentes, clique em "Instâncias de campo" e marque as caixas dos campos personalizados. Os campos são todos nomeados como node- [nome da máquina do tipo de nó] - [nome do campo]; portanto, no meu caso, como eu queria um campo de imagem, era node-novel_section-field_image.

Depois de selecionar os campos personalizados para o meu tipo de nó, cliquei em "Recurso de download" e salvei o arquivo .tar na minha área de trabalho, abri-o, abri a pasta "test" e depois vi o test.features.field_base.inc e test. features.field_instance.inc para obter as matrizes necessárias para meus campos.

Então eu apenas usei a estrutura descrita pelo primeiro link que eu postei e depois disso funcionou perfeitamente. Para mim.

Não consegui encontrar nenhuma documentação sobre as estruturas de matriz necessárias para itens como campos de imagem e campos de referência de taxonomia e parecia que todos os outros tutoriais e solicitações de ajuda on-line estão focados em itens específicos, como campos de texto.

Espero que qualquer pessoa com o mesmo problema que eu estava tendo veja isso e consiga fazer sua instalação funcionar usando esses exemplos e o módulo Recursos, como eu fiz.

Graças à tenken por apontar essa funcionalidade do módulo Recursos, eu nunca a usei e não sabia que faria isso.

Jason Gray
fonte
4

Este código que será criado novo tipo de conteúdo que deve ser adicionado ao arquivo .install.

Adicionando 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);
}
?>

Você deve enviar uma mensagem drupal e gravar este evento no log:

<?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')); 
  }
}
?>

Forneça hook_uninstall () para remover seu tipo de conteúdo :

<?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
fonte
Obrigado por uma resposta muito detalhada, mas como adiciono um campo Arquivo ao tipo de conteúdo depois que ele foi criado?
precisa
Eu usei o código acima e ele diz que foi adicionado o tipo de conteúdo, mas não aparecemadmin/structure/types
Kenny Wyland
11
Para que isso funcione, você precisa implementar hook_form () em seu módulo, caso contrário, se você olhar na tabela node_type no banco de dados, notará que seu tipo recém-criado está desabilitado. A implementação de hook_form () parece ativá-lo (por que é assim, não faço ideia e não faz muito sentido). A propósito, seu endereço é o segundo comentário.
user5013
1

Esta postagem está um pouco desatualizada, mas, se ajudar, achei este artigo muito claro. Ele mostra como criar um novo tipo de conteúdo passo a passo.

Link para o 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
fonte
Por favor, inclua uma citação relevante do que em sua resposta
Pierre.Vriens