domingo, 19 de setembro de 2010

Criar Curso no Moodle com Comando SQL


    Se você estiver fazendo migração de dados ou integração de um sistema acadêmico com a  Plataforma  Moodle, certamente vai precisar criar curso no Moodle diretamente no banco de  dados sem usar a interface do Moodle.

      Isso implica conhecer a estrutura das tabelas da base de dados do Moodle e fazer INSERT nas tabelas certas. Bem, isso me custou muitas horas de pesquisa. No final descobri que é necessário fazer apenas 4 INSERT básicos. Bem, vamos lá. São  três passos. 

Os comandos SQL foram testados na versão 1.9.3 do Moodle. Devem funcionar para qualquer versão 1.9.x e não para versão inferior a 1.9.
1º Passo – Criar o Curso
    Essa parte é mais moleza. Basta fazer um INSERT na tabela mdl_course com o seguinte comando SQL:

INSERT INTO mdl_course (category,fullname,shortname) VALUES (1,'Curso1','C1')   

Embora a tabela  mdl_course tenha muitas colunas, nesse exemplo foram usadas os mais importantes:
  • category -  Chave estrangeira da tabela de categoria de curso - mdl_course_categories 
  • fullname – Nome complete do curso 
  • shortname – Abreviatura do curso
No comando INSERT, foi criado um curso denominado Curso1 na categoria de curso padrão do Moodle, cujo id é 1. 
Após executar o INSERT, recupera o id do curso gerado automaticamente pelo banco de dados. No MySQL use o comando LAST_INSERT_ID().

2º Passo – Criar Contexto do Curso
    Com o curso criado, agora é necessário criar contexto do curso na tabela mdl_context com o seguinte comando SQL:

INSERT INTO mdl_context (contextlevel,instanceid) VALUES (50,?)
O campo contextlevel define o nível do contexto. Para curso 50 é o valor padrão da tabela de domínio. O campo instanceid é a instância do curso. Preencha esse campo com o valor do Id do curso gerado automaticamente no 1º passo.

    Ao executar o comando SQL, recupere o id do contexto gerado automaticamente. Use esse id para atualizar duas colunas:  path e depth. Para isso, execute o seguinte comando SQL:

UPDATE  mdl_context SET path='/1/3/$ID_CONTEXT', depth=3 WHERE id=$ID_CONTEXT

    Você precisa substituir a variável $ID_CONTEXT pelo id gerado automaticamente do INSERT anterior, ao executar o comando  para criar o contexto do curso. Se o id for 10,  o comando SQL de atualização será:

UPDATE  mdl_context SET path='/1/3/10', depth=3 WHERE id=10
Nesse momento você deve estar perguntando por que o campo path recebe  '/1/3/$ID_CONTEXT' como valor padrão  e o  campo  depth o número 3. Ainda não encontrei a resposta. Assim como você, eu também estou perguntando. Só sei que demorei três semanas mudando de variável até que funcionou. Se não preencher esses campos,  nenhum usuário consegue entrar no curso.  Se você encontrar alguma explicação  não esqueça de me avisar.

3º Passo – Criar tópico/seção padrão do curso 

Ao criar o curso no 1º passo, não foi definido o formato. Por padrão, será criado curso em formato de tópico.  Assim, é necessário cria um primeiro tópico, o tópico número zero,  do curso. Para isso, execute o seguinte comando SQL:

 INSERT INTO mdl_course_sections (course,section) VALUES (?,0)
Na coluna course o valor do parâmetro é o id do curso gerado automaticamente no 1º passo. A segunda coluna, a section define a ordem do tópico. Por se tratar do primeiro tópico, deixe zero como está.
    Há outras colunas na tabela mdl_course_sections. No entanto, para efeito de simplificação, se restringiu aos mais importantes.
    Ao finalizar o 3º passo, o curso já está criado no Moodle. Há muitas configurações do curso que não foram abordado nesse poste. Você pode fazer isso preenchendo todos as outras colunas das tabelas mdl_course mdl_course_sections  e entre outros. Agora que o curso já está criado, acesse o ambiente Moodle com a senha do admin,  ative a edição e adicione o bloco de administração. Daí, faça o restante das configurações.

    Os comandos SQL foram testados apenas na versão 1.9.3. Deve funcionar em qualquer versão 1.9.x  já a estrutura das tabelas são as mesmas.  Não deve funcionar para as versões anteriores a 1.9.  Mas lógica é muito parecida. Não custa testar e fazer os ajustes necessários.  Agora boa programação, ou melhor, boa sorte na jornada de integração do Moodle com o seu sistema acadêmico.


