SuiteCRM 全功能,不限用户
SuiteCRM 与 Salesforce 和 Dynamics 一样强大,具有更高的技术独立性和定制性。业务咨询与服务,请联系:188-9654-1629
我们提供的服务包括:插件开发、主题开发、安装和配置、CRM升级、CRM部署、支持与维护、用户培训…
目录
- 介绍
- 文件位置
- 客制化
- 不同的元数据
- detailviewdefs.php
- templateMeta
- 面板
- editviewdefs.php
- listviewdefs.php
- popupdefs.php
- quickcreatedefs.php
- searchdefs.php
- subpaneldefs.php
- 子面板
- studio.php
- 代码示例
介绍
模块元数据用于描述各种视图在模块中的行为。此方法的主要用途是提供字段和布局信息,但也可以用于过滤子面板并描述搜索中使用的字段。
文件位置
模块元数据可以在以下位置找到:
modules/<TheModule>/metadata/
客制化
通常,studio是自定义元数据的最佳方法。即使您确实希望通过Studio无法进行自定义,也可以更轻松地先在Studio中进行所有设置。对于基于布局的元数据尤其如此。但是,如果您要自定义元数据,则就像在自定义目录中放置或编辑文件一样简单。
例如,覆盖客户的detailviewdefs(位于 modules/Accounts/metadata/detailviewdefs.php
),我们会将文件放置(或编辑)到 custom/modules/Accounts/metadata/detailviewdefs.php
。
该规则的一个例外是studio.php文件。模块元数据文件夹是唯一选中的位置 – 的任何版本 custom/modules/<TheModule>/metadata/studio.php
被忽略。
不同的元数据
detailviewdefs.php
detailviewdefs.php提供有关此模块的详细视图的布局和字段的信息。该文件使用与editviewdefs.php相同的结构。我们来看一个虚构模块的例子 ABC_Vehicles
:
<?php
$viewdefs ['ABC_Vehicles'] ['DetailView'] = array (
'templateMeta' => array (
'form' => array (
'buttons' => array (
'EDIT',
'DUPLICATE',
'DELETE',
'FIND_DUPLICATES'
)
),
'maxColumns' => '2',
'widths' => array (
array (
'label' => '10',
'field' => '30'
),
array (
'label' => '10',
'field' => '30'
)
),
'includes' => array (
array (
'file' => 'modules/ABC_Vehicles/ABC_VehiclesDetail.js'
)
)
),
'panels' => array (
'LBL_ABC_VEHICLES_INFO' => array (
array (
array (
'name' => 'name',
'comment' => 'The Name of the Vehicle',
'label' => 'LBL_NAME',
),
'reg_number'
),
array (
array (
'name' => 'type',
'label' => 'LBL_TYPE',
),
array (
'name' => 'phone_fax',
'comment' => 'The fax phone number of this company',
'label' => 'LBL_FAX'
)
),
array (
array (
'name' => 'registered_address_street',
'label' => 'LBL_REGISTERED_ADDRESS',
'type' => 'address',
'displayParams' => array (
'key' => 'registered'
)
),
),
),
'LBL_PANEL_ADVANCED' => array (
array (
array (
'name' => 'assigned_user_name',
'label' => 'LBL_ASSIGNED_TO'
),
array (
'name' => 'date_modified',
'label' => 'LBL_DATE_MODIFIED',
'customCode' => '{$fields.date_modified.value} '
+ '{$APP.LBL_BY} '
+ '{$fields.modified_by_name.value}',
)
),
),
)
);
?>
我们看到第二行定义了一个数组 $viewdefs['ABC_Vehicles']['DetailView']
它将模块ABC_Vehicles的DetailView条目放入 $viewdefs
(根据需要,DetailView将为EditView或QuickCreateView)。该数组有两个在此定义的主键:
templateMeta
templateMeta键通常提供有关视图的信息。['form']['buttons']
条目定义应在此视图中显示的按钮。
maxColumns
定义用于该视图的列数。大于2是不寻常的。
widths
一个数组,用于定义每列的标签和字段的宽度。
includes
要包含的其他JavaScript文件数组。这对于将自定义JavaScript行为添加到页面很有用。
面板
面板条目定义“详细信息”(或“编辑”)视图的实际布局。每个条目都是视图中的一个新面板,键是该面板的标签。我们可以在示例中看到有2个面板。一种使用语言字符串定义的标签LBL_ABC_VEHICLES_INFO
,其他用途 LBL_PANEL_ADVANCED
。
每个面板的每一行都有一个数组条目,每个数组都包含每一列的条目。例如,我们可以看到第一行具有以下定义:
array(
array (
'name' => 'name',
'comment' => 'The Name of the Vehicle',
'label' => 'LBL_NAME',
),
'reg_number',
),
它具有第一行第一列的数组定义和第一行第二列的字符串定义。字符串定义非常简单,仅显示该字段的详细信息视图(或进行适当编辑)。它将使用默认标签,类型等。在我们的示例中,我们显示名为 reg_number
。
第一行第一列的数组定义要复杂一些。每个数组定义必须有一个name
值。在我们的示例中,我们正在显示该name
字段。但是,我们还提供其他一些值。最常用的值是:
comment
用于说明该字段的目的。
label
此标签的语言键。如果无法识别语言键,则将使用此值(请参见 语言篇)。
displayParams
一个用于为字段显示传递额外参数的数组。对于这些选项及其用法,您可以在其中查看相应的字段类型include/SugarFields/Fields
要么 custom/include/SugarFields/Fields
。一个示例是设置文本区域的大小:
'displayParams' => array(
'rows' => 2,
'cols' => 30,
),
customCode
允许提供用于显示的自定义智能代码。此处的代码可以包含任何有效的smarty代码,并且还可以通过以下方式访问此视图中的当前字段$fields
。输出ID字段的示例是{$fields.id.value}
。此外,可以 分别通过$MOD
和访问模块标签和应用标签$APP
。最后你可以使用@@FIELD@@
输出将要使用的字段的值。例如 {if $someCondition}@@FIELD@@{/if}
将有条件地显示该字段。
editviewdefs.php
editviewdefs.php
提供有关此模块的编辑视图的布局和字段的信息。该文件使用与detailviewdefs.php相同的结构。请参阅detailviewdefs.php上的信息。
listviewdefs.php
的 listviewdefs.php
模块的文件定义了该模块的列表视图将显示的字段。让我们看一个例子:
$listViewDefs ['AOR_Reports'] =
array (
'NAME' =>
array (
'width' => '15%',
'label' => 'LBL_NAME',
'default' => true,
'link' => true,
),
'REPORT_MODULE' =>
array (
'type' => 'enum',
'default' => true,
'studio' => 'visible',
'label' => 'LBL_REPORT_MODULE',
'width' => '15%',
),
'ASSIGNED_USER_NAME' =>
array (
'width' => '15%',
'label' => 'LBL_ASSIGNED_TO_NAME',
'module' => 'Employees',
'id' => 'ASSIGNED_USER_ID',
'default' => true,
),
'DATE_ENTERED' =>
array (
'type' => 'datetime',
'label' => 'LBL_DATE_ENTERED',
'width' => '15%',
'default' => true,
),
'DATE_MODIFIED' =>
array (
'type' => 'datetime',
'label' => 'LBL_DATE_MODIFIED',
'width' => '15%',
'default' => true,
),
);
要定义列表视图的定义,我们只需在其中添加一个键 $listViewDefs
数组。在这种情况下,我们为AOR_Reports
该数组包含我们希望在列表视图中显示的每个字段的条目,并以该字段的大写字母作为关键字。例如, REPORT_MODULE
关键是指 report_module
AOR_Reports的字段。
type
字段的类型。这可用于覆盖字段的显示方式。
default
默认情况下是否应在列表视图中显示此字段。如果为false,则该字段将出现在studio的可用列列表中。
studio
此字段是否应在Studio中显示。这对于确保不删除关键字段很有用。
label
用于此字段的标签。如果未提供,则将使用该字段的默认标签。
width
列表视图中字段的宽度。请注意,尽管通常以百分比形式给出,但会将其视为比例。上面的示例有五列,宽度为,15%
但实际上是20%
因为这是一个比率。
popupdefs.php
popupdefs.php提供有关在选择相关记录时通常使用的模块弹出窗口的布局,字段和搜索选项的信息。
我们来看一下“客户反馈”模块的默认popupdefs.php: 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))
),
)
);
popupdefs.php指定一个 $popupMeta
具有以下键的数组:
moduleMain
该弹出窗口将显示的模块。
varName
用于存储搜索首选项等的变量名。这通常只是大写的模块名。
className
此模块的SugarBean的类名称。如果未提供,则moduleMain
将会被使用。只有类名和模块名不同的类(例如Cases)才真正需要这样做。
orderBy
记录列表的默认字段将被排序。
whereClauses
旧版选项。仅当没有searchdef时才用作备用。定义允许搜索的字段名称及其数据库表示形式。
listviewdefs
在弹出列表视图中显示的字段列表。看到 listviewdefs.php
。
searchdefs
可以在弹出窗口中搜索的字段数组。请参阅searchdefs.php部分中的各个搜索defs(例如,basic_search
数组)。
quickcreatedefs.php
quickcreatedefs.php
提供有关此模块快速创建视图的布局和字段的信息(这是从子面板创建记录时出现的视图)。该文件的结构与detailviewdefs.php
。请参阅以下信息 detailviewdefs.php
。
searchdefs.php
模块的搜索定义定义了该模块中搜索的外观和行为。
让我们来看一个例子。—— 搜索视图元数据定义
$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%'
)
)
)
);
在这里,我们为 Accounts
在里面 $searchdefs
数组。这有两个键:templateMeta
的 templateMeta
键控制搜索表单的基本外观。在这里,我们定义了一些总体布局信息,例如基本搜索的最大列数(3)和最大列数(4)。最后,我们为搜索字段及其标签设置宽度。layout
的 layout
键包含基本搜索和高级搜索的布局定义。这只是字段的数组定义列表。有关某些选项的说明,请参见listviewdefs.php上的部分。
subpaneldefs.php
subpaneldefs.php文件提供了出现在模块详细视图中的子面板的定义。让我们看一个例子: 子面板元数据定义
$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'
)
)
)
)
);
在上面的示例中,我们为模块设置了一个定义(在这种情况下, AOS_Quotes
) 在里面 $layout_defs
数组。这只有一个钥匙 subpanel_setup
这是由名称键控的每个子面板定义的数组。这个名字应该是可识别的。在上述情况下,它是子面板显示的链接字段的名称。每个子面板的条目通常具有以下定义:
order
用于对子面板进行排序的数字。这些值本身是任意的,并且仅相对于其他子面板使用。
module
该子面板将显示的模块。例如 aos_quotes_project
上面示例中的def将显示以下内容的列表 Project
记录。
subpanel_name
将使用显示的模块中的子面板。请参阅本章的子面板部分。
sort_by
用于对记录进行排序的字段。
sort_order
排序顺序 sort_by
领域。asc
为上升 desc
而下降。
title_key
用于此子面板标签的语言键。
get_subpanel_data
用于指定在何处检索子面板记录。通常,这只是当前模块的链接名称。在这种情况下,相关记录将显示在子面板中。但是,对于更复杂的链接,可以指定要调用的函数。指定功能时,应确保get_subpanel_data
条目采用以下形式 function:theFunctionName
。另外,您可以使用来指定函数的位置和所需的任何其他参数function_parameters
键。可以在下面找到使用功能的子面板的示例。
function_parameters
指定子面板的参数,该子面板从功能中获取信息(请参阅get_subpanel_data
)。这是一个数组,允许通过使用import_function_file
密钥(如果不存在,但是 get_subpanel_data
定义一个函数,然后将在Bean上为子面板的父级调用该函数)。另外,此数组将作为参数传递给在中定义的函数get_subpanel_data
允许将参数传递给函数。
generate_select
有关功能子面板(请参阅 get_subpanel_data
)函数是否将返回表示要使用的查询的数组(用于 generate_select = true
),或者是否只是返回查询以用作字符串。
get_distinct_data
是否仅返回不同的行。关系不允许多次链接两个记录,因此仅在子面板源是函数时才真正适用。看到get_subpanel_data
有关功能子面板源的信息。
top_buttons
允许定义按钮显示在子面板上。这只是按钮定义的数组。这些定义至少具有widget_class
定义,决定要在其中使用的按钮类 include/generic/SugarWidgets
。根据按钮的不同,此数组还可用于将额外的参数传递给小部件类。
子面板
元数据文件夹中是 subpanels
夹。这允许为不同的父模块创建不同的子面板布局。例如,“联系人”模块在客户子面板中的显示与在案例子面板中的显示将有所不同。里面的文件 subpanels
文件夹可以命名为任何名称。重要的是它可以在subpanel_name
的 subpaneldefs.php
父模块的 通常的子面板文件简称为 default.php
。让我们看一下 modules/Accounts/metadata/subpanels/default.php
文件: 模块子面板的定义
$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,
),
)
);
有三个键 $subpanel_layout
此子面板的变量。这些是:
top_buttons
定义将显示在子面板顶部的按钮。见top_buttons
键入 subpaneldefs.php
。
where
允许在where
子句中添加条件。例如,这可以用于排除已关闭的案例(cases.state != "Closed"
)或仅包含特定行业的客户(accounts.industry = "Media"
)。请注意,在这些示例中,我们指定了表以消除查询中的任何歧义。
list_fields
定义要在此子面板中显示的字段列表。请参阅以下部分listviewdefs.php
想要查询更多的信息。
您可以在SuiteCRM安装的文件中找到有关Subpanels实施的其他技术信息: include/ SubPanel / subpanels.txt
studio.php
studio.php是元数据中最简单的文件,它的存在仅用于确认是否应在studio中显示模块以供用户调整。
请注意,与其他元数据文件不同,该文件位于 modules/<TheModule>/metadata/studio.php
将是唯一选中的一项。文件在custom/modules/<TheModule>/metadata/studio.php
将无效。
代码示例
这是使用元数据设置功能子面板的示例。
在此示例中,cases模块具有一个自定义字段 incident_code_c
用于跟踪具有相同根本原因的案例。我们将添加一个子面板以显示所有具有相同条件的案例incident_code_c
。
最初,我们添加到 subpanel_setup
在“案例”部分创建以下文件 custom/Extension/modules/Cases/Ext/Layoutdefs/IncidentLayoutdefs.php
IncidentLayoutdefs.php
<?php
$layout_defs["Cases"]["subpanel_setup"]['incident_cases'] = array(
'module' => '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,
);
接下来,我们创建将定义我们的文件 get_cases_by_incident
功能 custom/modules/Cases/IncidentUtils.php
IncidentUtils.php
<?php
function get_cases_by_incident(){
global $db;
//Get the current bean
$bean = $GLOBALS['app']->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;
}