Importar CSV para nós / entidades no Drupal 8, incluindo uma interface do usuário

7

Qual é a melhor solução para importar arquivos CSV para nós ou entidades no Drupal 8 que oferece uma interface do usuário para que os editores de conteúdo possam importar regularmente?

Ouvi dizer que o D8 Migrate funciona bem, mas entendo que atualmente não há interface do usuário para o processo de importação.

A importação de CSV via feeds ainda não parece estar pronta.

Scott Anderson
fonte
3
Tentei um teste básico usando a versão mais recente do Feeds D8 e aplicando o patch no 4 do tópico drupal.org/node/2443471#comment-9723715 e ele parece funcionar corretamente. Veja como se aplica a campos mais complexos.
Scott Anderson
Eu acho que o Drupal está salvando o wordpress o tempo todo ou o Drupal ainda está em desenvolvimento.
Vishal Kumar Sahu

Respostas:

10

Faço isso o tempo todo, utilizando entidades de configuração de migração (fornecidas pelo módulo migrate_plus ). Defina um plug-in de migração no diretório config / install do seu módulo de migração, usando o plug-in de origem CSV do módulo migrate_source_csv - omitindo a configuração de origem 'path', que será preenchida no formulário. Digamos que o ID dessa migração seja exemplo_csv. Crie um formulário com um elemento de upload de arquivo (chamado 'csv_file' neste caso) e no método submitForm ():

  public function submitForm(array &$form, FormStateInterface $form_state) {
    $all_files = $this->getRequest()->files->get('files', []);
    if (!empty($all_files['csv_file'])) {
      $validators = ['file_validate_extensions' => ['csv']];
      if ($file = file_save_upload('csv_file', $validators, 'public://', 0)) {
        $csv_migration = Migration::load('example_csv');
        $source = $csv_migration->get('source');
        $source['path'] = $file->getFileUri();
        $csv_migration->set('source', $source);
        $csv_migration->save();
        drupal_set_message($this->t('File uploaded as @uri.', ['@uri' => $file->getFileUri()]));
      }
      else {
        drupal_set_message($this->t('File upload failed.'));
      }
    }
  }

Isso atualiza as configurações de migração com o novo arquivo. Você ainda precisa executar a migração usando drush mi example_csvpara realmente importar o conteúdo.

Ou adicione algum código à função para realmente executar a importação:

      $migration_instance = \Drupal::service('plugin.manager.migration')->createInstance('example_csv');

      $executable = new MigrateExecutable($migration_instance, new MigrateMessage());

      try {
        $migration_status = $executable->import();
      }
      catch (\Exception $e) {
        \Drupal::logger('migrate_drupal_ui')->error($e->getMessage());
        $migration_status = MigrationInterface::RESULT_FAILED;
      }
      if ($migration_status) {
        drupal_set_message($this->t('Import Successful'));
      }
      else {
        drupal_set_message($migration_status, 'error');
      }
Mike Ryan
fonte
1

Provavelmente é melhor e mais rápido usar o Feeds , mas como a versão D8 ainda está em desenvolvimento; Como alternativa, você pode usar o Excel + VBA ( Visual Basic for Applications , vem com Excel) + Internet Explorer 11.

Aqui está um exemplo de como você pode importar seu conteúdo CSV usando o VBA.

Por exemplo, vamos supor que você queira importar isso e criar novos nós com as informações do seu CSV:

insira a descrição da imagem aqui

Aqui está um código VBA de exemplo:

Sub Drupal_Import()

Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")

Dim x As Integer

For x = 2 To 4 'this controls which rows get added, so only 2 to 4

myURL = "https://rgr79.ply.st/node/add/article"

With IE
.Visible = True 'makes your Internet Explorer window visible.
.navigate myURL
End With

Do
el = vbNullString
On Error Resume Next
Set HTML = IE.document
el = HTML.getElementsByClassName("visually-hidden")(1).innerText
DoEvents
Loop While el = vbNullString

'the above loops until the visualy-hidden class is detected, which means the edit form has been loaded

Application.Wait (Now + TimeValue("00:00:03")) 'tells the program to wait 3 secs.

Set HTML = IE.document

HTML.getElementById("edit-title-0-value").Value = Cells(x, 1).Value 'here the 1 is the Y (so 1 is Column A)

HTML.getElementById("edit-body-0-value").Value = Cells(x, 2).Value 'here the 2 is the Y (so 2 is Column B)

Cells(x, 3).Value = "Done" 'here we use the 3rd column (Column C) and mark it as Done to keep track.

HTML.getElementsByClassName("button js-form-submit form-submit")(1).Click 'clicks the submit button

Application.Wait (Now + TimeValue("00:00:00")) 'here I have a wait for 0, increase it to 2 or 3 if you see your VBA get stuck after submitting a node.

Do
el = vbNullString
On Error Resume Next
Set HTML = IE.document
el = HTML.getElementsByClassName("messages messages--status")(0).innerText
DoEvents
Loop While el = vbNullString

'all the above does is loops the code until the drupal message is detected, which means the node was loaded, after the submit.

Next x

End Sub

Certifique-se de alterar o nome do domínio na myURL = "https://rgr79.ply.st/node/add/article"linha do seu domínio. Estou usando um domínio simplytest.me , se você já não pode saber.

Como adicionar o código VBA?

Clique na guia Desenvolvedor e, em seguida, no ícone Visual Basic (ou ALT + F11)

insira a descrição da imagem aqui

e cole o código dentro da Plan1 (Plan1)

insira a descrição da imagem aqui