Veja Também
Matricular Usuário no Curso do Moodle com Comando SQL

43 comentários:

  1. Desculpe criticar, amigo, mas esta solução só seria válida para uma migração.

    Para integração de sistemas o ideal é utilizar a API do Moodle, como a função create_course(). Assim você evita problemas com novas versões, que podem conter estrutura diferente de bases, e o prefixo das tabelas, que pode ser qualquer coisa.

    ResponderExcluir
  2. Oi Paulo,
    Tudo beleza!

    Cara, você está fazendo uma crítica construtiva ao alertar os desenvolvedores do Moodle que existe API do Moodle como create_course(). Isso é um das alternativas de integração que pressupões usar linguagem PHP e gerenciar integração a partir do ambiente Moodle.

    Há situações que esse API não atende tais como:
    Uso de outra linguagem que não seja PHP
    Gerenciar integração a partir de um sistema externo e não do Moodle
    Imagina a situação de um sistema acadêmico escrito em Delphi ou Java que deve importar/exportar dados para o Moodle. Nesse modelo de integração em que a requisição deve partir sempre do sistema acadêmico para o Moodle e o não o inverso não dá para usar API do Moodle. Neste caso a integração dever ser feita escrevendo comando SQL embutido na linguagem de programação do sistema acadêmico. A desvantagem disso é atualizar o código SQL caso houver mudança na estrutura da tabela na nova versão do Moodle. Geralmente essa mudança é muito pequena.

    ResponderExcluir
  3. (...) UPDATE mdl_context SET path='/1/3/10', depth=3 WHERE id=10
    Nesse momento você deve estar perguntando por que o campo path recebe '/1/3/$ID_CONTEXT' como valor padrão e o campo depth o número 3. Ainda não encontrei a resposta. (...)

    Tanto quanto me parece, o "/1/3/10" significa que na árvore de organização dos cursos, esta disciplina/curso situa-se: primeiro no ramo "1", dentro desse no "3" e por último é o "10". A árvore tem profundidade de 3 níveis.

    Por exemplo no meu agrupamento de escolas no primeiro nível tenho as escolas, depois os ciclos, de seguida os anos de ensino e por último as turmas de cada ano. No meu caso uma disciplina vai para ao nível 5.

    (ou é isso ou não entendi nada :D)

    ResponderExcluir
  4. Cara, onde fica registro dessa árvore na base de dados?
    Esses níveis que você está falando não são subcategorias de curso?
    Ainda não entendi!

    ResponderExcluir
  5. Preciso de ajuda para criar formulários.

    Você poderia me ajudar? Qual o valor?

    ResponderExcluir
  6. Entre em contato por e-mail linovazmoniz@gmail.com e explica melhor que tipo de formulário você precisa.

    ResponderExcluir
  7. olá badiu, e como fazer pra adicionar também o professor administrador deste curso?

    ResponderExcluir
  8. Este comentário foi removido pelo autor.

    ResponderExcluir
  9. Lino, boa tarde.
    Estou tento um problema e não estou conseguindo resolver.
    Desenvolvi um código em php / mysql para fazer às funções de criação e atribuições as disciplinas...
    Hoje o professor somente acessa as suas disciplinas e o aluno as disciplinas a ele atribuída certo!!!
    Porém não estou conseguindo habilitar a função de importar o conteúdo de uma disciplina para a outra.. Não aparece a lista das disciplinas para o professor.
    Você saberia me dizer se é algum campo que se faz relacionamento ou se tem de setar alguma variável para isso???
    OBS: a opção não aparece nem para o administrador.

    ResponderExcluir
  10. Eric,
    A hipótese mais provável é a permissão referente a importação que deve estar desabilitada no perfil do admin e do professor. Faça um check list no sistema de permissão atribuído a esses dois perfis.

    ResponderExcluir
    Respostas
    1. Vou verificar novamente na lista. Tem algum item em específico a se verificar?

      abraço

      Excluir
    2. Eric,
      Verifique no sistema de permissão se as seguintes permissões estão ativadas:

      moodle/restore:restoretargetimport - Isso habilita o link de importação no painel de administração do curso.

      moodle/backup:backuptargetimport - Isso habilita importação de conteúdo dos cursos em que o usuário está inscrito.

      Excluir
    3. Estou ficando louco já...
      Ambas as permissões estão ativadas.

      OBS. para alguns professores estão funcionando a opção de importar, para outros não.. Para o Adm está funcionando.

      fiz um comparativo das permissões de uma professor q está funcionando a importação com um outro q não está. Em ambos as configurações estão iguais.

      Será q pode ser alguma coisa no curso?

      Valeu novamente.

      Excluir
  11. Lino, continuando a minha busca aqui no mooodle para resolver esse problema, encontrei em Home Page / Administração do site / Relatórios / Visão geral da segurança / Usuários confiáveis para XSS uma lista com todos os professores q não estão conseguindo fazer a importação.

    Será q pelo moodle estar identificando que eles são possíveis riscos o sistema não está deixando utilizar esse recurso?

    Tem como tirar os usuários dessa lita?

    Abraço

    ResponderExcluir
    Respostas
    1. Eric

      No meu Moodle, versão 2.2.2 os usuários que constam na lista:
      Administração do site / Relatórios / Visão geral da segurança / Usuários confiáveis para XSS
      conseguem efetuar importação de dados. Sendo assim, essa hipótese pode ser descartada. Mesmo assim, me informa qual versão do Moodle você está usando. Assim, vou fazer teste com a mesma versão que você está usando.

      A hipótese que julgo mais provável é a sobreposição de permissão. Para descartar essa hipótese, faça a seguinte averiguação:

      1) Faça levantamento do perfil dos usuários que não estão conseguindo importar conteúdo de outro curso. Verifique se esses usuários são admin, tutor etc.

      2) Faça levantamento do perfil dos usuários que estão conseguindo importar conteúdo de outro curso. Verifique se esses usuários são admin, tutor etc.

      3) Crie um novo usuário com perfil de admin e verifique se o link importar aparece no curso. Crie outros usuários e atribua diferentes perfis como autor do curso e tutor. Acesse com senha desses usuários virgens e veja se o link importar aparece ou não.

      4) Se o resultado do teste do item 3) for satisfatório para perfil admin e tutor, a hipótese a ser considerada é que os usuários levantados no item 1) tenham sobreposição de permissão, ou seja, podem estar com duplicidade de inscrição no curso com perfis diferentes. Essa hipótese pode ser averiguada via consulta direta no banco com comando SQL.

      5) Se o resultado de teste do item 3) não for satisfatório, a hipótese mais provável é que as permissões padrões do Moodle tenham sido alteradas. Neste caso, uma forma de eliminar essa hipótese é reconfigurar cada perfil padrão do Moodle para a configuração padrão original. Isso deve ser feita em Administração do site / ► Usuários / ► Permissões e selecionar cada opção de perfil. É rocomendado fazer esse procedimento em um ambiente de teste e não de produção.

      6) Se o item 5) não der resultado satisfatório, a hipótese de permissão deve ser descartada. A pesquisa deve focar em outras variáveis de configuração que podem influenciar no processo de importação.

      7) Se todas as possibilidades acima levantadas não surtiram efeito, o caminho é fazer uma investigação diretamente na camada de base de dados e no código php do Moodle.

      Excluir
    2. Badiu, fiz o seguinte teste.
      Peguei alguns perfil de professor e adicionei como sendo adm, e liberou os cursos para importar.

      Qual o sql, para verificar os diferentes perfis atribuídos a um professor.

      Excluir
  12. Badiu, bom dia.

    Vou fazer as etapas q vc me sugeriu!!!

    A versão que estou usando é
    $release = '2.2.1+ (Build: 20120119)';

    Abraço

    ResponderExcluir
  13. Boa tarde...

    Como eu estava encontrando vários problemas, fiz um teste fazendo a instalação do moodle e integrando ele ao sistema acadêmico novamente... PARA NOOOOOOOOOOOOOOSA ALEGRIAAAA... está funcionando.

    Provavelmente o problema realmente estava em sobreposição de direitos atribuído ao grupo professor.

    Não tenho como agradecer essa força q vc me deu.

    Forte abraço. e se precisar de algo q possa te ajudar estamos ai...

    Att.
    Eric

    ResponderExcluir
  14. Eric,
    Que bom que deu tudo certo. Qualquer coisa me dá um sinal.

    ResponderExcluir
  15. Badiu, no moodle 2.3, para criar um curso com várias seções, como deve ser estruturado co campo modinfo da tabela mdl_course? (Pois até onde sei a renderização das seções de um curso dependem do conteúdo desse campo)

    ResponderExcluir
    Respostas
    1. Consegui, bastava apenas especificar o campo numsections de mdl_course com o número de seções que vocÊ deseja criar para o curso e em seguida criar as seções em número correspodente. Porém o moodle sempre cria uma seçao extra a qual é direcionada para o módulo do Fórum de notícias.

      Excluir
    2. Valeu Renato,
      É isso mesmo a solução. Na tabela mdl_course o campo numsections define a quantidade de tópicos do curso.

      Excluir
  16. Badiu, Bom dia tudo bem?
    Você poderia me ajudar com minha dúvida?

    Estou utilizando o Moodle 2.3.2+ (Build: 20120914).
    Estou importando os Cursos do nosso sistema legado em Delphi para o Moodle, importei os cursos normalmente, mas quando entro num curso e aperto o botão "ativar edição" aparece a seguinte mensagem: "Não foi encontrada nenhum dado gravado na tabela de banco de dados course." O que pode ser?

    ResponderExcluir
  17. Só pra te situar melhor, no meu caso, Na tabela mdl_context, Estou criando contextos para os cursos de maneira que o contextlevel seja 50, o instanceid seja igual o id do curso na mdl_course, o path seja igual à sequencia dos ID's das categorias acima, com o último numero do path igual ao id do contexto. Por exemplo: 2/6/35/36/65 (tenho 4 níveis de categorias: Cidade, Entidade, Unidade, Área, mais o número 65 que é o id do contexto). E o campo depth = a quantidade de níveis do path que nesse caso foi 5. Tem algo errado?? Quando entro no curso aparece a mensagem: "Não foi encontrada nenhum dado gravado na tabela de banco de dados course." sombreada em vermelho. Agradeço sua atenção Badiu! Obrigado!!

    ResponderExcluir
    Respostas
    1. Júlio,
      A hipótese mais provável do erro que está ocorrendo é que ao criar o curso, alguma tabela não foi alimentada ou foi alimentada de forma incorreta. Não acredito que o erro esteja no campo depth. Ainda não mapiei o comando SQL para criar um curso na camada de base de dados na versão 2.x do Moodle. Como a verão 2.x ocorreu mudanças, certamente esse post não se aplica na família 2.x do Moodle.

      Sugiro que você adote o seguinte procedimento:

      1- Ative o erro do Moodle e tente ver em qual arquivo dá erro. Isso pode ser uma pista. Para ativar o debug, siga os passos no post: http://moodlephp.blogspot.com.br/2011/03/ativar-exibicao-do-erro-no-moodle.html

      2- Para mapear as tabelas que você deve usar para criar um curso, crie um curso teste no ambiente do Moodle pela interface gráfica. Após isso, vá na base de dados e mapeia em quais tabelas ocorreram INSERT para que o curso seja criado. A partir daí, revise o seu processo de SQL para gerar cursos.

      Excluir
    2. Blz Badiu!! Muito obrigado pela gentileza!!
      Vou verificar!! Valew!!

      Excluir
  18. Eu devo estar fazendo algo de errado com os contextos ou com as categorias por que não esta funcionando. Como deve ser a ordem no campo "PATH" da mdl_context ? no meu caso, tenho as categorias de cidades, dentro delas tenho as de unidades, e dentro das unidades, tenho as categorias de áreas, e só dentro das áreas que tenho os cursos, vinculados às categorias de áreas. Ficando o contexto de um curso igual a esse: [41 | 50 | 4 |'/1/2/5/26/41' | 5 ], onde 41 é o id do contexto, 50 é o context level, 4 é o ID do curso na mdl_course, '/1/2/5/26/41' é p path, que pelo que eu entendi representa a "descendência" desse curso, que esta dentro de uma categoria que esta dentro de outra, que esta dentro de outra etc..

    Será que devo retirar o numero 1 do início do "path" ? Acha que meu campo Path está errado BAdiu?? Me desculpe, é que eu já estou desistindo de tanto tentar e não dar certo. Valew pela força!!

    ResponderExcluir
    Respostas
    1. Júlio,

      No campo path da tabela mdl_context, o /1 é sempre o valor padrão. O valor '/1/2/5/26/41' que está no campo path, você precisa verificar o seguinte:
      26- Equivale a id do contexto da categoria em que o curso está vinculado
      5 – Id do contexto da categoria pai da categoria do curso.
      2 – Id do contexto da primeira categoria na nível de hierarquia

      Verifique se o campo depth está preenchido com o número referente em nível de hierarquia. Com esse '/1/2/5/26/41' valor no campo path o campo depth deve ficar com valor 5, ou seja, quinta posição na ordem de hierarquia.

      Excluir
  19. Badiu, bom dia...
    Estou com problemas aqui no moodle de nossa empresa.
    Usamos banco de dados SqlServer e, alguns cursos, após a inserção deles, quando queremos entrar no curso novamente, aparece a seguinte mensagem:

    Notice: unserialize() [function.unserialize]: Error at offset 25022 of 25026 bytes in /var/www/moodleteste/lib/modinfolib.php on line 245

    Notice: unserialize() [function.unserialize]: Error at offset 25022 of 25026 bytes in /var/www/moodleteste/lib/modinfolib.php on line 250
    Problem with "modinfo" data for this course
    line 253 of /lib/modinfolib.php: call to debugging()
    line 1260 of /lib/modinfolib.php: call to course_modinfo->__construct()
    line 1926 of /lib/navigationlib.php: call to get_fast_modinfo()
    line 1987 of /lib/navigationlib.php: call to global_navigation->generate_sections_and_activities()
    line 47 of /course/format/topics/lib.php: call to global_navigation->load_generic_course_sections()
    line 1901 of /lib/navigationlib.php: call to callback_topics_load_content()
    line 1255 of /lib/navigationlib.php: call to global_navigation->load_course_sections()
    line 3041 of /lib/navigationlib.php: call to global_navigation->initialise()
    line 781 of /lib/pagelib.php: call to navbar->has_items()
    line 3 of /theme/senaigo/layout/general.php: call to moodle_page->has_navbar()
    line 768 of /lib/outputrenderers.php: call to include()
    line 715 of /lib/outputrenderers.php: call to core_renderer->render_page_layout()
    line 232 of /course/view.php: call to core_renderer->header()

    Warning: array_slice() expects parameter 1 to be array, null given in /var/www/moodleteste/lib/navigationlib.php on line 1927

    Warning: Invalid argument supplied for foreach() in /var/www/moodleteste/lib/navigationlib.php on line 1930

    Warning: Invalid argument supplied for foreach() in /var/www/moodleteste/lib/navigationlib.php on line 2006

    o que pode ser isso?

    ResponderExcluir
    Respostas
    1. Fernando,

      Para investigar esse tipo de erro, me passa as seguintes informações:

      1- Esse erro acorre quanto você tenta acessar apenas um determinado curso ou qualquer curso?

      2- Qual é o url que está no navegador quando esse erro ocorre?

      3- Que alteração ocorreu na aplicação do Moodle, banco do Moodle e servidor do Moodle antes desse erro ocorrer?

      4- Ative a exibição de erro e veja a tela do erro vem mais detalhado. Para ativar o debug, siga instruções nesse link:
      http://moodlephp.blogspot.com.br/2011/03/ativar-exibicao-do-erro-no-moodle.html

      Ao ativar o erro, se a mensagem de erro for deferente, me envie.

      Excluir
    2. Olá Badiu, boa tarde.
      Me desculpe, mas somente hoje voltei ao post!
      Para resolver o problema, atualizamos a versão para 2.4+ e atualizamos algumas extensões do php para deixar o mais atualizado possível. Mexemos também na estrutura do apache para que o erro fosse corrigido. Mas mesmo assim, muito obrigado pelo retorno. Estou estudando muito essa parte de integração e se eu souber de mais alguma coisa para a versão 2.x vou postando aqui e ajudando aos colegas. Obrigado.

      Excluir
    3. Obrigado Badiu,

      Estava fazendo o select buscando só o instanceid na tabela mdl_context. Estava retornando um registro errado também faltava inserir o timestart.
      Tudo funcionando agora.
      Aproveitando, vou fazer uma instalação do Moodle 2.5 e pretendo integrar ao meu sistema também. Saberias dizer suas dicas para matrícula de alunos no 2.0 funciona do 2.5? E o restante (criar curso, etc) funciona também?

      Excluir
  20. Olá Badiu
    Estou com um problema para criar um curso via sql

    1º Passo:
    INSERT INTO mdl_course (category,fullname,shortname) VALUES ('46','Curso1','C1')
    Até aqui deu tudo certo. Utilizei 46 pois é uma categoria criada.

    Resumidamente a linha ficou:
    id category sortorder fullname shortname
    181 46 0 Curso1 C1

    2º Passo:
    INSERT INTO mdl_context (contextlevel,instanceid) VALUES ('50','181')

    Pelo que eu entendi essa instância é o id do curso, confere?

    Esse comando dá esse erro:
    #1062 - Duplicate entry '50-181' for key 'mdl_cont_conins_uix'

    Estou fazendo pelo phphmyadmin

    Minha versão do moodle
    2013051401.08
    2.5.1+

    Desde já agradeço pois aprendi várias coisas nesse blog

    Abraço

    ResponderExcluir
    Respostas
    1. Este comentário foi removido pelo autor.

      Excluir
    2. Estou com o mesmo erro, e tbm não sei se entendi bem a parte path='/1/3/10'...se entendi direito os valores '/1/3/10' são os indicadores das categorias acima certo? se conseguir resolver esta outra parte poste sua solução por favor.

      Excluir
  21. henriqueleitao@gmail.com19 de abril de 2014 às 12:05

    Badiu,
    Como vejo pelo SQL a agenda de um curso no Moodle 1.9?

    ResponderExcluir
    Respostas
    1. Oi Henrique,
      Não entendi bem a sua questão. O que você está referindo como agenda? São as atividades de um curso? Explique com mais detalhe a sua questão.

      Excluir
  22. Boa Noite Baidu, Estou usando a versão do moodle 2.6, realizei o insert na tabela de curso, contexto e sessão do curso conforme o seu tutorial, porém o curso não aparece no moodle, o mesmo só aparece caso eu edite a categoria na qual o curso está associado,teria alguma dica, ou o script para a versão 2.6?

    ResponderExcluir
    Respostas
    1. Milver,
      O comando de criar curso só foi testado na versão 1.9 do Moodle e não na versão 2.

      Você precisa criar um curso ou atividade de um curso? Me explica um pouco o que precisa para ver se há algum caminho alternativo.

      Excluir
  23. Cara... Muito obrigado.
    Estou precisando fazer uma replicação de dados e isso vai me poupar horas e horas de trabalho!

    ResponderExcluir