Introdução
Os metadados do módulo são usados ​​para descrever como várias visualizações se comportam no módulo. O principal uso disso é fornecer informações de campo e layout, mas também pode ser usado para filtrar subpainéis e descrever quais campos são usados ​​na pesquisa.

 

Localização
Os metadados do módulo podem ser encontrados em:

Exemplo 6.1: localização de metadados do módulo
modules / / metadata /

 

Customizando
Normalmente, o Studio é a melhor maneira de personalizar metadados. Mesmo quando você deseja fazer personalizações que não são possíveis através do estúdio, pode ser mais simples configurar tudo no estúdio primeiro.
Isso é particularmente verdadeiro para metadados baseados em layout.
No entanto, se você estiver personalizando metadados, é tão simples quanto colocar ou editar o arquivo no diretório personalizado.
Por exemplo, para substituir o detailviewdefs das contas (encontrado em modules / Accounts / metadata / detailviewdefs.php), colocaríamos (ou editaríamos) o arquivo em custom / modules / Accounts / metadata / detailviewdefs.php.
Uma exceção a essa regra é o arquivo studio.php. A pasta de metadados de módulos é o único local verificado – qualquer versão em custom / modules / /metadata/studio.php é ignorada.

 

 

Metadados diferentes

detailviewdefs.php
detailviewdefs.php fornece informações sobre o layout e os campos da visualização de detalhes para este módulo. Este arquivo usa a mesma estrutura que editviewdefs.php.
Vejamos um exemplo de um módulo fictício ABC_Vehicles:

Example 6.2: Visualização detalhada da definição de Metadata


Parte01

 


Parte02

 

Vemos que a linha 2 define um array $viewdefs [‘ABC_Vehicles’] [‘DetailView’] que coloca uma entrada DetailView para o módulo ABC_Vehicles em $ viewdefs (DetailView será EditView ou QuickCreateView conforme apropriado).
Este array possui duas chaves principais definidas aqui:

templateMeta
A chave templateMeta fornece informações sobre a visualização em geral. As entradas [‘form’] [‘botões’] definem os botões que devem aparecer nesta visualização.

maxColumns
Define o número de colunas a serem usadas para esta visualização. É incomum que seja mais do que 2.

widths
Uma matriz que define a largura do rótulo e do campo para cada coluna.

includes
Uma série de arquivos JavaScript adicionais a serem incluídos. Isso é útil para adicionar um comportamento JavaScript personalizado à página.

 

 

Panels
A entrada de painéis define o layout real da visualização Detalhe (ou Editar). Cada entrada é um novo painel na visualização, com a chave sendo o rótulo desse painel. Podemos ver em nosso exemplo que temos 2 painéis. Um usa o rótulo definido pela string de idioma LBL_ABC_VEHICLES_INFO, o outro usa LBL_PANEL_ADVANCED.

Cada painel possui uma entrada de array para cada linha, com cada array contendo uma entrada para cada coluna. Por exemplo, podemos ver que a primeira linha tem a seguinte definição:

Exemplo 6.3: definição de linha de metadados DetailView

array (
  array (
     'nome' => 'nome',
     'comment' => 'O nome do veículo',
     'label' => 'LBL_NAME',
  ),
  'reg_number',
),

Este possui uma definição de array para a primeira linha, primeira coluna e uma definição de string para a primeira linha, segunda coluna. A definição da string é muito direta e simplesmente exibe a visualização de detalhes (ou edição, conforme apropriado) para aquele campo. Ele usará o rótulo, tipo, etc. padrão. Em nosso exemplo, estamos exibindo o campo denominado reg_number.

A definição do array para a primeira linha, primeira coluna é um pouco mais complexa. Cada definição de array deve ter um valor de nome. Em nosso exemplo, estamos exibindo o campo de nome. No entanto, também fornecemos alguns outros valores. Os valores mais comumente usados ​​são:

Comment
Usado para observar o propósito do campo.

label
A chave de idioma para este rótulo. Se a chave do idioma não for reconhecida, este valor será usado em seu lugar (consulte o capítulo sobre idioma).

