Changes

m
no edit summary
Line 1: Line 1:  +
<!-- BEGIN origin interlang links -->
 +
<!-- You can edit this section but do NOT remove these comments
 +
    Links below will be automatically replicated on translated pages by PolyglotBot -->
 +
[[fr:Module_CustomFields_FR]]
 +
<!-- END interlang links -->
 +
 
[[Category:Complementary modules]]
 
[[Category:Complementary modules]]
 
[[Category:CustomFields]]
 
[[Category:CustomFields]]
Line 8: Line 14:  
devdoc=[[Module_CustomFields_Dev]]|
 
devdoc=[[Module_CustomFields_Dev]]|
 
userdoc=This page|}}
 
userdoc=This page|}}
[[Category:FAQ EN]]
     −
This documentation is about module CustomFields branch v3. For previous versions, please read the included README inside the archive, although most of the documentation here is also valid for those older versions.
+
'''<span style="color:red; font-size: 1.5em;">This module is not available for Dolibarr Version > 3 . </span>'''
 +
'''<span style="color:red; font-size: 1.5em;">For newer Dolibarr version use the native [[Extrafields]] module, see the related page.</span>'''
 +
 
 +
This documentation is about the external module CustomFields in branch v3. For previous versions, please read the included README inside the archive, although most of the documentation here is also valid for those older versions (particularly for branch V2 which is the Free edition).
    
You can also jump directly to [[Module_CustomFields_Cases]] wiki page for a collection of practical examples.
 
You can also jump directly to [[Module_CustomFields_Cases]] wiki page for a collection of practical examples.
      −
= Informations =
+
=Informations=
 
{{TemplateModuleInfo
 
{{TemplateModuleInfo
 +
|modulename=CustomFields
 
|editor=Larroque Stephen
 
|editor=Larroque Stephen
|web=customfields.org
+
|web=www.customfields.org
 
|webbuy={{LinkToPluginDownloadDoliStore|keyword=customfield}}
 
|webbuy={{LinkToPluginDownloadDoliStore|keyword=customfield}}
 
|status=stable
 
|status=stable
|prerequisites=Dolibarr <= 3.6.0-alpha
+
|prerequisites=Dolibarr <= 3.6.0-alpha.
 
|minversion=3.1.0
 
|minversion=3.1.0
 
|note=
 
|note=
 
}}
 
}}
   −
= Description =
+
=Description=
    
This module allows the implementer to easily create and manage custom fields, and then use them in PDF and ODT documents, or in any other way you want.
 
This module allows the implementer to easily create and manage custom fields, and then use them in PDF and ODT documents, or in any other way you want.
Line 33: Line 42:     
The three main goals of CustomFields are to enable you to:
 
The three main goals of CustomFields are to enable you to:
* Easily create your own custom fields with your data type of choice.
+
 
* Automatically manage/create/update/delete custom fields records of datas.
+
*Easily create your own custom fields with your data type of choice.
* Easily use the custom fields in your ODT and PDF documents, or any other PHP code.
+
*Automatically manage/create/update/delete custom fields records of datas.
 +
*Easily use the custom fields in your ODT and PDF documents, or any other PHP code.
    
And the philosophy:
 
And the philosophy:
* Standards-compliance.
+
 
* Independence with the Dolibarr code.
+
*Standards-compliance.
* Be reusable.
+
*Independence with the Dolibarr code.
 +
*Be reusable.
    
