One of the great features of SugarCRM is its extensibility and one way to utilize that extensibility is by creating modules. Modules are generally developed to meet a business need such as the functionality provided by forums, teams or social media integrations.  

Manifest

There are three main arrays in the manifest.php file; $manifest, $installdefs, and $upgrade_manifest.

$manifest

1
$manifest = array(

acceptable_sugar_flavors

Defines which editions of SugarCRM that the package can be installed on. Acceptable values are : CE, PRO, CORP, ULT and ENT Example:

1
2
3
‘acceptable_sugar_flavors’ => array(
    ‘CE’, ‘PRO’, ‘CORP’ , 'ULT’, ‘ENT’
),

acceptable_sugar_versions

Defines which versions of SugarCRM that the package is supported on. There are two options for matching versions; exact_matches or regex_matches. Example:

1
2
3
4
5
‘acceptable_sugar_versions’ =>  array (
    ‘exact_matches’ => array (
      ‘5.5.0’, ‘5.5.1a’
    ),
),

OR:

1
2
3
4
5
‘acceptable_sugar_versions’ =>  array (
    ‘regex_matches’ => array (
      ‘5\.5\.0*’,
    ),
),

readme

(Optional) The Module Builder will allow the author to set a README text within a text box to be displayed during installation. If this is desired for a hand built package instead create a README.txt in the root directory of the zip and the installer will pick it up and display it. Example:

1
‘readme’ => ‘Please make sure to visit our documentation at…’,

key

(Optional) The Module Builder will force the author to define a key so that the module will not conflict with other similar modules. For example, there may be multiple twitter modules out there that. To avoid stepping on toes (such as overwritting the modules/Twitter/.. directory) a key can be used to help ensure uniqueness. For example ‘crmstage’ could be used which would create the module directory and tables with a crmstage_prefix (modules/crmstage_Twitter). Example:

1
‘key’ => ‘crmstage’,

author The author(s) who created the package. Example:

1
‘author’ => ‘CRMStage’,

description

(Optional) A short description of the package. Example:

1
‘description’ => ‘Yet another Twitter module,

icon

(Optional) An icon that will be displayed during installation. Example:

1
‘icon’ => ‘/icon/CRMStage.png’,

is_uninstallable

Defines whether the package can be uninstalled. It is highly suggested that any module be uninstallable. Example:

1
‘is_uninstallable’ => true,

name

Name of the package. This will be displayed both during the installation and also on the Module Loader list. Example:

1
‘name’ => ‘Twitter Module’,

published_date

The date that the package was created and published. Example:

1
‘published_date’ => ‘2010/01/04’,

type

The package type. Accepted values include: langpack, module, patch, full, and theme.

  • langpack

* Packages of type langpack will be automatically added to the “Language” dropdown on the Sugar Login screen. They are installed using the Upgrade Wizard.

  • module

* Packages of type module are installed using the Module Loader.

  • patch

* Packages of type patch are installed using the Upgrade Wizard.

  • theme

* Packages of type theme will be automatically added to the “Theme” dropdown on the Sugar Login screen. They are installed using the Upgrade Wizard. Example:

1
‘type’ => ‘module’,

version

The version of the package. This can be any combination of alphanumeric characters. Example:

1
‘version’ => ‘2.5’,

remove_tables

(Optional) By default the uninstaller will assume this to be set to ‘true’. If the user should be allowed to choose whether to remove the database tables or not ‘prompt’ should be used. This is suggested to help avoid accidental data loss. Example:

1
‘remove_tables’ => ‘prompt’,

dependencies

(Optional) An array that defines what modules need to be installed before the current package can be installed. Example:

1
2
3
4
5
6
‘dependencies’ => array(
    array(
      ‘id_name’ => ‘twitter_helper’,
      ‘version’ => ‘1.0’
    ),
),

Closing the $manifest array );

Additional Notes