displayParams
Uma matriz usada para passar argumentos extras para a exibição do campo. Para as opções e como elas são usadas, você pode dar uma olhada no tipo de campo apropriado em include / SugarFields / Fields ou custom / include / SugarFields / Fields. Um exemplo é definir o tamanho de uma área de texto:

Exemplo 6.4: DisplayParams de metadados de DetailView

'displayParams' => array (
    'linhas' => 2,
    'cols' => 30,
),

Customcode
Permite o fornecimento de código inteligente personalizado para ser usado para a exibição. O código aqui pode incluir qualquer código Smarty válido e isso também terá acesso aos campos atuais nesta visualização por meio de $ fields. Um exemplo de saída do campo ID seria {$ fields.id.value}.
Além disso, os rótulos dos módulos e dos aplicativos podem ser acessados ​​por meio de $ MOD e $ APP, respectivamente. Finalmente, você pode usar @@ FIELD @@ para gerar o valor do campo que teria sido usado. Por exemplo, {if $ someCondition} @@ FIELD @@ {/ if} mostrará condicionalmente o campo.

editviewdefs.php
editviewdefs.php fornece informações sobre o layout e os campos da visualização de edição para este módulo. Este arquivo usa a mesma estrutura que detailviewdefs.php. Por favor, consulte as informações em detailviewdefs.php.

listviewdefs.php
O arquivo listviewdefs.php para um módulo define quais campos a visualização de lista desse módulo exibirá. Vamos dar uma olhada em um exemplo:

Exemplo 6.5: definição de metadados ListView

$listViewDefs ['AOR_Reports'] = 
array (   'NOME' =>   
  array (     
  'width' => '15% ',     
   'label' => 'LBL_NAME',     
   'default' => verdadeiro,     
   'link' => verdadeiro,   
),   
'REPORT_MODULE' =>   
   array (     
   'type' => 'enum',     
   'default' => verdadeiro,     
   'studio' => 'visible',     
   'rótulo' => 'LBL_REPORT_MODULE',     
   'width' => '15% ',   
),   
'ASSIGNED_USER_NAME' =>   
   array (     
   'largura' => '15% ',     
   'label' => 'LBL_ASSIGNED_TO_NAME',    
   'módulo' => 'Funcionários',     
   'id' => 'ASSIGNED_USER_ID',     
   'default' => verdadeiro,   
),   'DATE_ENTERED' =>   
   array (     
   'type' => 'datetime',     
   'label' => 'LBL_DATE_ENTERED',     
   'largura' => '15% ',     
   'default' => verdadeiro,   
),   'DATE_MODIFIED' =>   
   array (     
   'type' => 'datetime',     
   'rótulo' => 'LBL_DATE_MODIFIED',     
   'largura' => '15% ',    
   'default' => verdadeiro,   
 ), 
);

Para definir as defs de visualização de lista, simplesmente adicionamos uma chave ao array $ listViewDefs.
Neste caso, adicionamos uma entrada para AOR_Reports. Este array contém uma entrada para cada campo que desejamos mostrar na visualização de lista e é codificado pelo nome em maiúsculas do campo.
Por exemplo, a chave REPORT_MODULE se refere ao campo report_module de AOR_Reports.

type
O tipo do campo. Isso pode ser usado para substituir como um campo é exibido.

default
Se este campo deve ser mostrado na visualização de lista por padrão. Se for falso, o campo aparecerá na lista de colunas disponíveis no Studio.

studio
Se este campo deve ou não ser exibido no estúdio. Isso pode ser útil para garantir que um campo crítico não seja removido.

label
O rótulo a ser usado para este campo. Se não for fornecido, o rótulo padrão para esse campo será usado.

width
A largura do campo na visualização de lista. Observe que, embora isso geralmente seja dado como uma porcentagem, é tratado como uma proporção.
O exemplo acima tem cinco colunas com largura de 15%, mas na verdade serão 20%, pois é uma proporção.

popupdefs.php
popupdefs.php fornece informações sobre o layout, campos e opções de pesquisa do pop-up do módulo que geralmente é usado ao selecionar um registro relacionado.
Vejamos o popupdefs.php padrão para o módulo Contas:

Exemplo 6.6: definição de metadados PopupView