CustomFields has been made with the intention of being as portable, flexible, modular and reusable as possible, so that it can be adapted to any Dolibarr's module, and to (almost) any user's need (even if something isn't implemented, you can most probably just use a custom sql statement, the rest will be managed automatically, even with custom statements.).
 
CustomFields has been made with the intention of being as portable, flexible, modular and reusable as possible, so that it can be adapted to any Dolibarr's module, and to (almost) any user's need (even if something isn't implemented, you can most probably just use a custom sql statement, the rest will be managed automatically, even with custom statements.).
   −
= Understanding CustomFields =
+
=Understanding CustomFields=
    
Technically speaking, this module is a simple wrapper for your sql database. It respects sql standards and manages them in a standard way.
 
Technically speaking, this module is a simple wrapper for your sql database. It respects sql standards and manages them in a standard way.
Line 50: Line 61:  
This means that you can modify your sql database with another tool (eg: phpMyAdmin), and the changes will be reflected inside CustomFields as well.
 
This means that you can modify your sql database with another tool (eg: phpMyAdmin), and the changes will be reflected inside CustomFields as well.
   −
= Features overview =
+
=Features overview=
   −
- Natively support the modules: Invoices, Propales and Products/Services.
+
- Natively support most Dolibarr core modules.
    
- Full multilanguage support:
 
- Full multilanguage support:
* multilanguage in the administration gui (french and english for now, but can be translated by anyone using langs files)
+
 
* multilanguage user-defined custom fields labels
+
*multilanguage in the administration gui (french and english for now, but can be translated by anyone using langs files)
* multilanguage custom fields values (eg: yes/no select box can be translated to any language, same for enum user defined values). You can even translate the values of your dropdown boxes or your constrained fields.
+
*multilanguage user-defined custom fields labels
 +
*multilanguage custom fields values (eg: yes/no select box can be translated to any language, same for enum user defined values). You can even translate the values of your dropdown boxes or your constrained fields.
    
- Several natively supported fields types :
 
- Several natively supported fields types :
* Textbox
+
 
* Areabox
+
*Textbox
* YesNoBox
+
*Areabox
* TrueFalseBox
+
*YesNoBox
* DropdownBox (your own options)
+
*TrueFalseBox
* Date
+
*DropdownBox (your own options)
* DateTime
+
*Date
* Integer
+
*DateTime
* Float
+
*Integer
* Double
+
*Float
* Constrained (link to other tables)
+
*Double
* Other (custom type, defined by your own SQL command)
+
*Constrained (link to other tables)
 +
*Other (custom type, defined by your own SQL command)
    
Note: you can add your own sql datatypes, see the related chapter.
 
Note: you can add your own sql datatypes, see the related chapter.
Line 109: Line 122:  
- Optimized and fast: cache whenever possible and super optimized sql requests and fast php code with as few loops as possible and low number of opcodes.
 
- Optimized and fast: cache whenever possible and super optimized sql requests and fast php code with as few loops as possible and low number of opcodes.
   −
= Requirements =
+
=Requirements=
    
This module requires your database to support Foreign Keys for full functionalities, for example with MySQL you need to enable InnoDB, because MyISAM alone does not support foreign keys and referential integrity checks.
 
This module requires your database to support Foreign Keys for full functionalities, for example with MySQL you need to enable InnoDB, because MyISAM alone does not support foreign keys and referential integrity checks.
Line 117: Line 130:  
For more informations, please read the developper's documentation about the [[Module_CustomFields_Dev#SQL_Compatibility_mode|SQL Compatibility mode]].
 
For more informations, please read the developper's documentation about the [[Module_CustomFields_Dev#SQL_Compatibility_mode|SQL Compatibility mode]].
   −
= Usage =
+
=Usage=
   −
== Enabling the module ==
+
==Enabling the module==
    
{{ActivationModuleEn}}
 
{{ActivationModuleEn}}
Line 129: Line 142:  
Note: when you update Dolibarr or the module, you should disable and re enable the module to activate the new functionnalities (particularly the support of new modules).
 
Note: when you update Dolibarr or the module, you should disable and re enable the module to activate the new functionnalities (particularly the support of new modules).
   −
== Creating a custom field ==
+
==Creating a custom field==
    
After enabling the module and creating the table, you can now create a custom field.
 
After enabling the module and creating the table, you can now create a custom field.
Line 136: Line 149:     
You will then be presented with several options (bold are required):
 
You will then be presented with several options (bold are required):
* Label: this option is disabled, because the label will automatically be the same as the Field Name, but you can translate it (set it) in language files (see the related chapter below).
+
 
* '''Field Name''': sql field name. Choose any name you want, it just has to be alphanumeric without any space (you can use underscore '_'). You can also use remote sql columns names if you set a constrained field to enable Smart Value Substitution for this field (see the related chapter).
+
*Label: this option is disabled, because the label will automatically be the same as the Field Name, but you can translate it (set it) in language files (see the related chapter below).
* '''Type''': the type of the field. This is where you choose what kind of data your field will hold, and more importantly how it will be shown (eg: Textbox, DropdownBox, etc..). You can also choose '''Other''' and set your own SQL type (and size) by entering it in the Other box just below (Eg: int(11)  will create an int of max size 11 bits).
+
*'''Field Name''': sql field name. Choose any name you want, it just has to be alphanumeric without any space (you can use underscore '_'). You can also use remote sql columns names if you set a constrained field to enable Smart Value Substitution for this field (see the related chapter).
* Size, or for DropdownBox the Values: if you want to set a specific size, you can set it here. By default, the module will set the right size for most uses, but if you find that it's too limited, you set any value. Also, this is '''required''' if you set an DropdownBox type, and instead of setting the size you should here set the values that will be offered in the box (eg: "firstval","secondval","thirdval" WITH the quotes and commas).
+
*'''Type''': the type of the field. This is where you choose what kind of data your field will hold, and more importantly how it will be shown (eg: Textbox, DropdownBox, etc..). You can also choose '''Other''' and set your own SQL type (and size) by entering it in the Other box just below (Eg: int(11)  will create an int of max size 11 bits).
* Accept null values: if enabled, the field will accept empty values. Else if disabled, a value will be required, and if an empty value is entered, the last non empty value will be used instead.
+
*Size, or for DropdownBox the Values: if you want to set a specific size, you can set it here. By default, the module will set the right size for most uses, but if you find that it's too limited, you set any value. Also, this is '''required''' if you set an DropdownBox type, and instead of setting the size you should here set the values that will be offered in the box (eg: "firstval","secondval","thirdval" WITH the quotes and commas).
* Default value: you can set the default value when a field has not received any value by the user yet.
+
*Accept null values: if enabled, the field will accept empty values. Else if disabled, a value will be required, and if an empty value is entered, the last non empty value will be used instead.
* Constraint: you can link the field to another table in the database. The field will then offer as choices the records in the remote table.
+
*Default value: you can set the default value when a field has not received any value by the user yet.
* Custom SQL Definition: this is used to add more sql commands to the sql definition of the field (such as comments, meta parameters or transformations).
+
*Constraint: you can link the field to another table in the database. The field will then offer as choices the records in the remote table.
 +
*Custom SQL Definition: this is used to add more sql commands to the sql definition of the field (such as comments, meta parameters or transformations).
 +
 
 
Any SQL command you write here will be appended at the end of the automatically generated SQL statement to create the custom field.
 
Any SQL command you write here will be appended at the end of the automatically generated SQL statement to create the custom field.
   Line 159: Line 174:     
You can of course add multiple statements as long as they are doable in the same statement (you are not allowed to use ";" to add another request, you should then use Custom SQL Statement to do that).
 
You can of course add multiple statements as long as they are doable in the same statement (you are not allowed to use ";" to add another request, you should then use Custom SQL Statement to do that).
* Custom SQL Statement: any sql command can be entered here and will be issued '''only ONCE''' after the definition of the field (thus the commands won't be issued every time the field is shown, but only once when you create the field!). This is the same as using a third-party tool such as phpMyAdmin, and is just offered as a quick shortcut.
+
 
 +
*Custom SQL Statement: any sql command can be entered here and will be issued '''only ONCE''' after the definition of the field (thus the commands won't be issued every time the field is shown, but only once when you create the field!). This is the same as using a third-party tool such as phpMyAdmin, and is just offered as a quick shortcut.
 +
 
 
Note: in Custom SQL Statement, do NOT do <pre>SELECT *</pre> it will be rejected by the injection protection of Dolibarr - and anyway this is totally useless as the module won't show you the result of the request, you should better try sql commands like View, Procedure, Trigger, Check, etc..
 
Note: in Custom SQL Statement, do NOT do <pre>SELECT *</pre> it will be rejected by the injection protection of Dolibarr - and anyway this is totally useless as the module won't show you the result of the request, you should better try sql commands like View, Procedure, Trigger, Check, etc..
 
any SQL request (not just one or two commands like above) will be issued AFTER the creation statement (not in the same statement, this is the main difference with the Custom SQL Definition field).
 
any SQL request (not just one or two commands like above) will be issued AFTER the creation statement (not in the same statement, this is the main difference with the Custom SQL Definition field).
Line 189: Line 206:  
Note: fields are ordered by ordinal_position (order of creation - first created at the top, last at the bottom), so if you want a specific order for your fields, you are advised to carefully think what order you want. Then delete and recreate fields in the order you want them to be.
 
Note: fields are ordered by ordinal_position (order of creation - first created at the top, last at the bottom), so if you want a specific order for your fields, you are advised to carefully think what order you want. Then delete and recreate fields in the order you want them to be.
   −
== Modifying a custom field ==
+
==Modifying a custom field==
    
To edit a custom field, just click on the edit button at the right hand side of the admin page (one button per field).
 
To edit a custom field, just click on the edit button at the right hand side of the admin page (one button per field).
Line 195: Line 212:  
The same form as when you create a custom field will appear with the parameters of the field, and you can then freely edit them, and click '''Save''' to commit the changes.
 
The same form as when you create a custom field will appear with the parameters of the field, and you can then freely edit them, and click '''Save''' to commit the changes.
   −
== Deleting a custom field ==
+
==Deleting a custom field==
    
To delete a custom field, simply click on the trash button at the right hand side (just at the right of the edit button).
 
To delete a custom field, simply click on the trash button at the right hand side (just at the right of the edit button).
Line 201: Line 218:  
WARNING: no confirmation will be asked, and once a custom field is deleted you can not get it back nor get back the values saved by user, they are lost forever! Anyway you can re-create the same field, but user's values will still be lost.
 
WARNING: no confirmation will be asked, and once a custom field is deleted you can not get it back nor get back the values saved by user, they are lost forever! Anyway you can re-create the same field, but user's values will still be lost.
   −
== Translation of a custom field's label ==
+
==Translation of a custom field's label==
    
Fields can easily be labeled or translated using the provided language files.
 
Fields can easily be labeled or translated using the provided language files.
Line 212: Line 229:  
</pre>
 
</pre>
   −
== Testing your custom fields with the PDFTest module ==
+
==Testing your custom fields with the PDFTest module==
    
An auxiliary module called CustomFieldsPDFTest is provided so that you can easily test your custom fields in your PDF outputs. This avoids the need to make your own PDF template and risking to do some mistakes in the php code.
 
An auxiliary module called CustomFieldsPDFTest is provided so that you can easily test your custom fields in your PDF outputs. This avoids the need to make your own PDF template and risking to do some mistakes in the php code.
Line 224: Line 241:  
Note: already generated pdf files won't be affected, only generated PDF documents '''after the PDFTest module is activated''' will have a list of custom fields appended, and if you disable the module and generate again the PDF document, the appended page will disappear.
 
Note: already generated pdf files won't be affected, only generated PDF documents '''after the PDFTest module is activated''' will have a list of custom fields appended, and if you disable the module and generate again the PDF document, the appended page will disappear.
   −
== Implementing in ODT templates ==
+
==Implementing in ODT templates==
    
First, you have to know how to create an ODT template. Please refer to the related documentation: [[Create_an_ODT_document_template]]
 
First, you have to know how to create an ODT template. Please refer to the related documentation: [[Create_an_ODT_document_template]]
Line 270: Line 287:  
</pre>
 
</pre>
   −
== Implementing in PDF templates ==
+
==Implementing in PDF templates==
    
First, before implementing the custom fields, you have to make your own PDF template. Please refer to the related documentation: [[Create_a_PDF_document_template]]
 
First, before implementing the custom fields, you have to make your own PDF template. Please refer to the related documentation: [[Create_a_PDF_document_template]]
Line 276: Line 293:  
To use custom fields in your PDF template, you first need to load the custom fields datas, then you can use them wherever you want.
 
To use custom fields in your PDF template, you first need to load the custom fields datas, then you can use them wherever you want.
   −
* To load the custom fields:
+
*To load the custom fields:
 +
 
 
<source lang="php">
 
<source lang="php">
 
// Init and main vars for CustomFields
 
// Init and main vars for CustomFields
Line 292: Line 310:  
</source>
 
</source>
   −
* To access the field's value:
+
*To access the field's value:
    
Beautified formatting:
 
Beautified formatting:
Line 303: Line 321:  
</source>
 
</source>
   −
* To access a product's line's value:
+
*To access a product's line's value:
 +
 
 
<source lang="php">
 
<source lang="php">
 
$lineid = $object->lines[$i]->rowid;
 
$lineid = $object->lines[$i]->rowid;
$object->customfields->lines->$lineid>cf_myfield
+
$object->customfields->lines->$lineid->cf_myfield
 
</source>
 
</source>
 
Where $lineid must be replaced by the id of the line you want to fetch (rowid of the product, so it does NOT necessary start at 0).
 
Where $lineid must be replaced by the id of the line you want to fetch (rowid of the product, so it does NOT necessary start at 0).
   −
* To print it with FPDF (the default PDF generation library):
+
*To print it with FPDF (the default PDF generation library):
 +
 
 
<source lang="php">
 
<source lang="php">
 
$pdf->MultiCell(0,3, $object->customfields->cf_myfield, 0, 'L'); // printing the customfield
 
$pdf->MultiCell(0,3, $object->customfields->cf_myfield, 0, 'L'); // printing the customfield
 
</source>
 
</source>
   −
* And if you want to print the multilanguage label of this field :
+
*And if you want to print the multilanguage label of this field :
 +
 
 
<source lang="php">
 
<source lang="php">
 
$outputlangs->load('customfields-user@customfields');
 
$outputlangs->load('customfields-user@customfields');
Line 327: Line 348:  
</source>
 
</source>
   −
* If you want to print an HTML field (Areabox), the FPDF library provides you with a mean to do so:
+
*If you want to print an HTML field (Areabox), the FPDF library provides you with a mean to do so:
 +
 
 
<source lang="php">
 
<source lang="php">
 
$pdf->writeHTML('HTML beautified printing for myfield: '.$object->customfields->cf_myfield); // printing areabox with html parsing
 
$pdf->writeHTML('HTML beautified printing for myfield: '.$object->customfields->cf_myfield); // printing areabox with html parsing
Line 338: Line 360:  
</source>
 
</source>
   −
== Implementing in php code (dolibarr core modules or your own module) ==
+
==Implementing in php code (dolibarr core modules or your own module)==
    
One of the main features of the CustomFields module is that it offers a generic way to access, add, edit and view custom fields from your own code. You can easily develop your own modules accepting user's inputs based on CustomFields.
 
One of the main features of the CustomFields module is that it offers a generic way to access, add, edit and view custom fields from your own code. You can easily develop your own modules accepting user's inputs based on CustomFields.
Line 349: Line 371:     
customfields_fill_object() takes 5 parameters:
 
customfields_fill_object() takes 5 parameters:
* $object: the object where the custom fields datas will be set
+
 
* $fromobject: the object from which the custom fields will be fetched (this can be used to fetch custom fields from multiple modules into one $object)
+
*$object: the object where the custom fields datas will be set
* $langs: language translation class, to localize your custom fields values
+
*$fromobject: the object from which the custom fields will be fetched (this can be used to fetch custom fields from multiple modules into one $object)
* $prefix: prefix to add to help you organize and avoid overwriting custom fields (eg: you have two modules and want to store into one $object, with $prefix='invoice' the first will store inside $object->customfields->invoice->cf_myfield, and second='propal' will store inside $object->customfields->propal->cf_myfield).
+
*$langs: language translation class, to localize your custom fields values
* $pdfformat: beautify the customfields values? (null = no beautify nor translation; false = beautify and translate; true = translation and pdf beautify with html entities encoding)
+
*$prefix: prefix to add to help you organize and avoid overwriting custom fields (eg: you have two modules and want to store into one $object, with $prefix='invoice' the first will store inside $object->customfields->invoice->cf_myfield, and second='propal' will store inside $object->customfields->propal->cf_myfield).
 +
*$pdfformat: beautify the customfields values? (null = no beautify nor translation; false = beautify and translate; true = translation and pdf beautify with html entities encoding)
 +
 
 
Note: $fromobject (or $object if $fromobject=null) can be a dummy object and contain only two properties: $fromobject->id and $fromobject->table_element (which is the module's name, or table's name where the module stores its datas).
 
Note: $fromobject (or $object if $fromobject=null) can be a dummy object and contain only two properties: $fromobject->id and $fromobject->table_element (which is the module's name, or table's name where the module stores its datas).
   Line 374: Line 398:  
You can also manually fetch the custom fields values (called $records below):
 
You can also manually fetch the custom fields values (called $records below):
   −
* First, you necessarily have to instanciate the CustomFields class:
+
*First, you necessarily have to instanciate the CustomFields class:
 +
 
 
<source lang="php">
 
<source lang="php">
 
// Init and main vars
 
// Init and main vars
Line 382: Line 407:  
</source>
 
</source>
   −
* Secondly, you have the fetch the records (this will fetch ALL custom fields for ALL records):
+
*Secondly, you have the fetch the records (this will fetch ALL custom fields for ALL records):
 +
 
 
<source lang="php">
 
<source lang="php">
 
$records = $customfields->fetchAll();
 
$records = $customfields->fetchAll();
 
</source>
 
</source>
   −
* Thirdly, you can now print all your records this way:
+
*Thirdly, you can now print all your records this way:
 +
 
 
<source lang="php">
 
<source lang="php">
 
if (!is_null($records)) { // verify that we have at least one result
 
if (!is_null($records)) { // verify that we have at least one result
Line 399: Line 426:  
</source>
 
</source>
   −
* Full final code:
+
*Full final code:
 +
 
 
<source lang="php">
 
<source lang="php">
 
// Init and main vars
 
// Init and main vars
Line 418: Line 446:  
</source>
 
</source>
   −
* If you want to fetch only one record:
+
*If you want to fetch only one record:
 +
 
 
<source lang="php">
 
<source lang="php">
 
$record = $customfields->fetch($id); // Where id is of course the id of the record to fetch.
 
$record = $customfields->fetch($id); // Where id is of course the id of the record to fetch.
Line 428: Line 457:  
</source>
 
</source>
   −
* You can get the errors returned by the CustomFields class (sql errors and others):
+
*You can get the errors returned by the CustomFields class (sql errors and others):
 +
 
 
<source lang="php">
 
<source lang="php">
 
print($customfields->error); // This will print all errors concatenated in a single string returned by the CustomFields class
 
print($customfields->error); // This will print all errors concatenated in a single string returned by the CustomFields class
Line 440: Line 470:  
</source>
 
</source>
   −
== Do's and don't to avoid slowdowns when implementing CustomFields ==
+
==Do's and don't to avoid slowdowns when implementing CustomFields==
   −
* In PDF templates, use customfields_fill_object_lines() only ONCE before the loop, else it will be very heavy on CPU and memory usage (using it once will already fetch all lines for the current object at once, no need to use it several times).
+
*In PDF templates, use customfields_fill_object_lines() only ONCE before the loop, else it will be very heavy on CPU and memory usage (using it once will already fetch all lines for the current object at once, no need to use it several times).
   −
* Adding a lot of customfields or product lines won't really slow down CustomFields in any way (datasheet printing, editing field, PDF/ODT generation, etc..), thank's to caching.
+
*Adding a lot of customfields or product lines won't really slow down CustomFields in any way (datasheet printing, editing field, PDF/ODT generation, etc..), thank's to caching.
   −
* Try to avoid the number of constrained customfields: adding a lot of constrained customfields will, because CustomFields automatically lookup the remote tables for every constrained field, so that you can access any remote column in your PDF. There is a cache mechanism that tries to speed up the process, so for example if you have many different constrained customfields on the same remote table (eg: with different Smart Value Substitution prefixes), then the performance won't be tampered, but if every constrained customfields is linked to a different table, there is no way around, it will slow down. If you encounter problems, try to limit the number of constrained fields you create, or try to add SQL indexes on the remote table of the constrained field, or don't use customfields_fill_object*() functions but directly access _only_ the fields you need by using the CustomFields class or your own sql query.
+
*Try to avoid the number of constrained customfields: adding a lot of constrained customfields will, because CustomFields automatically lookup the remote tables for every constrained field, so that you can access any remote column in your PDF. There is a cache mechanism that tries to speed up the process, so for example if you have many different constrained customfields on the same remote table (eg: with different Smart Value Substitution prefixes), then the performance won't be tampered, but if every constrained customfields is linked to a different table, there is no way around, it will slow down. If you encounter problems, try to limit the number of constrained fields you create, or try to add SQL indexes on the remote table of the constrained field, or don't use customfields_fill_object*() functions but directly access _only_ the fields you need by using the CustomFields class or your own sql query.
   −
* Smart value substitution for constrained fields does not hamper any performance (eg: prefix of the remote column for auto replacement of the raw value by the specified column's value).
+
*Smart value substitution for constrained fields does not hamper any performance (eg: prefix of the remote column for auto replacement of the raw value by the specified column's value).
   −
* Try to use customfields_fill_object() and customfields_fill_object_lines() only once per script, these functions are really heavy and do all the work for you, they are optimized and cache everything they can, but the drawback is that they're heavy. An easy way is to modify directly the original $object, so that the result will be transmitted to every other parts of Dolibarr (but be careful, do it only if you know that this will not conflict). You can also choose to not use these functions at all, and use directly the CustomFields class, if you have really specific needs, you can have fastest results (eg: if you don't need to fetch all the customfields but only one or a few, or if you only need the raw values).
+
*Try to use customfields_fill_object() and customfields_fill_object_lines() only once per script, these functions are really heavy and do all the work for you, they are optimized and cache everything they can, but the drawback is that they're heavy. An easy way is to modify directly the original $object, so that the result will be transmitted to every other parts of Dolibarr (but be careful, do it only if you know that this will not conflict). You can also choose to not use these functions at all, and use directly the CustomFields class, if you have really specific needs, you can have fastest results (eg: if you don't need to fetch all the customfields but only one or a few, or if you only need the raw values).
   −
= Constraints =
+
=Constraints=
    
This chapter will present the special functionnalities of constrained fields, which are a powerful functionnality of CustomFields.
 
This chapter will present the special functionnalities of constrained fields, which are a powerful functionnality of CustomFields.
   −
== Adding a constrained/linked custom field ==
+
==Adding a constrained/linked custom field==
 
Let's say you want to make a custom field that let you choose among all the users of Dolibarr.
 
Let's say you want to make a custom field that let you choose among all the users of Dolibarr.
   Line 469: Line 499:  
PowerTip2: If that's still not enough to satisfy your needs, you can create more complex sql fields by using the Custom SQL field at the creation or update page, the sql statement that you will put there will be executed just after the creation/update of the field, so that you can create view, execute procedures. And the custom field will still be fully managed by CustomFields core without any edit to the core code.
 
PowerTip2: If that's still not enough to satisfy your needs, you can create more complex sql fields by using the Custom SQL field at the creation or update page, the sql statement that you will put there will be executed just after the creation/update of the field, so that you can create view, execute procedures. And the custom field will still be fully managed by CustomFields core without any edit to the core code.
   −
PowerTip3: And if that's still not enough, you can overload functions to manage your fields directly with the customfields_fields_extend.lib.php library. And yes, it also works with constrained fields.
+
PowerTip3: And if that's still not enough, you can [[Module_CustomFields#Overloading_functions:_Adding_your_own_management_code_for_custom_fields|overload functions]] to manage your fields directly with the customfields_fields_extend.lib.php library. And yes, it also works with constrained fields.
   −
== Smart Value Substitution ==
+
==Smart Value Substitution==
    
Smart Value Substitution is a quick and easy option to show another remote field's value of a constrained field in place of the raw value (sql row id).
 
Smart Value Substitution is a quick and easy option to show another remote field's value of a constrained field in place of the raw value (sql row id).
Line 497: Line 527:  
And you want the user to choose not only the country but also the region, you can just create a custom fields with the name 'country_region' and it will show a list of all countries and regions, from which the user will easily choose.
 
And you want the user to choose not only the country but also the region, you can just create a custom fields with the name 'country_region' and it will show a list of all countries and regions, from which the user will easily choose.
   −
== Accessing remote fields via a constrained field ==
+
==Remote Fields Access via a constrained field==
    
With constrained fields, you can not only access the custom field's value, but also any remote field (sql column) of the linked table.
 
With constrained fields, you can not only access the custom field's value, but also any remote field (sql column) of the linked table.
Line 539: Line 569:  
</source>
 
</source>
   −
= Advanced configuration =
+
PowerTip: to get the list of available variable, you can use the CustomFieldsPDFTest module (provided with CustomFields Pro) to print the full list of custom fields variables for you. This list will be printed in a PDF, but the variables' names are the same in ODT document.
 +
 
 +
==Recursive Remote Fields Access via a constrained field==
 +
 
 +
In ODT and PDF documents and when using the customfields_fill_object() api, you automatically get a very powerful feature: the recursive access to remote fields.
 +
 
 +
This is just like Remote Fields Access, but recursively: if the remote table contains constrained custom fields, these remote constrained custom fields will also be traversed and the referenced table they link to will be fetched too.
 +
 
 +
This will be clearer with an example: let's say you have a custom field named "user_firstname" in the Client Invoice module, that is constrained on "llx_user". Now, let's say that on the User module, you also added a custom field named "task_name", constrained on "llx_project_task". Now, in your invoices, when you select a user in the "user_firstname" custom field, you will not only get every standard User fields associated to the selected user, but also the task selected for this user and every fields of the linked Task object for this user. Thus, you here linked an invoice to a user to a task, without even programming anything!
 +
 
 +
This is a very powerful feature, somewhat similar to ProductsEasyAccess but more generic (and thus less efficient). Indeed, be aware that this powerful feature has a drawback: it can consume a lot of resources and thus slowndown significantly your PDF/ODT generation process. However, this should not slowdown your navigation in your Dolibarr webapp, since the recursive remote fields access is only enabled on PDF/ODT generation or in your code using customfields_fill_object() (because CustomFields does not use this facade API internally).
 +
 
 +
Additionally, there is nothing to enable, this functionality is managed automatically. You just need to create constrained fields to make the bridge between the different modules you want to access.
 +
 
 +
Powertip: you can mix this automatic feature with the NonEditable option, the Hide option and the Duplication option: this will allow you to make a bridge and access any object. For example, in your Invoices, if you want to access in your ODT document every fields of the Client (most of the client's infos are not accessible in ODT documents), you can create a custom field that will duplicate the client's id field, and then in your ODT document you will gain access to any Client's fields thank's to the RRFA feature. If in addition you put this custom field as NonEditable and Hide, this custom field will be totally transparent and hidden, your Dolibarr users won't even notice it.
 +
 
 +
==Manage constrained fields programmatically==
 +
 
 +
If you use the facade API customfields_fill_object(), the constrained fields will be automatically managed for you, you won't have to do any further processing.
 +
 
 +
However, if you want to have a finer control over constrained fields, read the rest of this chapter.
 +
 
 +
Constrained custom fields are just like any custom field: you can $customfields->fetch() it, and also $customfields->fetchFieldStruct() to get its options.
 +
 
 +
Example to load the constrained custom field structure and check if it's really constrained:
 +
 
 +
<source lang="php">
 +
dol_include_once('/customfields/class/customfields.class.php'); // NEW WAY since Dolibarr v3.3
 +
$customfields = new CustomFields($this->db, $currentmodule); // where $currentmodule is the current module, you can replace it by '' if you just want to use printing functions and fetchAny.
 +
$myfield = $customfields->fetchFieldStruct('myfield'); // where 'myfield' is the name of the constrained custom field
 +
 
 +
// Check if it's a constrained field
 +
if ($myfield->referenced_table_name) {
 +
    // Do your stuff here...
 +
}
 +
</source>
 +
 
 +
Now, if you want to fetch the remote fields referenced by your constrained customfield, use one of the following:
 +
 
 +
<source lang="php">
 +
//$fkrecord = $customfields->fetchAny('*', $field->referenced_table_name, $field->referenced_column_name."='".$id."'"); // we fetch the record in the referenced table. Equivalent to the fetchReferencedValuesList command below using $id=$value and $allcolumns=true.
 +
//$fkrecord = $customfields->fetchReferencedValuesList($field, $id, null, true); // works correctly but is not recursive. Use fetchReferencedValuesRec() for a recursive fetching.
 +
$fkrecord = fetchReferencedValuesRec($customfields, $field, $id); // we fetch the record in the referenced table, in a recursive fashion.
 +
</source>
 +
 
 +
where $id is the id of the record you want to fetch, generally given by $object->cf_myfield.
 +
 
 +
For more info on these functions, see the developper's documentation.
 +
 
 +
From here, you have an $fkrecord array containing all remote fields values, and you can do whatever you want with those.
 +
 
 +
=Extra options=
 +
 
 +
This chapter will present extra options that you can set in the administration panel.
 +
 
 +
==Recopy==
 +
 
 +
Recopy option allows to transfert a custom field's value in module A to another custom field of another module B. This allows to keep custom fields values when converting an object.
 +
 
 +
For example, let's say that you have a custom field named "piece_reference" in your Commercial proposals. You now would like that when you convert your Commercial proposals into an Invoice, you also transfert this "piece_reference" in the Invoice so that you can easily print it on your generated invoice documents. To do this, you just need to create a custom field named the same, "piece_reference", on Invoices, and then enable the Recopy option on it (not on Commercial proposal's custom field, the recopy option is to be enabled on the child field on which we want to recopy on).
 +
 
 +
This feature is automatically managed, and it supports chaining (eg: recopy from Intervention to Commercial Proposal, and then recopy from Commercial Proposal to Invoice).
 +
 
 +
You can also specify the parent field's name if the name is different (eg: "piece_reference" in Commercial proposals but "client_ref" in Invoices).
 +
 
 +
==Cascade==
 +
 
 +
This option allows to create dynamically linked/dependent lists, also called '''cascaded dropdown lists'''.
 +
 
 +
This is a common construct seen on the modern web, for example: you want to be able to specify the location of your client. To do this, instead of using a text field to enter the address, you'd prefer to use Dropdown lists as to avoid entry mistakes. To do that, you can create one field "country_libelle" (or country_label in Dolibarr >= 3.7) constrained on llx_c_pays to indicate the client's country, and then another field "region_nom" constrained on llx_c_regions to show the list of regions. However, those two lists are independent, and the selected region can be entirely wrong considered the country. To limit the available regions depending on the selected country, you can use the Cascade option on the "region_nom" (child) field, and set the Parent field to be "country_libelle". Then, you will see that regions will automatically be limited to the relevant ones depending on the selected country. This is called '''cascading''', because the parent field "country_libelle" cascaded its value to the child "region_nom".
 +
 
 +
By default, the management of the cascade is fully automatic and is managed via AJAX. For compatibility, if the user has no AJAX support, the cascading won't happen so that user's without AJAX support (eg: smartphones, tablets, etc.) will still be able to select a value.
 +
 
 +
Currently, the automatic management only works on '''constrained fields''' (both the child and parent fields must be constrained). If you want to cascade fields of other types than Constrained, you can use the [[Module_CustomFields#Custom_AJAX_Functions|Custom Ajax Functions]] facility (see below) to manage cascading at object's creation, and [[Module_CustomFields#Overloading_functions:_Adding_your_own_management_code_for_custom_fields|Overloading Functions]] to manage cascading at object's edition.
 +
 
 +
To setup a cascade in the administration panel, you just need to enable the Cascade option, and select the Parent field that should cascade its value onto the currently edited field. The admin panel will try to fill out the remaining fields automatically. However, if an alert is shown or if the two Join From and Join On fields remain empty, you will need to fill them manually.
   −
== Changing the default variable prefix for fields name ==
+
These two Join fields specify how the linked tables of the two constrained fields are related (eg: foreign key). CustomFields admin panel will try to detect that automatically, but this may not always be possible (if there's no foreign key).
 +
 
 +
*Join From is the current field's linked table SQL column that points to the parent field's linked table.
 +
*Join On is the parent field's linked table SQL column that is pointed by the Join From column (by default: rowid).
 +
 
 +
For example: let's say you now want to add a field to specify the department. To do that, you can create a field "dep_nom" constrained on llx_c_departements, and enable Cascade with the Parent field being "region_nom". However, CustomFields will show you an alert telling you that no relationship could be found. This is because the relationship between the two tables isn't encoded in a Foreign Key in your SQL database. To find the relationship, you can take a look using phpMyAdmin at both llx_c_departements and llx_c_regions tables, and you will see that llx_c_departements has a field named "fk_region" (so yes they are both linked), and llx_c_regions has a field named "code_region". You now have everything you need: set Join From as "fk_region", and set Join On as "code_region". Save your new custom field, and you will see that your "dep_nom" field is correctly cascaded when you select a region using "region_nom" field.
 +
 
 +
==Duplicate==
 +
 
 +
Duplicate is a semi-automatic functionality that allows you to tell your custom field to automatically copy the value from another object's field. This is not to be confused with the Recopy or Clone options: Duplicate will copy a field from the same object, whereas Recopy copies the value from another object from a different type, and Clone copies from another object of the same type as the target one.
 +
 
 +
Duplicate can copy from another custom field or from a standard Dolibarr's field.
 +
 
 +
This is a very useful option in certain cases, for example when you want to gain access of standard Dolibarr's fields as tags in your ODT documents: in this case, you can simply set a hidden and noneditable custom field to duplicate this standard Dolibarr field you want to access, and it will be accessible in your ODT document, as simple as that.
 +
 
 +
For example, let's say that in your Invoices ODT documents you want to access every fields of the Client (most of the client's infos are not accessible in ODT documents), you can create a custom field that will duplicate the client's id field, and then in your ODT document you will gain access to any Client's fields thank's to the RRFA feature. If in addition you put this custom field as NonEditable and Hide, this custom field will be totally transparent and hidden, your Dolibarr users won't even notice it.
 +
 
 +
To enable this option, you just need to fill the DuplicateFrom field: this is the name of the property in $object that you want to copy. $object is the standard thing in Dolibarr that contains everything about your invoice, client, propal, etc. You can set any property, or even convoluted paths.
 +
 
 +
For example, you can set DuplicateFrom="mycustomfield". In this case, if you have another custom field named "mycustomfield", this field will be automatically duplicated in this one (by accessing $object->cf_mycustomfield).
 +
 
 +
Now, let's say you set DuplicateFrom="client->id". Here, you will access $object->client->id, which is the identifier number of the client for the current invoice. In the end, your custom field will duplicate the client id. If in addition you set the custom field to be constrained on "llx_user", you will get a full access to all of the client's fields, and even client's custom fields.
 +
 
 +
==Other options==
 +
 
 +
Here are a few other options that you can set:
 +
 
 +
*Required: make the field required at object's creation. Eg: when creating an Invoice, this field will need to be filled, empty value will not be accepted.
 +
 
 +
*Not editable: the field cannot be edited by users. Particularly useful for summary fields (eg: an Invoice Lines's custom field that does the final sum after applying custom coefficients on the product's price). These fields are to be implemented by yourself via [[Module_CustomFields#Overloading_functions:_Adding_your_own_management_code_for_custom_fields|overloading functions]] (you will get every infos you need, other fields included, you'll just have to make your computations and then return that).
 +
 
 +
*Hide: hide this custom field from view. It can still be seen in sourcecode and be manipulated via overloading functions and custom ajax functions. This is particularly useful if you want to hide/show some fields conditionally to the value selected on another field (to do that, enable Cascade and Hide on this field, and then use a custom ajax function (see below) to trigger display depending on parent's value).
 +
 
 +
*Separator: display a separator above the current field, thus all fields below the current one (included) will be shown in a separate table.
 +
 
 +
=Advanced configuration=
 +
 
 +
==Changing the default variable prefix for fields name==
    
A prefix is automatically added to each custom field's name in the code (not in the database!), to avoid any collision with other core variables or fields in the Dolibarr core code.
 
A prefix is automatically added to each custom field's name in the code (not in the database!), to avoid any collision with other core variables or fields in the Dolibarr core code.
Line 551: Line 693:  
Then edit the value of the '''$fieldsprefix''' variable.
 
Then edit the value of the '''$fieldsprefix''' variable.
   −
== Changing the delimiter for Smart Value Substitution ==
+
==Changing the delimiter for Smart Value Substitution==
    
When using smart value substitution (ie: when you create a constrained field and set remote columns names in the field's name), by default every column name must be separated by an underscore '_'. This is usually good enough for most cases, but in a few occasions you might want to link to a remote column which name already contains an underscore, and in this case you won't be able to access it with SVS (but you can still access it with the remote field access in PDF/ODT templates and PHP codes, eg: myfield_remote_field_name_with_underscore).
 
When using smart value substitution (ie: when you create a constrained field and set remote columns names in the field's name), by default every column name must be separated by an underscore '_'. This is usually good enough for most cases, but in a few occasions you might want to link to a remote column which name already contains an underscore, and in this case you won't be able to access it with SVS (but you can still access it with the remote field access in PDF/ODT templates and PHP codes, eg: myfield_remote_field_name_with_underscore).
Line 563: Line 705:  
'''CAUTION''': you can only set as a delimiter a character that is accepted by your DBMS, or else this will produce errors!
 
'''CAUTION''': you can only set as a delimiter a character that is accepted by your DBMS, or else this will produce errors!
   −
== Overloading functions: Adding your own management code for custom fields ==
+
==Overloading functions: Adding your own management code for custom fields==
    
The module offers an overloading facility where you can overload (read here: replace) functions of CustomFields by your own.
 
The module offers an overloading facility where you can overload (read here: replace) functions of CustomFields by your own.
Line 569: Line 711:  
The idea is that for each custom field you create, a few overloading functions are created and associated with it. You can use them or not. If you use them, you can put inside the functions your own SQL queries and other calculations you want to do, and then CustomFields will try to automatically manage this field, '''using your specifications'''.
 
The idea is that for each custom field you create, a few overloading functions are created and associated with it. You can use them or not. If you use them, you can put inside the functions your own SQL queries and other calculations you want to do, and then CustomFields will try to automatically manage this field, '''using your specifications'''.
   −
This can be used in various ways: to change how a particular field is printed, how a particular field is saved, to add your own SQL request to manage a custom field, etc.
+
This can be used in various ways: to change how a particular field is printed, how a particular field is saved, to add your own SQL request to manage a custom field, to manage which options are shown to users, etc.
    
Within this library, you can define one function per action (view, edit, create, save, etc.), per module and per field (so that you can define different functions for different fields).
 
Within this library, you can define one function per action (view, edit, create, save, etc.), per module and per field (so that you can define different functions for different fields).
Line 584: Line 726:     
<source lang="php">
 
<source lang="php">
/* Decription: you can overload a few functions of CustomFields to do your own stuff, mainly the printing and the management of the fields.
+
/* Description: here you can overload a few functions of CustomFields to do your own stuff, mainly the printing and the management of the fields.
 
  *
 
  *
 
  * Guidelines:
 
  * Guidelines:
Line 616: Line 758:  
  * create: in creation page, you can change the value(s) that will be available in a customfield, and then CustomFields will continue the processing/printing.
 
  * create: in creation page, you can change the value(s) that will be available in a customfield, and then CustomFields will continue the processing/printing.
 
  * createfull: in creation page, CF stops and you do the rest of the processing/printing.
 
  * createfull: in creation page, CF stops and you do the rest of the processing/printing.
  * save: at edition (on datasheet), you can change the values that will be stored in the database, and then CF will commit them (you don't have to, just change the values).
+
  * save: just before saving a custom field in database, you can change the values that will be stored in the database, and then CF will commit them (you don't have to, just change the values).
  * savefull: at edition (on datasheet), CF stops the processing and you do the rest of the commit to the database (WARNING: CF will not store the data, you have to do it!)
+
  * savefull: just before saving a custom field in database, CF stops the processing and you do the rest of the commit to the database (WARNING: CF will not store the data, you have to do it!).
 +
* aftersave: just after saving a custom field in database. Great to call various Dolibarr refresh functions (like $object->update_price() to refresh the total price).
 
  * BONUS: if you want to change values saving at creation and stop CF to do the processing and commit, you can use a TRIGGER in the customfield's trigger file (eg: FACTURE_CREATE, and then you can filter which field you want to process specifically, as soon as you do a return this will stop CF to process the fields at creation).
 
  * BONUS: if you want to change values saving at creation and stop CF to do the processing and commit, you can use a TRIGGER in the customfield's trigger file (eg: FACTURE_CREATE, and then you can filter which field you want to process specifically, as soon as you do a return this will stop CF to process the fields at creation).
 
  *
 
  *
Line 665: Line 808:  
For more complete example cases, you can read the [[Module_CustomFields_Cases]] page.
 
For more complete example cases, you can read the [[Module_CustomFields_Cases]] page.
   −
== Adding a new sql data type ==
+
Note: beware, save, savefull and aftersave types have different arguments:
 +
<source lang="php">
 +
function customfields_field_save_mymodule_myfield (&$currentmodule, &$object, &$action, &$user, &$customfields, &$field, &$name, &$value, $fields) {
 +
}
 +
 
 +
function customfields_field_savefull_mymodule_myfield (&$currentmodule, &$object, &$action, &$user, &$customfields, &$field, &$name, &$value, $fields) {
 +
}
 +
 
 +
function customfields_field_aftersave_mymodule_myfield (&$currentmodule, &$object, &$action, &$user, &$customfields, &$field, &$name, &$value, $fields) {
 +
}
 +
</source>
 +
 
 +
==Custom AJAX Functions==
 +
 
 +
CustomFields now supports AJAX to send/receive data and dynamically update HTML form's inputs. This section will describe how you can manually implement AJAX for any field, and then it will explain how you can manually manage a cascading field.
 +
 
 +
===Attaching AJAX to any field===
 +
 
 +
Note: you can skip this part if you just want to manually manage a cascading field, but this can help you understand the way it works.
 +
 
 +
An AJAX script can be attached to any field (including non-CustomFields) by using the method:
 +
 
 +
<source lang="php">
 +
$customfields->ShowInputFieldAjax($id, $phpcallback, $on_func="change", $request_type="post")
 +
</source>
 +
 
 +
Where $id is the HTML id of the field you want to attach the AJAX to, and $phpcallback the relative path from Dolibarr's htdocs root folder to the php script that will receive and send back data.
 +
 
 +
The AJAX script will automatically manage sending/receiving of data:
 +
 
 +
*automatically send all form's inputs values, as well as the current calling field's name and value. The sending happens on change by default, but another event can be set using the $on_event argument. Data will be sent using standard GET or POST.
 +
*Upon reception of data from the php script, the AJAX script will automatically parse the data and update the HTML fields.
 +
 
 +
The PHP callback script must send back to AJAX the data in JSON encoded format, and with with a specific format:
 +
 
 +
*the data must be an associative array, where each entry's key is the name (not ID!) of an HTML field to update.
 +
*each entry's value is an associative array, where each sub-entry's key is the action to do. Available actions: 'options', 'value', 'html', 'alert', 'css', 'attr' (see below for more details).
 +
*each sub-entry's value is the value for this action and HTML field.
 +
 
 +
Thus, this approach allows to generically support a wide range of updating actions, managed automatically.
 +
 
 +
You, the implementer, have just to edit the PHP callback script and return an associative array defining what action you want for each field you want to update. This is exactly what has been implemented in the Custom AJAX Functions library, which simplifies even more your job by managing automatically the step described here (generating AJAX and formatting data), so that you can focus on '''making the data'''.
 +
 
 +
===Custom cascading===
 +
 
 +
To manage cascading manually, a very similar system to the Overloading Functions was implemented: you just have to define a function, with the name including the module and the field's name you want to manage, and CustomFields will call your function instead of managing automatically the AJAX for this field.
 +
 
 +
Note also that you have to enable the Cascade Custom option for this field in the admin panel, else your function won't be called.
 +
 
 +
To make your own Custom Ajax Functions, first rename the following file: /customfields/fields/customfields_fields_ajax_custom.lib.php.example
 +
 
 +
Into (just remove the .example at the end): /customfields/fields/customfields_fields_ajax_custom.lib.php
 +
 
 +
Then open it with your text/php editor.
 +
 
 +
You will find inside all the information you need, here is an excerpt:
 +
 
 +
<source lang="php">
 +
/* Description: here you can define your own interactive manipulation of the customfields on create pages, which will then be sent back to user's browser via AJAX.
 +
*
 +
* Guidelines:
 +
* You can use and modify any variable, CustomFields will then use them afterwards (except for 'full' functions which completely overload CustomFields, so that you must take care of everything on your own).
 +
* If not using full method, just return an array $result which contain an entry for each of your customfields, and inside the manipulation you want. Eg: $result = array('cf_mycustomfieldname' => array('options'=>array('option1'=>'optiontitle1', 'option2'=>'optiontitle2'));
 +
* If using a full method, you have to print the JSON encoded $result array yourself (eg: print(json_encode($result)); ). Please also be aware that it will stop any other printing, thus you can't use more than one full method per module (the other fields will just be silenced, because, well, there's no way to json reencode an array that is already printed, thus it's not possible to append data to what you print).
 +
*
 +
* The $result array works this way:
 +
* - At the first array level, the keys define which customfield's HTML field will be modified. The value contains an array defining the changes that will be done (see 2nd array level).
 +
* - At the second array level, the keys define what kind of change you will do, and the value is the value of the change. Available change actions are: 'options' to just define the options for a select dropdown list type (the value must be an array where the keys will be the html value, and the value will be the title displayed for this option), 'html' change the whole html, 'value' change the currently selected value, 'alert' shows an error message to the user.
 +
* You can also store all your alert messages directly at first level, in an array of messages to show, they will all be shown, eg: $results['alert'][] = 'Error message1'; $results['alert'][] = 'Error message2';
 +
*
 +
* To access the database using Dolibarr's core functions, you can use:
 +
* global $db;
 +
* then you can: $db->query('SELECT * FROM table'); or use the equivalent $customfields->fetchAny('*', 'table') for added security against injection.
 +
*
 +
* $_POST is sanitized (except when using a full method, then there's no sanitization) and available in the variable $data, but you still should sanitize your inputs if it's coming from users, so please resanitize $_POST depending on your usage (eg, by typing your variables with filter_var() or filter_var_array()).
 +
*
 +
* You can also access a variety of other things via globals, like:
 +
* $conf - contain all Dolibarr's config
 +
* $user - current user's loggued (can access his rights to check security)
 +
* $langs - current language of the user (for internationalization)
 +
*
 +
* Lastly, you can access the raw GET and POST variables using:
 +
* $myvar = GETPOST('myvar');
 +
*
 +
*
 +
* Format for the name of your functions:
 +
* All ajax custom functions must be named with the following convention ($fieldname is the field's name without the prefix 'cf_'):
 +
* customfields_field_ajax_$module_$fieldname
 +
*
 +
* You can also make a generic function that will be called for all fields of the module if there's no specific function for the current customfield
 +
* customfields_field_ajax_$module_all
 +
*
 +
* For example, for the module invoice (called 'facture' in Dolibarr, see conf_customfields.lib.php) and a field named 'myfield', you can use:
 +
* customfields_field_ajax_facture_myfield
 +
*
 +
* And a generic function for the invoice module:
 +
* customfields_field_ajax_facture_all
 +
*
 +
* This generic function will be called for all customfields in the invoice module, except for myfield which will use the specific function defined just above.
 +
*
 +
* A list of modules can be found in conf_customfields.lib.php in the $modulesarray variable.
 +
*
 +
* IMPORTANT: for a field to call a function here, the option cascade MUST be enabled for this field in the CustomFields admin panel. Also note that these functions will only be called at creation sheet, for editing sheet (when editing a customfield on an object already created), you should also create a custom overloading function of type 'edit'.
 +
*
 +
*/
 +
</source>
 +
 
 +
==Adding a new sql data type==
    
Here you will learn how to add the native support for a data type.
 
Here you will learn how to add the native support for a data type.
Line 717: Line 967:  
You can find them at /customfields/langs/code_CODE/customfields.lang or customfields-user.lang
 
You can find them at /customfields/langs/code_CODE/customfields.lang or customfields-user.lang
   −
== Adding the support of a new module ==
+
==Adding the support of a new module==
    
Please read the [[Module _CustomFields_Dev|CustomFields developpers documentation]] for the instructions on how to implement the support of a new module in CustomFields (beware: it may require some php abilities in the worst case scenario when hooks and triggers are not yet implemented in the module).
 
Please read the [[Module _CustomFields_Dev|CustomFields developpers documentation]] for the instructions on how to implement the support of a new module in CustomFields (beware: it may require some php abilities in the worst case scenario when hooks and triggers are not yet implemented in the module).
   −
= Example cases =
+
=Example cases=
    
You can find a compilation of concrete, practical examples on the [[Module_CustomFields_Cases]] wiki page.
 
You can find a compilation of concrete, practical examples on the [[Module_CustomFields_Cases]] wiki page.
   −
= Exporting and importing your CustomFields =
+
=Exporting and importing your CustomFields=
    
If you want to export your custom fields into another database, or just make a backup, please carefully read this chapter.
 
If you want to export your custom fields into another database, or just make a backup, please carefully read this chapter.
   −
== Exporting your SQL data ==
+
==Exporting and importing in CSV (Excel) via Dolibarr tools==
 +
 
 +
The values of your custom fields can be imported/exported via Dolibarr. Just go to tools > export or import, and then select the module you wish to export/import. Custom fields will automatically be injected into the list of exported/imported fields. Just follow the exporting/importing instructions as usual. Custom fields cannot be exported/imported separately from the module they are related to, you need to export them via the parent module.
 +
 
 +
A nice feature is that you will be able to filter the values out when exporting. Most custom fields types support filtering (such as Text and Constrained), so that you can easily filter your CSV export given a specific value of a custom field, just like any other Dolibarr field.
 +
 
 +
This will allow you to keep your custom fields values in CSV format, readable by Excel. However, you should not rely only on this method to keep a backup of your database, the CSV export/import is better used when you just need to hand your records to a collaborator not using Dolibarr (for example your accountant), but for a regular backup of your Dolibarr system along with your custom fields, you should follow the other instructions below.
 +
 
 +
Note: if you want to import custom fields in CSV format, you need to create a custom field named "import_key" for each module you want custom fields to be imported to. This field is required by the Dolibarr's import tool to store metadata about the import. You can safely delete the import_key custom fields after your import is completed.
 +
 
 +
Note2: importing CustomFields in CSV only works for Dolibarr >= v3.7. You can however port the changes required to any version of Dolibarr below 3.7, by applying the changes in this patch (only 3 additions and 1 deletion):
 +
 
 +
https://github.com/Dolibarr/dolibarr/pull/2386/files
 +
 
 +
==Exporting your SQL data==
    
CustomFields stores all its datas and your custom fields configurations directly inside the database.
 
CustomFields stores all its datas and your custom fields configurations directly inside the database.
Line 743: Line 1,007:  
Note: please note that you should set FOREIGN_KEY_CHECKS = 0 when exporting any Dolibarr's or CustomFields SQL table (please read the Dolibarr wiki about [[Backups|Database Backups]] for a more extensive guide).
 
Note: please note that you should set FOREIGN_KEY_CHECKS = 0 when exporting any Dolibarr's or CustomFields SQL table (please read the Dolibarr wiki about [[Backups|Database Backups]] for a more extensive guide).
   −
== Exporting your CustomFields files ==
+
==Exporting your customized CustomFields files==
    
Although CustomFields stores as much as possible its configuration in the database, to give you more freedom of extensibility, there are a few configuration files that are stored directly inside the CustomFields directory.
 
Although CustomFields stores as much as possible its configuration in the database, to give you more freedom of extensibility, there are a few configuration files that are stored directly inside the CustomFields directory.
Line 751: Line 1,015:  
To be more specific, the main files that you should backup are:
 
To be more specific, the main files that you should backup are:
   −
* The overloading functions file if you use overloading functions to manage some of your custom fields, it is located at /htdocs/customfields/fields/customfields_fields_extend.lib.php
+
*The overloading functions and custom AJAX files if you use overloading functions or custom AJAX to manage some of your custom fields. They are both located inside the /htdocs/customfields/fields/ folder, so that you can just backup the fields folder and you're good to go.
   −
* The languages files if you have translated the labels of your custom fields, which are located inside the following folder: /htdocs/customfields/langs/
+
*The languages files if you have translated the labels of your custom fields, which are located inside the following folder: /htdocs/customfields/langs/
   −
== Updating your Dolibarr/CustomFields ==
+
=Updating your Dolibarr/CustomFields=
    
CustomFields was designed to be totally independent from Dolibarr so you don't have to worry when you're updating your Dolibarr install.
 
CustomFields was designed to be totally independent from Dolibarr so you don't have to worry when you're updating your Dolibarr install.
   −
Also, you can easily update your CustomFields install by just replacing the old files (just make sure that you've made a backup of your modified files, see the previous chapter). After you updated your CustomFields files, you should '''disable then re enable CustomFields''' in the Dolibarr's modules administration page: this is necessary to refresh some of the global parameters.
+
Also, you can easily update your CustomFields install by just replacing the old files (just make sure that you've made a backup of your modified CustomFields fields and langs files, see the previous chapter). After you updated your CustomFields files, you should '''disable then re enable CustomFields''' in the Dolibarr's modules administration page: this is necessary to refresh some of the global parameters.
   −
= Troubleshooting =
+
=Troubleshooting=
   −
== General advices for troubleshooting ==
+
==General advices for troubleshooting==
    
If you encounter an error (script not functionning, blank page, etc...), please '''enable php warnings and error notices''' and post the errors on the forum if you can't find the solution here or by yourself.
 
If you encounter an error (script not functionning, blank page, etc...), please '''enable php warnings and error notices''' and post the errors on the forum if you can't find the solution here or by yourself.
Line 791: Line 1,055:  
</source>
 
</source>
   −
== Q: I have installed CustomFields but it doesn't show up in the modules administration panel ==
+
==Q: I have installed CustomFields but it doesn't show up in the modules administration panel==
 
A: You probably copied the CustomFields files in the wrong place. Please check that the customfields and customfieldspdftest folders are located just under /dolibarr/htdocs/, or if you have specified an alternate folder in your conf.php file ($dolibarr_main_document_root_alt), place the folders inside this path.
 
A: You probably copied the CustomFields files in the wrong place. Please check that the customfields and customfieldspdftest folders are located just under /dolibarr/htdocs/, or if you have specified an alternate folder in your conf.php file ($dolibarr_main_document_root_alt), place the folders inside this path.
    
Details: For any Dolibarr module to be shown on the Dolibarr's Modules Administration Panel, the only necessary thing is that Dolibarr must find the module descriptor file at the correct place (and with the correct syntax). Since the syntax is taken care of by the developer, if you can't see the module in the admin panel, you should check if you have copied the CustomFields files in the correct location.
 
Details: For any Dolibarr module to be shown on the Dolibarr's Modules Administration Panel, the only necessary thing is that Dolibarr must find the module descriptor file at the correct place (and with the correct syntax). Since the syntax is taken care of by the developer, if you can't see the module in the admin panel, you should check if you have copied the CustomFields files in the correct location.
   −
== Q: I'm trying to edit a constrained customfield parameters in the admin configuration page, but everytime I change the constraint it goes back to None ? ==
+
==Q: I'm trying to edit a constrained customfield parameters in the admin configuration page, but everytime I change the constraint it goes back to None ?==
 
A: This is behaviour is probably due to some of your records containing an illegal value for the new constraint. For example, if you switch your customfield's constraint from your products' table containing 100 products to the llx_users table containing 2 users, the database won't know what to do with the illegal values higher than 2, so it won't accept the new constraint and set to None.
 
A: This is behaviour is probably due to some of your records containing an illegal value for the new constraint. For example, if you switch your customfield's constraint from your products' table containing 100 products to the llx_users table containing 2 users, the database won't know what to do with the illegal values higher than 2, so it won't accept the new constraint and set to None.
 
In this case, just edit yourself the illegal values, either by fixing them or just deleting all the values for this customfields (but in this case you can just delete the custom field and recreate it, this will indeed delete all values and leave you free to recreate the field with a different constraint).
 
In this case, just edit yourself the illegal values, either by fixing them or just deleting all the values for this customfields (but in this case you can just delete the custom field and recreate it, this will indeed delete all values and leave you free to recreate the field with a different constraint).
   −
== Q: I'm trying to delete a constrained customfield in the admin configuration page, but it doesn't work! ==
+
==Q: I'm trying to delete a constrained customfield in the admin configuration page, but it doesn't work!==
 
A: This is a normal behaviour. This means that there are a few items in dolibarr (invoices/propale/orders or whatever module you're using this customfield with) that still use this constrained field, and to protect the integrity of your database, your DBMS prevent the deletion.
 
A: This is a normal behaviour. This means that there are a few items in dolibarr (invoices/propale/orders or whatever module you're using this customfield with) that still use this constrained field, and to protect the integrity of your database, your DBMS prevent the deletion.
 
Simple fix: either reset to an NULL (empty) value all items using the constrained field, or either delete manually in your DBMS (eg: using phpmyadmin) the constraints and then the field.
 
Simple fix: either reset to an NULL (empty) value all items using the constrained field, or either delete manually in your DBMS (eg: using phpmyadmin) the constraints and then the field.
Line 821: Line 1,085:  
</source>
 
</source>
   −
== Q: I have a big problem with my fields, and I want to delete all the fields and reinitialize the customfields table ==
+
==Q: I have a big problem with my fields, and I want to delete all the fields and reinitialize the customfields table==
    
If you have a big problem with a module's custom fields, you may want to start from scratch by deleting the entire custom fields table.
 
If you have a big problem with a module's custom fields, you may want to start from scratch by deleting the entire custom fields table.
Line 832: Line 1,096:  
</source>
 
</source>
   −
== Q: CustomFields produces a lot of weird errors anywhere I go even when it is disabled, what should I do? ==
+
==Q: CustomFields produces a lot of weird errors anywhere I go even when it is disabled, what should I do?==
    
CustomFields, but also Dolibarr, expects the database columns to be all lowercase, but on a few systems the result may be returned in uppercase or mixed-case.
 
CustomFields, but also Dolibarr, expects the database columns to be all lowercase, but on a few systems the result may be returned in uppercase or mixed-case.
Line 842: Line 1,106:  
Eg: For MySQL, check the '''lower_case_table_names''' system variable (check the MySQL manual at '''identifier-case-sensitivity''').
 
Eg: For MySQL, check the '''lower_case_table_names''' system variable (check the MySQL manual at '''identifier-case-sensitivity''').
   −
== Q: Whenever I try to create a custom field or a record, I get an error "Duplicate entry '1' for key 'PRIMARY'" ==
+
==Q: Whenever I try to create a custom field or a record, I get an error "Duplicate entry '1' for key 'PRIMARY'"==
    
Unluckily, this is one of the worst error you can ever encounter :( This error means that the DBMS can't resolve the primary key checks, and it finds a duplicate even if it shouldn't.
 
Unluckily, this is one of the worst error you can ever encounter :( This error means that the DBMS can't resolve the primary key checks, and it finds a duplicate even if it shouldn't.
    
This is something that generally happens when either:
 
This is something that generally happens when either:
* Your SQL queries are malformed, or you are trying to issue a SQL query that the DBMS does not support (DBMS are quite a deal behind the SQL standard in terms of functionnalities).
+
 
* Your database is corrupted
+
*Your SQL queries are malformed, or you are trying to issue a SQL query that the DBMS does not support (DBMS are quite a deal behind the SQL standard in terms of functionnalities).
 +
*Your database is corrupted
    
Since CustomFields was made and extensively tested to avoid malformed SQL queries, it is probable that your database got corrupted. There are various ways to fix this error, but one of the most working solution is to:
 
Since CustomFields was made and extensively tested to avoid malformed SQL queries, it is probable that your database got corrupted. There are various ways to fix this error, but one of the most working solution is to:
* First try to run '''mysqlcheck'''
+
 
* If that didn't work out, then first export a backup of your database in a .sql file, then drop your database altogether, and import your backup back into your DBMS. This should fix the problem.
+
*First try to run '''mysqlcheck'''
 +
*If that didn't work out, then first export a backup of your database in a .sql file, then drop your database altogether, and import your backup back into your DBMS. This should fix the problem.
    
For more informations, here is an interesting thread:
 
For more informations, here is an interesting thread:
 
softwareprojects dot com/resources/programming/t-how-to-fix-mysql-duplicate-entry-for-key-primary-o-1844.html
 
softwareprojects dot com/resources/programming/t-how-to-fix-mysql-duplicate-entry-for-key-primary-o-1844.html
   −
== Q: CustomFields Pro is VERY slow when it is enabled, even on modules datasheet where no custom field was created! (aka INFORMATION_SCHEMA slowness) ==
+
==Q: CustomFields Pro is VERY slow when it is enabled, even on modules datasheet where no custom field was created! (aka INFORMATION_SCHEMA slowness)==
    
Note the characteristic definition of this problem: CustomFields Pro slows down every datasheet and creation page, even when not any custom field were created for the module!
 
Note the characteristic definition of this problem: CustomFields Pro slows down every datasheet and creation page, even when not any custom field were created for the module!
676

edits