Agora, na barra de ferramentas, clique em toole depoisReferences

insira a descrição da imagem aqui

Você precisará rolar, encontrar e marcar

  • Biblioteca de objetos HTML da Microsoft
  • Controles da Internet da Microsoft

insira a descrição da imagem aqui

Nota: Eu sei que funciona com o Internet Explorer 11, não tenho certeza se funciona com o novo navegador Microsoft Edge.

Agora você está pronto para executar o script. Você pode fazer isso clicando no botão Reproduzir

insira a descrição da imagem aqui

Você também pode executá-lo clicando no ícone Macros (veja a imagem2), mas prefiro fazê-lo na janela do VBA.

Então você pressiona o botão play e uma janela do IE é aberta automaticamente e você vê o seguinte:

insira a descrição da imagem aqui

Ah, sim, você esqueceu de fazer login, lol.

Então, você prossegue o login no Drupal e fecha o explorer (já que o histórico de cookies salva o seu login) e planeja pressionar o botão play novamente. Mas você não é capaz de ... você vê o botão play acinzentado e não é capaz de fazer alterações no código VBA ... O que está acontecendo?

Bem, seu código ainda está sendo executado, então você precisa pressionar o botão Parar (redefinir).

insira a descrição da imagem aqui

Agora você pode clicar no botão play novamente e alegrar o mundo da automação.

Importante

Se você planeja inserir itens no campo Corpo (como estamos fazendo neste exemplo), como o Drupal 8 usa CKEditor para esse campo e CKEditor é JS, não podemos segmentar uma classe ou ID div; portanto, não podemos adicionar conteúdo dentro do CKEditor.

Felizmente, há uma solução alternativa. Verifique se as configurações de segurança do IE 11 estão definidas como Alta, isso automaticamente bloqueará todas as JS. Portanto, o CKeditor não será carregado e o campo do corpo será como os outros campos.

insira a descrição da imagem aqui


Se você precisar editar um exemplo de nós:

insira a descrição da imagem aqui

Sub Drupal_Edit()

Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")

Dim x As Integer

For x = 2 To 4 'this controls which rows get added, so only 2 to 4

myURL = "https://rgr79.ply.st/node/" & Cells(x, 3) & "/edit"

With IE
.Visible = True 'makes your Internet Explorer window visible.
.navigate myURL
End With

Do
el = vbNullString
On Error Resume Next
Set HTML = IE.document
el = HTML.getElementsByClassName("visually-hidden")(1).innerText
DoEvents
Loop While el = vbNullString

'the above loops until the visualy-hidden class is detected, which means the edit form has been loaded

Application.Wait (Now + TimeValue("00:00:04")) 'tells the program to wait 3 secs.

Set HTML = IE.document

HTML.getElementById("edit-title-0-value").Value = Cells(x, 1).Value 'here the 1 is the Y (so 1 is Column A)

HTML.getElementById("edit-body-0-value").Value = Cells(x, 2).Value 'here the 2 is the Y (so 2 is Column B)

Cells(x, 4).Value = "Done" 'here we use the 4th column (Column D) and mark it as Done to keep track.

HTML.getElementsByClassName("button js-form-submit form-submit")(1).Click 'clicks the submit button

Application.Wait (Now + TimeValue("00:00:00")) 'here I have a wait for 0, increase it to 2 or 3 if you see your VBA get stuck after submitting a node.

Do
el = vbNullString
On Error Resume Next
Set HTML = IE.document
el = HTML.getElementsByClassName("messages messages--status")(0).innerText
DoEvents
Loop While el = vbNullString

'all the above does is loops the code until the drupal message is detected, which means the node was loaded, after the submit.

Next x

End Sub
Sem suor
fonte
Obrigado ... essa é uma opção interessante. Acho que vou precisar de uma solução mais simples do ponto de vista da interface do usuário.
Scott Anderson
2
Não funcionará se os usuários não tiverem o IE e parecerem desnecessariamente complexos. Acho que o caminho a seguir seria um formulário de confirmação de administrador personalizado, operação em lote e processo de migração ... @mikeryan seria a pessoa a perguntar.
Kevin Kevin
Você é assassino.
Vishal Kumar Sahu
0

A multa acima está trabalhando para mim, mas Migratin::Load()e save()método não está disponível no Drupal 8 3.x. Fiz algumas alterações acima no código sugerido por Mike Ryan. Aqui está o código de trabalho no manipulador de subrit de formulário.

public function submitForm(array &$form, FormStateInterface $form_state) {
$all_files = $form_state->getValue('csv_file');
if (!empty($all_files)) {
  $file = file_load($all_files[0]);
  if (!empty($file)) {
    $csv_migration = \Drupal::service('plugin.manager.migration')->createInstance('panalist_migration');
    $source = $csv_migration->get('source');
    $source['path'] = $file->getFileUri();
    $csv_migration->set('source', $source);
    drupal_set_message($this->t('File uploaded as @uri.', ['@uri' => $file->getFileUri()]));
    $executable = new MigrateExecutable($csv_migration, new MigrateMessage());

    try {
      $migration_status = $executable->import();
    }
    catch (\Exception $e) {
      \Drupal::logger('migrate_drupal_ui')->error($e->getMessage());
      $migration_status = MigrationInterface::RESULT_FAILED;
    }
    if ($migration_status) {
      drupal_set_message($this->t('Import Successful'));
    }
    else {
      drupal_set_message($migration_status, 'error');
    }
  }
  else {
    drupal_set_message($this->t('File upload failed.'));
  }
}
Manav
fonte