$popupMeta = array(
   'moduleMain' => 'Case',
   'varName' => 'CASE',
   'className' => 'aCase',
   'orderBy' => 'name',
   'whereClauses' =>
       array('name' => 'cases.name',
               'case_number' => 'cases.case_number',
               'account_name' => 'accounts.name'),
   'listviewdefs' => array(
       'CASE_NUMBER' => array(
           'width' => '5',
           'label' => 'LBL_LIST_NUMBER',
           'default' => true),
       'NAME' => array(
           'width' => '35',
           'label' => 'LBL_LIST_SUBJECT',
           'link' => true,
           'default' => true),
       'ACCOUNT_NAME' => array(
           'width' => '25',
           'label' => 'LBL_LIST_ACCOUNT_NAME',
           'module' => 'Accounts',
           'id' => 'ACCOUNT_ID',
           'link' => true,
           'default' => true,
           'ACLTag' => 'ACCOUNT',
           'related_fields' => array('account_id')),
       'PRIORITY' => array(
           'width' => '8',
           'label' => 'LBL_LIST_PRIORITY',
           'default' => true),
       'STATUS' => array(
           'width' => '8',
           'label' => 'LBL_LIST_STATUS',
           'default' => true),
       'ASSIGNED_USER_NAME' => array(
           'width' => '2',
           'label' => 'LBL_LIST_ASSIGNED_USER',
           'default' => true,
          ),
       ),
   'searchdefs'   => array(
       'case_number',
       'name',
       array(
           'name' => 'account_name',
           'displayParams' => array(
               'hideButtons'=>'true',
               'size'=>30,
               'class'=>'sqsEnabled sqsNoAutofill'
           )
       ),
       'priority',
       'status',
       array(
           'name' => 'assigned_user_id',
           'type' => 'enum',
           'label' => 'LBL_ASSIGNED_TO',
           'function' => array(
               'name' => 'get_user_array',
               'params' => array(false))
           ),
     )
 );

O popupdefs.php especifica uma matriz $ popupMeta com as seguintes chaves:

moduleMain
O módulo que será exibido por este pop-up.

varName
O nome da variável usado para armazenar as preferências de pesquisa, etc. Normalmente, será simplesmente o nome do módulo em maiúsculas.

classname
O nome da classe do SugarBean para este módulo. Se não for fornecido, moduleMain será usado. Isso só é realmente necessário para classes em que o nome da classe e o nome do módulo são diferentes (como casos).

orderBy
O campo padrão pelo qual a lista de registros será classificada.

whereClauses
Opção de legado. Isso só é usado como fallback quando não há searchdefs. Define os nomes dos campos para permitir a pesquisa e sua representação no banco de dados.

listviewdefs
A lista de campos exibidos na visualização de lista pop-up. Veja listviewdefs.php.

searchdefs
Uma matriz dos campos que devem estar disponíveis para pesquisa no pop-up. Veja as defs de pesquisa individuais na seção searchdefs.php (por exemplo, o array basic_search).

quickcreatedefs.php
quickcreatedefs.php fornece informações sobre o layout e os campos da visualização de criação rápida para este módulo (esta é a visualização que aparece ao criar um registro de um subpainel). Este arquivo usa a mesma estrutura que detailviewdefs.php. Por favor, consulte as informações em detailviewdefs.php.

searchdefs.php
As defs de pesquisa de um módulo definem como a pesquisa nesse módulo se parece e se comporta. Vejamos um exemplo.

Exemplo 6.7: Definição de metadados da Visualização de Pesquisa