Similar to the README.txt mentioned above a license can be displayed by dropping a LICENSE.txt file into the root zip directory. The license will be displayed during installation and will force the installer to choose whether to accept the license or not. Choosing to not accept the license will cause the installation to abort. $installdefs

1
$installdefs= array(

Closing the $installdefs array );

id

The name of the module. This MUST be unique. Example:  

1
‘id’            => ‘Twitter’,

image_dir

The path to the images that should be added to the default theme directory. These images may include module icons, etc. Example:

1
‘image_dir’        => ‘/images’,

beans

An array of Sugar Beans included as part of the module. * module: The module’s name * class: The name of the class defined in the bean file * path: The path containing the bean’s definition (the file that extends the core SugarBean.php) * tab: Determines whether a tab should be created for the module Example:

1
2
3
4
5
6
7
8
‘beans’ => array(
    array(
      ‘module’      => ‘Twitter’,
      class’        => ‘Twitter’,
      ‘path’        => ‘modules/Twitter/Twitter.php’,
      ‘tab’        => true,
    )
),

copy

Used to define what files or directories to copy. Generally these are the core files to the module. This may also be used for copying over include files, libraries, etc. Example:

1
2
3
4
5
6
copy’ => array(
    array(
    ‘from’        => ‘/modules/Twitter’,
    ‘to’          => ‘modules/Twitter’,
    ),
),

mkdir

Used to define what files or directories to copy. Generally these are the core files to the module. This may also be used for copying over include files, libraries, etc. Example:

1
2
3
mkdir’ => array(
    ‘/cache/twitter/images/’,
),

schedulers

From sugar version 6.3+ you can install a scheduler job via manifest. copy a file Example:

1
2
3
4
array(
          'from' => '<basepath>/custom/Extension/application/Ext/ScheduledTasks/myscheduler.php',
          'to' => 'custom/Extension/application/Ext/ScheduledTasks/myscheduler.php',
      ),

 

language

Defines the display text for various labels for specific modules or for the application as a whole. Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
‘language’ => array(
      /** ENGLISH en_us */
      array(
        ‘from’          => ‘/language/application/en_us.twitteradmin.php’,
        ‘to_module’      => ‘application’,
        ‘language’      => ‘en_us’
      ),
      array(
        ‘from’        => ‘/language/modules/Administration/en_us.twitteradmin.php’,
        ‘to_module’    => ‘Administration’,
        ‘language’      => ‘en_us’
      ),
      array(
        ‘from’        => ‘/language/modules/Contacts/en_us.twitter.php’,
        ‘to_module’      => ‘Contacts’,
        ‘language’      => ‘en_us’
      ),
      /** END ENGLISH en_us */
      /** SPANISH es_es */
      array(
        ‘from’          => ‘/language/application/es_es.twitteradmin.php’,
        ‘to_module’      => ‘application’,
        ‘language’      => ‘es_es’
      ),
      array(
        ‘from’        => ‘/language/modules/Administration/es_es.twitteradmin.php’,
        ‘to_module’    => ‘Administration’,
        ‘language’      => ‘es_es’
      ),
      array(
        ‘from’        => ‘/language/modules/Contacts/es_es.twitter.php’,
        ‘to_module’      => ‘Contacts’,
        ‘language’      => ‘es_es’
      ),
      /** END SPANISH es_es */
  ),

menu

Custom menu links can be defined and added to any module with the menu array. Example:

1
2
3
4
5
6
‘menu’ => array (
    array(
      ‘from’        => ‘/menu/modules/Twitter/menu.php’,
      ‘to_module’    => ‘Twitter’
    )
),

dashlets

Add any custom dashlets that need to be installed to this array. Example:  

1
2
3
4
5
6
‘dashlets’ => array (
     array(
       ‘from’        => ‘/dashlets/modules/Twitter/TwitterDashlet/’,
       ‘name’        => ‘TwitterDashlet’
     )
 ),

layoutdefs

Used to define customized subpanel layouts for modules. Add, remove, or reorder subpanels with this array. Example:

1
2
3
4
5
6
‘layoutdefs’ => array(
    array(
      ‘from’        => ‘/layoutdefs/modules/Contacts/twitter_contacts_layoutdefs.php’,
      ‘to_module’    => ‘Contacts’,
    ),
),

vardefs

Although any custom field may be defined in these files they are generally used to define non-database custom fields such as those of type link or those that are meant for display only info such as calculated fields or data from external systems. Example:

1
2
3
4
5
6
‘vardefs’ => array(
    array(
      ‘from’        => ‘/vardefs/modules/Contacts/twitter_contacts_vardefs.php’,
      ‘to_module’    => ‘Contacts’,
    ),
),

administration

The array holds definition files for adding link options to the Admin page. Example:

1
2
3
4
5
‘administration’ => array(
    array(
      ‘from’        => ‘/administration/twitter_adminoption.php’,
    ),
),

relationships

Here is where any relationships between the custom module and any other module is defined. The module and meta_data indexes are required. Example:

1
2
3
4
5
6
7
8
‘relationships’ => array(
    array(
      ‘module’      => ‘Contacts’,
      ‘meta_data’    => ‘/relationships/modules/Contacts/twitter_contacts_metadata.php’,
      ‘module_vardefs’  => ‘/relationships/modules/Contacts/twitter_contacts_vardefs.php’,
      ‘module_layoutdefs’ => ‘/relationships/modules/Contacts/twitter_contacts_layoutdefs.php’
    ),
),

custom_fields

Generally used to add custom fields to existing modules. * name: The internal name of your custom field. Note that your custom field will be referred to as _c, as “_c” indicates a custom field. * label: The visible label of your custom field * type: The type of custom field. Accepted values include text, textarea, double, float, int, date, bool, enum, and relate. * max_size: The custom field’s maximum character storage size * require_option: Used to mark custom fields are either required or option. Accepted values include optional and required. * default_value: Used to specify a default value for your custom field * ext1: Used to specify a dropdown name (only applicable to enum type custom fields) * ext2: Unused * ext3: Unused * audited: Used to denote whether or not the custom field should be audited. Accepted values include 0 and 1. * module: Used to specify the module where the custom field will be added. Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
‘custom_fields’ => array(
    array(
      ‘name’        => ‘twitter_name’,
      ‘label’        => ‘Twitter Name’,
      ‘type’        => ‘varchar’,
      ‘max_size’      =>  255,
      ‘require_option’  => ‘optional’,
      ‘default_value’  => ’ ‘,
      ‘ext1’        => ‘’,
      ‘ext2’        => ‘’,
      ‘ext3’        => ’ ‘,
      ‘audited’      => 0,
      ‘module’      => ‘Contacts’,
    ),
),

 

logic_hooks

Defines what logic hooks (workflows) that the module needs installed. See About Logic_Hooks for more information. Example:

1
2
3
4
5
6
7
8
9
10
11
‘logic_hooks’ => array(
    array(
      ‘module’      => ‘Contacts’,
      ‘hook’        => ‘after_save’,
      ‘order’      => 100,
      ‘description’  => ‘Misc Twitter Hooks’,
      ‘file’        => ‘custom/modules/Twitter/TwitterHook.php’,
      class’      => ‘TwitterHook’,
      function’    => ‘process_tweets’,
    ),
),

You may need a single logic hook to work for all modules. For that you need keep module is blank in logic hook definition Example:

1
‘module’  =>'',

so it will create a logic_hook file at /custom/modules/logic_hooks.php

Additional Notes

There are four scripts that can be defined as part of the module install/uninstall process. To make use of this ability add a scripts directory to the base directory of the module zip and add one or more of the following files: * scripts/pre_install.php * scripts/post_install.php * scripts/pre_uninstall.php * scripts/post_uninstall.php These files can be used for anything from pre-installation checks to module satisfaction surveys to even simply display author information and help links.

upgrade_manifest