$searchdefs ['Accounts'] = array (
      'templateMeta' => array (
          'maxColumns' => '3',
          'maxColumnsBasic' => '4',
          'widths' => array (
              'label' => '10',
              'field' => '30'
          )
      ),
      'layout' => array (
          'basic_search' => array (
              'name' => array (
                  'name' => 'name',
                  'default' => true,
                  'width' => '10%'
              ),
              'current_user_only' => array (
                  'name' => 'current_user_only',
                  'label' => 'LBL_CURRENT_USER_FILTER',
                  'type' => 'bool',
                  'default' => true,
                  'width' => '10%'
              )
          )
          ,
          'advanced_search' => array (
              'name' => array (
                  'name' => 'name',
                  'default' => true,
                  'width' => '10%'
              ),
              'website' => array (
                  'name' => 'website',
                  'default' => true,
                  'width' => '10%'
              ),
              'phone' => array (
                  'name' => 'phone',
                  'label' => 'LBL_ANY_PHONE',
                  'type' => 'name',
                  'default' => true,
                  'width' => '10%'
              ),
              'email' => array (
                  'name' => 'email',
                  'label' => 'LBL_ANY_EMAIL',
                  'type' => 'name',
                  'default' => true,
                  'width' => '10%'
              ),
              'address_street' => array (
                  'name' => 'address_street',
                  'label' => 'LBL_ANY_ADDRESS',
                  'type' => 'name',
                  'default' => true,
                  'width' => '10%'
              ),
              'address_city' => array (
                  'name' => 'address_city',
                  'label' => 'LBL_CITY',
                  'type' => 'name',
                  'default' => true,
                  'width' => '10%'
              ),
              'address_state' => array (
                  'name' => 'address_state',
                  'label' => 'LBL_STATE',
                  'type' => 'name',
                  'default' => true,
                  'width' => '10%'
              ),
              'address_postalcode' => array (
                  'name' => 'address_postalcode',
                  'label' => 'LBL_POSTAL_CODE',
                  'type' => 'name',
                  'default' => true,
                  'width' => '10%'
              ),
              'billing_address_country' => array (
                  'name' => 'billing_address_country',
                  'label' => 'LBL_COUNTRY',
                  'type' => 'name',
                  'options' => 'countries_dom',
                  'default' => true,
                  'width' => '10%'
              ),
              'account_type' => array (
                  'name' => 'account_type',
                  'default' => true,
                  'width' => '10%'
              ),
              'industry' => array (
                  'name' => 'industry',
                  'default' => true,
                  'width' => '10%'
              ),
              'assigned_user_id' => array (
                  'name' => 'assigned_user_id',
                  'type' => 'enum',
                  'label' => 'LBL_ASSIGNED_TO',
                  'function' => array (
                      'name' => 'get_user_array',
                      'params' => array (
                         0 => false
                      )
                  ),
                  'default' => true,
                  'width' => '10%'
             )
         )
     )
 );

Aqui, configuramos um novo array para contas no array $ searchdefs.
Isso tem duas chaves:

templateMeta
A chave templateMeta controla a aparência básica dos formulários de pesquisa. Aqui definimos algumas informações gerais de layout, como o máximo de colunas (3) e o número máximo de colunas para a pesquisa básica (4). Por fim, definimos as larguras dos campos de pesquisa e seus rótulos.

layout
A chave de layout contém as definições de layout para a pesquisa básica e pesquisa avançada. Esta é simplesmente uma lista de definições de array dos campos. Veja a seção em listviewdefs.php para uma descrição de algumas das opções.

subpaneldefs.php
O arquivo subpaneldefs.php fornece definições para os subpainéis que aparecem na visualização de detalhes de um módulo. Vejamos um exemplo:

Exemplo 6.8: definição de metadados de subpainel

$layout_defs['AOS_Quotes'] = array (
   'subpanel_setup' => array (
       'aos_quotes_aos_contracts' => array (
           'order' => 100,
           'module' => 'AOS_Contracts',
           'subpanel_name' => 'default',
           'sort_order' => 'asc',
           'sort_by' => 'id',
           'title_key' => 'AOS_Contracts',
           'get_subpanel_data' => 'aos_quotes_aos_contracts',
           'top_buttons' => array (
               0 => array (
                   'widget_class' => 'SubPanelTopCreateButton'
               ),
               1 => array (
                   'widget_class' => 'SubPanelTopSelectButton',
                   'popup_module' => 'AOS_Contracts',
                   'mode' => 'MultiSelect'
               )
           )
       ),
       'aos_quotes_aos_invoices' => array (
           'order' => 100,
           'module' => 'AOS_Invoices',
           'subpanel_name' => 'default',
           'sort_order' => 'asc',
           'sort_by' => 'id',
           'title_key' => 'AOS_Invoices',
           'get_subpanel_data' => 'aos_quotes_aos_invoices',
           'top_buttons' => array (
               0 => array (
                   'widget_class' => 'SubPanelTopCreateButton'
               ),
               1 => array (
                   'widget_class' => 'SubPanelTopSelectButton',
                   'popup_module' => 'AOS_Invoices',
                   'mode' => 'MultiSelect'
               )
           )
       ),
       'aos_quotes_project' => array (
           'order' => 100,
           'module' => 'Project',
           'subpanel_name' => 'default',
           'sort_order' => 'asc',
           'sort_by' => 'id',
           'title_key' => 'Project',
           'get_subpanel_data' => 'aos_quotes_project',
           'top_buttons' => array (
               0 => array (
                   'widget_class' => 'SubPanelTopCreateButton'
               ),
               1 => array (
                   'widget_class' => 'SubPanelTopSelectButton',
                   'popup_module' => 'Accounts',
                   'mode' => 'MultiSelect'
               )
           )
       )
    )
 );

No exemplo acima, configuramos uma definição para um módulo (neste caso AOS_Quotes) no array $ layout_defs. Ele tem uma única chave subpanel_setup que é uma matriz de cada uma das definições de subpainel codificadas por um nome. Este nome deve ser algo reconhecível. No caso acima, é o nome do campo do link exibido pelo subpainel.
A entrada para cada subpainel geralmente tem o seguinte definido:

order
Um número usado para classificar os subpainéis. Os próprios valores são arbitrários e usados ​​apenas em relação a outros subpainéis.

module
O módulo que será exibido por este subpainel. Por exemplo, o defeito aos_quotes_project no exemplo acima exibirá uma lista de registros do Projeto.

subpanel_name
O subpainel do módulo exibido que será usado. Consulte a seção de subpainéis deste capítulo.

orderBy
O campo para classificar os registros.

sort_by
A ordem na qual classificar o campo sort_by. asc para ascendente descida para descendente.

title_key
A chave de idioma a ser usada para o rótulo deste subpainel.

get_subpanel_data
Usado para especificar onde recuperar os registros do subpainel. Normalmente, é apenas um nome de link para o módulo atual. Neste caso, os registros relacionados serão exibidos no subpainel. No entanto, para links mais complexos, é possível especificar uma função a ser chamada. Ao especificar uma função, você deve garantir que a entrada get_subpanel_data esteja no formato function: theFunctionName. Além disso, você pode especificar a localização da função e quaisquer parâmetros adicionais necessários usando a chave function_parameters. Um exemplo de um subpainel que usa uma função pode ser encontrado abaixo.

function_parameters
Especifica os parâmetros para um subpainel que obtém as informações de uma função (consulte get_subpanel_data). Este é um array que permite especificar onde a função está usando a chave import_function_file (se estiver ausente, mas get_subpanel_data define uma função, então a função será chamada no bean para o pai do subpainel). Além disso, este array será passado como um argumento para a função definida em get_subpanel_data que permite passar argumentos para a função.

generate_select
Para subpainéis de função (consulte get_subpanel_data) se a função retornará ou não uma matriz que representa a consulta a ser usada (para generate_select = true) ou se simplesmente retornará a consulta a ser usada como string.

get_distinct_data
Se deve ou não retornar apenas linhas distintas. Os relacionamentos não permitem vincular dois registros mais de uma vez, portanto, isso só se aplica realmente se a origem do subpainel for uma função. Vejo get_subpanel_data para obter informações sobre as fontes de subpainéis de função.

top_buttons
Permite definir os botões que aparecem no subpainel. Esta é simplesmente uma matriz de definições de botão. Essas definições têm, pelo menos, o widget_class definido que decide a classe do botão a ser usado em include / generic / SugarWidgets. Dependendo do botão, esse array também pode ser usado para passar argumentos extras para a classe do widget.

 

 

Subpainéis
Dentro da pasta de metadados está a pasta de subpainéis. Isso permite a criação de diferentes layouts de subpainéis para diferentes módulos pai. Por exemplo, o módulo Contatos será exibido de forma diferente no subpainel de uma conta e no subpainel de um caso. Os arquivos dentro da pasta de subpainéis podem ter qualquer nome. Tudo o que importa é que ele pode ser referenciado no subpanel_name do subpaneldefs.php do módulo pai. O arquivo de subpainel usual é simplesmente denominado default.php. Vejamos o arquivo modules / Accounts / metadata / subpanels / default.php