(Optional) Defines the upgrade path between versions. The installer will check to see if the module has been installed already. If so, it will check the current version of the module installed and will process the instructions defined in the corresponding upgrade_path. For example, if the Twitter module has been installed already and is at version 1.0 it will process the 1.0 instructions which specifies to copy the Twitter module directory and to add a new custom field to the Contacts module. If the currently installed version is 2.0 it will just copy the Twitter module directory (since it is assumed that the custom field has already been created). Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
$upgrade_manifest = array(
  ‘upgrade_paths’ => array(
      ‘1.0’ => array(
        ‘id’ => ‘Twitter’,
        copy’=>array(
          array(
              ‘from’=> ‘/modules/Twitter’,
              ‘to’=> ‘modules/Twitter’,
          ),
        ),
        ‘custom_fields’ => array(
          array(
              ‘name’        => ‘twitter_name’,
              ‘label’        => ‘Twitter Name’,
              ‘type’        => ‘varchar’,
              ‘max_size’      =>  255,
              ‘require_option’  => ‘optional’,
              ‘default_value’  => ’ ‘,
              ‘ext1’        => ‘’,
              ‘ext2’        => ‘’,
              ‘ext3’        => ’ ‘,
              ‘audited’      => 0,
              ‘module’      => ‘Contacts’,
          ),
        ),
      ),
      ‘2.0’ => array(
        ‘id’ => ‘Twitter’,
        copy’ => array(
          array(
              ‘from’=> ‘/module/Twitter’,
              ‘to’=> ‘modules/Twitter’,
          ),
        ),
      ),
  ),
);

Full Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
$manifest = array(
  ‘acceptable_sugar_flavors’ => array(
      ‘CE’, ‘PRO’ ,‘ENT’
  ),
  ‘acceptable_sugar_versions’ =>  array (
      ‘regex_matches’ => array (
        ‘5\.*’,
      ),
  ),
  ‘readme’ => ‘Please make sure to visit our documentation at…’,
  ‘key’ => ‘’,
  ‘author’ => ‘CRMStage’,
  ‘description’ => ‘Yet another Twitter module,
  ‘icon’ => ‘/icon/CRMStage.png’,
  ‘is_uninstallable’ => true,
  ‘name’ => ‘Twitter Module’,
  ‘published_date’ => ‘2010/01/04’,
  ‘type’ => ‘module’,
  ‘version’ => ‘2.5’,
  ‘remove_tables’ => ‘prompt’,
  ‘dependencies’ => array(
      array(
        ‘id_name’ => ‘twitter_helper’,
        ‘version’ => ‘1.0’
      ),
  ),
);
 