Exemplo 6.8: Definição de subpainéis de módulo

$subpanel_layout = array(
   'top_buttons' => array(
       array(
           'widget_class' => 'SubPanelTopCreateButton'
       ),
       array(
           'widget_class' => 'SubPanelTopSelectButton',
           'popup_module' => 'Accounts'
       ),
   ),
   'where' => '',
   'list_fields' => array (
     'name' =>
     array (
      'vname' => 'LBL_LIST_ACCOUNT_NAME',
      'widget_class' => 'SubPanelDetailViewLink',
      'width' => '45%',
      'default' => true,
     ),
     'billing_address_city' =>
     array (
       'vname' => 'LBL_LIST_CITY',
       'width' => '20%',
       'default' => true,
     ),
     'billing_address_country' =>
     array (
       'type' => 'varchar',
       'vname' => 'LBL_BILLING_ADDRESS_COUNTRY',
       'width' => '7%',
       'default' => true,
     ),
     'phone_office' =>
     array (
       'vname' => 'LBL_LIST_PHONE',
       'width' => '20%',
       'default' => true,
     ),
     'edit_button' =>
     array (
       'vname' => 'LBL_EDIT_BUTTON',
       'widget_class' => 'SubPanelEditButton',
       'width' => '4%',
       'default' => true,
     ),
     'remove_button' =>
     array (
       'vname' => 'LBL_REMOVE',
       'widget_class' => 'SubPanelRemoveButtonAccount',
       'width' => '4%',
       'default' => true,
     ),
   )
 );

Existem três chaves na variável $subpanel_layout para este subpainel.
Esses são:

top_buttons
Define os botões que aparecerão na parte superior do subpainel. Veja a chave top_buttons em subpaneldefs.php.

where
Permite a adição de condições à cláusula where. Por exemplo, isso pode ser usado para excluir casos que são encerrados (cases.state! = “Encerrados”) ou incluir apenas contas de um setor específico (accounts.industry = “Media”). Observe que, nesses exemplos, especificamos a tabela para remover qualquer ambigüidade na consulta.

list_fields
Define a lista de campos a serem exibidos neste subpainel. Consulte a seção em listviewdefs.php para obter mais informações.

studio.php
studio.php é o arquivo mais simples em metadados e sua existência é simplesmente usado para confirmar se um módulo deve ser mostrado no studio para ajustes do usuário. Observe que, ao contrário de outros arquivos de metadados, o arquivo em modules / /metadata/studio.php será o único verificado. Um arquivo em custom / modules / /metadata/studio.php não terá efeito.

 

Exemplo de Código
Este é um exemplo de configuração de um subpainel de função usando Metadados.

Neste exemplo, o módulo de casos tem um campo personalizado incidente_code_c que é usado para rastrear casos com a mesma causa raiz. Adicionaremos um subpainel para mostrar todos os casos que têm o mesmo incidente_code_c.

Inicialmente, adicionamos à seção subpanel_setup de Casos criando o seguinte arquivo em custom / Extension / modules / Cases / Ext / Layoutdefs / IncidentLayoutdefs.php

Exemplo A.1: IncidentLayoutdefs.php

'Cases',
    'title_key' => 'LBL_INCIDENT_CASES',
    'subpanel_name' => 'default',
    'get_subpanel_data' => 'function:get_cases_by_incident',
    'function_parameters' =>
            array('import_function_file' => 'custom/modules/Cases/IncidentUtils.php',),
            "generate_select" => true,
 );

Em seguida, criamos o arquivo que definirá nossa função get_cases_by_incident custom / modules / Cases / IncidentUtils.php.

Exemplo A.2: IncidentUtils.php

controller->bean;
          $incidentCode = $db->quote($bean->incident_code_c);
          //Create the SQL array
          $ret = array();
          $ret['select'] = ' SELECT id FROM cases ';
          $ret['from'] = ' FROM cases ';
          $ret['join'] = "";
          //Get all cases where the incident code matches but exclude the current case.
          $ret['where']="WHERE cases.deleted = 0 AND cases_cstm.incident_code_c = '{$incidentCode}' AND cases.id != '{$bean->id}'";
          return $ret;
 }