$installdefs = array(
  ‘id’            => ‘Twitter’,
  ‘image_dir’        => ‘/images’,
  ‘beans’ => array(
      array(
        ‘module’      => ‘Twitter’,
        class’        => ‘Twitter’,
        ‘path’        => ‘modules/Twitter/Twitter.php’,
        ‘tab’        => true,
      )
  ),
  copy’ => array(
      array(
      ‘from’        => ‘/modules/Twitter’,
      ‘to’          => ‘modules/Twitter’,
      ),
  ),
  mkdir’ => array(
      ‘/cache/twitter/images/’,
  ),
  ‘language’ => array(
      /** ENGLISH en_us */
      array(
        ‘from’          => ‘/language/application/en_us.twitteradmin.php’,
        ‘to_module’      => ‘application’,
        ‘language’      => ‘en_us’
      ),
      array(
        ‘from’        => ‘/language/modules/Administration/en_us.twitteradmin.php’,
        ‘to_module’    => ‘Administration’,
        ‘language’      => ‘en_us’
      ),
      array(
        ‘from’        => ‘/language/modules/Contacts/en_us.twitter.php’,
        ‘to_module’      => ‘Contacts’,
        ‘language’      => ‘en_us’
      ),
      /** END ENGLISH en_us */
      /** SPANISH es_es */
      array(
        ‘from’          => ‘/language/application/es_es.twitteradmin.php’,
        ‘to_module’      => ‘application’,
        ‘language’      => ‘es_es’
      ),
      array(
        ‘from’        => ‘/language/modules/Administration/es_es.twitteradmin.php’,
        ‘to_module’    => ‘Administration’,
        ‘language’      => ‘es_es’
      ),
      array(
        ‘from’        => ‘/language/modules/Contacts/es_es.twitter.php’,
        ‘to_module’      => ‘Contacts’,
        ‘language’      => ‘es_es’
      ),
      /** END SPANISH es_es */
  ),
  ‘menu’ => array (
      array(
        ‘from’        => ‘/menu/modules/Twitter/menu.php’,
        ‘to_module’    => ‘Twitter’
      )
  ),
  ‘dashlets’ => array (
      array(
        ‘from’        => ‘/dashlets/modules/Twitter/TwitterDashlet/’,
        ‘name’        => ‘TwitterDashlet’
      )
  ),
  ‘layoutdefs’ => array(
      array(
        ‘from’        => ‘/layoutdefs/modules/Contacts/twitter_contacts_layoutdefs.php’,
        ‘to_module’    => ‘Contacts’,
      ),
  ),
  ‘vardefs’ => array(
      array(
        ‘from’        => ‘/vardefs/modules/Contacts/twitter_contacts_vardefs.php’,
        ‘to_module’    => ‘Contacts’,
      ),
  ),
  ‘administration’ => array(
      array(
        ‘from’        => ‘/administration/twitter_adminoption.php’,
      ),
  ),
  ‘relationships’ => array(
      array(
        ‘module’      => ‘Contacts’,
        ‘meta_data’    => ‘/relationships/modules/Contacts/twitter_contacts_metadata.php’,
        ‘module_vardefs’  => ‘/relationships/modules/Contacts/twitter_contacts_vardefs.php’,
        ‘module_layoutdefs’ => ‘/relationships/modules/Contacts/twitter_contacts_layoutdefs.php’
      ),
  ),
  ‘custom_fields’ => array(
      array(
        ‘name’        => ‘twitter_name’,
        ‘label’        => ‘Twitter Name’,
        ‘type’        => ‘varchar’,
        ‘max_size’      =>  255,
        ‘require_option’  => ‘optional’,
        ‘default_value’  => ’ ‘,
        ‘ext1’        => ‘’,
        ‘ext2’        => ‘’,
        ‘ext3’        => ’ ‘,
        ‘audited’      => 0,
        ‘module’      => ‘Contacts’,
      ),
  ),
  ‘logic_hooks’ => array(
      array(
        ‘module’      => ‘Contacts’,
        ‘hook’        => ‘after_save’,
        ‘order’      => 100,
        ‘description’  => ‘Misc Twitter Hooks’,
        ‘file’        => ‘custom/modules/Twitter/TwitterHook.php’,
        class’      => ‘TwitterHook’,
        function’    => ‘process_tweets’,
      ),
  ),
 
);
 
$upgrade_manifest = array(
  ‘upgrade_paths’ => array(
      ‘1.0’ => array(
        ‘id’ => ‘Twitter’,
        copy’=>array(
          array(
              ‘from’=> ‘/modules/Twitter’,
              ‘to’=> ‘modules/Twitter’,
          ),
        ),
        ‘custom_fields’ => array(
          array(
              ‘name’        => ‘twitter_name’,
              ‘label’        => ‘Twitter Name’,
              ‘type’        => ‘varchar’,
              ‘max_size’      =>  255,
              ‘require_option’  => ‘optional’,
              ‘default_value’  => ’ ‘,
              ‘ext1’        => ‘’,
              ‘ext2’        => ‘’,
              ‘ext3’        => ’ ‘,
              ‘audited’      => 0,
              ‘module’      => ‘Contacts’,
          ),
        ),
      ),
      ‘2.0’ => array(
        ‘id’ => ‘Twitter’,
        copy’ => array(
          array(
              ‘from’=> ‘/modules/Twitter’,
              ‘to’=> ‘modules/Twitter’,
          ),
        ),
      ),
  ),
);