From d2650d31cf167026d7ffcb0af6e1c42f44ae2814 Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Thu, 11 Mar 2021 09:50:05 +0100 Subject: [PATCH 01/79] add multicompany module --- htdocs/custom/multicompany/COPYING | 674 + htdocs/custom/multicompany/ChangeLog.md | 335 + htdocs/custom/multicompany/INSTALL | 16 + htdocs/custom/multicompany/README | 11 + htdocs/custom/multicompany/README.md | 36 + htdocs/custom/multicompany/README_FR | 14 + htdocs/custom/multicompany/admin/about.php | 76 + htdocs/custom/multicompany/admin/caches.php | 103 + htdocs/custom/multicompany/admin/index.html | 0 .../multicompany/admin/multicompany.php | 131 + .../admin/multicompany_extrafields.php | 115 + htdocs/custom/multicompany/admin/options.php | 494 + .../multicompany/admin/tpl/caches.tpl.php | 118 + .../multicompany/admin/tpl/card.tpl.php | 386 + .../custom/multicompany/admin/tpl/index.html | 0 .../multicompany/admin/tpl/list.tpl.php | 230 + .../multicompany/admin/tpl/switch.tpl.php | 122 + .../class/actions_multicompany.class.php | 4608 +++++ .../class/api_multicompany.class.php | 334 + .../class/dao_multicompany.class.php | 990 + htdocs/custom/multicompany/class/index.html | 0 .../custom/multicompany/class/ssp.class.php | 412 + .../multicompany/core/ajax/functions.php | 286 + .../custom/multicompany/core/ajax/index.html | 0 htdocs/custom/multicompany/core/ajax/list.php | 248 + htdocs/custom/multicompany/core/js/index.html | 0 .../custom/multicompany/core/js/lib_head.js | 214 + .../multicompany/core/login/functions_mc.php | 166 + .../custom/multicompany/core/login/index.html | 0 .../multicompany/core/modules/index.html | 0 .../core/modules/modMultiCompany.class.php | 587 + .../multicompany/core/triggers/index.html | 0 ...ulticompany_MulticompanyWorkflow.class.php | 86 + .../custom/multicompany/css/dropdown.inc.php | 199 + htdocs/custom/multicompany/css/index.html | 0 .../multicompany/css/multicompany.css.php | 355 + htdocs/custom/multicompany/img/gplv3.png | Bin 0 -> 2666 bytes htdocs/custom/multicompany/img/index.html | 0 htdocs/custom/multicompany/img/inodbox.png | Bin 0 -> 6316 bytes .../custom/multicompany/img/multicompany.png | Bin 0 -> 4380 bytes .../multicompany/img/object_multicompany.png | Bin 0 -> 1269 bytes .../img/object_multicompany_eldy.png | Bin 0 -> 972 bytes .../img/object_multicompany_md.png | Bin 0 -> 954 bytes .../buttons/css/buttons.dataTables.css | 354 + .../buttons/css/buttons.dataTables.min.css | 1 + .../inc/datatables/buttons/css/common.scss | 27 + .../inc/datatables/buttons/css/mixins.scss | 136 + .../datatables/buttons/js/buttons.colVis.js | 206 + .../buttons/js/buttons.colVis.min.js | 6 + .../datatables/buttons/js/buttons.flash.js | 1441 ++ .../datatables/buttons/js/buttons.html5.js | 1370 ++ .../buttons/js/buttons.html5.min.js | 26 + .../datatables/buttons/js/buttons.print.js | 194 + .../buttons/js/buttons.print.min.js | 4 + .../buttons/js/dataTables.buttons.js | 1705 ++ .../buttons/js/dataTables.buttons.min.js | 37 + .../inc/datatables/css/jquery.dataTables.css | 455 + .../datatables/css/jquery.dataTables.min.css | 1 + .../inc/datatables/images/sort_asc.png | Bin 0 -> 160 bytes .../datatables/images/sort_asc_disabled.png | Bin 0 -> 148 bytes .../inc/datatables/images/sort_both.png | Bin 0 -> 201 bytes .../inc/datatables/images/sort_desc.png | Bin 0 -> 158 bytes .../datatables/images/sort_desc_disabled.png | Bin 0 -> 146 bytes .../multicompany/inc/datatables/index.html | 0 .../inc/datatables/js/jquery.dataTables.js | 15345 ++++++++++++++++ .../datatables/js/jquery.dataTables.min.js | 167 + .../responsive/css/responsive.dataTables.css | 178 + .../css/responsive.dataTables.min.css | 1 + .../responsive/js/dataTables.responsive.js | 1255 ++ .../js/dataTables.responsive.min.js | 26 + htdocs/custom/multicompany/inc/index.html | 0 .../multicompany/inc/multiselect/CHANGELOG.md | 25 + .../multicompany/inc/multiselect/LICENSE | 22 + .../multicompany/inc/multiselect/README.md | 66 + .../inc/multiselect/css/bootstrap-iso.min.css | 7 + .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 20127 bytes .../fonts/glyphicons-halflings-regular.svg | 288 + .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 45404 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 23424 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes .../inc/multiselect/js/bootstrap.min.js | 7 + .../inc/multiselect/js/multiselect.js | 813 + .../inc/multiselect/js/multiselect.min.js | 11 + htdocs/custom/multicompany/index.html | 0 .../langs/ca_ES/multicompany.lang | 250 + .../langs/de_AT/multicompany.lang | 250 + .../langs/de_CH/multicompany.lang | 250 + .../langs/de_DE/multicompany.lang | 250 + .../langs/en_GB/multicompany.lang | 250 + .../langs/en_US/multicompany.lang | 250 + .../langs/es_CL/multicompany.lang | 250 + .../langs/es_ES/multicompany.lang | 250 + .../langs/es_MX/multicompany.lang | 250 + .../langs/fr_FR/multicompany.lang | 250 + .../langs/hu_HU/multicompany.lang | 250 + htdocs/custom/multicompany/langs/index.html | 0 .../langs/it_IT/multicompany.lang | 250 + .../langs/nl_NL/multicompany.lang | 250 + .../langs/pt_PT/multicompany.lang | 250 + .../lib/PHP_Markdown/License.text | 36 + .../multicompany/lib/PHP_Markdown/Readme.text | 777 + .../multicompany/lib/PHP_Markdown/index.html | 0 .../lib/PHP_Markdown/markdown.php | 1732 ++ htdocs/custom/multicompany/lib/index.html | 0 .../multicompany/lib/multicompany.lib.php | 484 + .../sql/dict/init_new_entity_c_paiement.sql | 37 + .../dict/init_new_entity_c_payment_term.sql | 42 + htdocs/custom/multicompany/sql/index.html | 0 .../multicompany/sql/init_new_entity.sql | 68 + .../sql/init_new_entity_nocrypt.sql | 68 + .../multicompany/sql/llx_entity.key.sql | 23 + htdocs/custom/multicompany/sql/llx_entity.sql | 33 + .../sql/llx_entity_extrafields.sql | 26 + .../sql/llx_entity_thirdparty.key.sql | 24 + .../sql/llx_entity_thirdparty.sql | 27 + .../multicompany/sql/update_3.1.0-3.2.0.sql | 8 + .../multicompany/sql/update_3.6.0-3.7.0.sql | 14 + .../multicompany/sql/update_3.8.0-3.9.0.sql | 20 + .../multicompany/sql/update_5.0.0-6.0.0.sql | 14 + 119 files changed, 42453 insertions(+) create mode 100755 htdocs/custom/multicompany/COPYING create mode 100755 htdocs/custom/multicompany/ChangeLog.md create mode 100755 htdocs/custom/multicompany/INSTALL create mode 100755 htdocs/custom/multicompany/README create mode 100755 htdocs/custom/multicompany/README.md create mode 100755 htdocs/custom/multicompany/README_FR create mode 100755 htdocs/custom/multicompany/admin/about.php create mode 100755 htdocs/custom/multicompany/admin/caches.php create mode 100755 htdocs/custom/multicompany/admin/index.html create mode 100755 htdocs/custom/multicompany/admin/multicompany.php create mode 100755 htdocs/custom/multicompany/admin/multicompany_extrafields.php create mode 100755 htdocs/custom/multicompany/admin/options.php create mode 100755 htdocs/custom/multicompany/admin/tpl/caches.tpl.php create mode 100755 htdocs/custom/multicompany/admin/tpl/card.tpl.php create mode 100755 htdocs/custom/multicompany/admin/tpl/index.html create mode 100755 htdocs/custom/multicompany/admin/tpl/list.tpl.php create mode 100755 htdocs/custom/multicompany/admin/tpl/switch.tpl.php create mode 100755 htdocs/custom/multicompany/class/actions_multicompany.class.php create mode 100755 htdocs/custom/multicompany/class/api_multicompany.class.php create mode 100755 htdocs/custom/multicompany/class/dao_multicompany.class.php create mode 100755 htdocs/custom/multicompany/class/index.html create mode 100755 htdocs/custom/multicompany/class/ssp.class.php create mode 100755 htdocs/custom/multicompany/core/ajax/functions.php create mode 100755 htdocs/custom/multicompany/core/ajax/index.html create mode 100755 htdocs/custom/multicompany/core/ajax/list.php create mode 100755 htdocs/custom/multicompany/core/js/index.html create mode 100755 htdocs/custom/multicompany/core/js/lib_head.js create mode 100755 htdocs/custom/multicompany/core/login/functions_mc.php create mode 100755 htdocs/custom/multicompany/core/login/index.html create mode 100755 htdocs/custom/multicompany/core/modules/index.html create mode 100755 htdocs/custom/multicompany/core/modules/modMultiCompany.class.php create mode 100755 htdocs/custom/multicompany/core/triggers/index.html create mode 100755 htdocs/custom/multicompany/core/triggers/interface_25_modMulticompany_MulticompanyWorkflow.class.php create mode 100755 htdocs/custom/multicompany/css/dropdown.inc.php create mode 100755 htdocs/custom/multicompany/css/index.html create mode 100755 htdocs/custom/multicompany/css/multicompany.css.php create mode 100755 htdocs/custom/multicompany/img/gplv3.png create mode 100755 htdocs/custom/multicompany/img/index.html create mode 100755 htdocs/custom/multicompany/img/inodbox.png create mode 100755 htdocs/custom/multicompany/img/multicompany.png create mode 100755 htdocs/custom/multicompany/img/object_multicompany.png create mode 100755 htdocs/custom/multicompany/img/object_multicompany_eldy.png create mode 100755 htdocs/custom/multicompany/img/object_multicompany_md.png create mode 100755 htdocs/custom/multicompany/inc/datatables/buttons/css/buttons.dataTables.css create mode 100755 htdocs/custom/multicompany/inc/datatables/buttons/css/buttons.dataTables.min.css create mode 100755 htdocs/custom/multicompany/inc/datatables/buttons/css/common.scss create mode 100755 htdocs/custom/multicompany/inc/datatables/buttons/css/mixins.scss create mode 100755 htdocs/custom/multicompany/inc/datatables/buttons/js/buttons.colVis.js create mode 100755 htdocs/custom/multicompany/inc/datatables/buttons/js/buttons.colVis.min.js create mode 100755 htdocs/custom/multicompany/inc/datatables/buttons/js/buttons.flash.js create mode 100755 htdocs/custom/multicompany/inc/datatables/buttons/js/buttons.html5.js create mode 100755 htdocs/custom/multicompany/inc/datatables/buttons/js/buttons.html5.min.js create mode 100755 htdocs/custom/multicompany/inc/datatables/buttons/js/buttons.print.js create mode 100755 htdocs/custom/multicompany/inc/datatables/buttons/js/buttons.print.min.js create mode 100755 htdocs/custom/multicompany/inc/datatables/buttons/js/dataTables.buttons.js create mode 100755 htdocs/custom/multicompany/inc/datatables/buttons/js/dataTables.buttons.min.js create mode 100755 htdocs/custom/multicompany/inc/datatables/css/jquery.dataTables.css create mode 100755 htdocs/custom/multicompany/inc/datatables/css/jquery.dataTables.min.css create mode 100755 htdocs/custom/multicompany/inc/datatables/images/sort_asc.png create mode 100755 htdocs/custom/multicompany/inc/datatables/images/sort_asc_disabled.png create mode 100755 htdocs/custom/multicompany/inc/datatables/images/sort_both.png create mode 100755 htdocs/custom/multicompany/inc/datatables/images/sort_desc.png create mode 100755 htdocs/custom/multicompany/inc/datatables/images/sort_desc_disabled.png create mode 100755 htdocs/custom/multicompany/inc/datatables/index.html create mode 100755 htdocs/custom/multicompany/inc/datatables/js/jquery.dataTables.js create mode 100755 htdocs/custom/multicompany/inc/datatables/js/jquery.dataTables.min.js create mode 100755 htdocs/custom/multicompany/inc/datatables/responsive/css/responsive.dataTables.css create mode 100755 htdocs/custom/multicompany/inc/datatables/responsive/css/responsive.dataTables.min.css create mode 100755 htdocs/custom/multicompany/inc/datatables/responsive/js/dataTables.responsive.js create mode 100755 htdocs/custom/multicompany/inc/datatables/responsive/js/dataTables.responsive.min.js create mode 100755 htdocs/custom/multicompany/inc/index.html create mode 100755 htdocs/custom/multicompany/inc/multiselect/CHANGELOG.md create mode 100755 htdocs/custom/multicompany/inc/multiselect/LICENSE create mode 100755 htdocs/custom/multicompany/inc/multiselect/README.md create mode 100755 htdocs/custom/multicompany/inc/multiselect/css/bootstrap-iso.min.css create mode 100755 htdocs/custom/multicompany/inc/multiselect/fonts/glyphicons-halflings-regular.eot create mode 100755 htdocs/custom/multicompany/inc/multiselect/fonts/glyphicons-halflings-regular.svg create mode 100755 htdocs/custom/multicompany/inc/multiselect/fonts/glyphicons-halflings-regular.ttf create mode 100755 htdocs/custom/multicompany/inc/multiselect/fonts/glyphicons-halflings-regular.woff create mode 100755 htdocs/custom/multicompany/inc/multiselect/fonts/glyphicons-halflings-regular.woff2 create mode 100755 htdocs/custom/multicompany/inc/multiselect/js/bootstrap.min.js create mode 100755 htdocs/custom/multicompany/inc/multiselect/js/multiselect.js create mode 100755 htdocs/custom/multicompany/inc/multiselect/js/multiselect.min.js create mode 100755 htdocs/custom/multicompany/index.html create mode 100755 htdocs/custom/multicompany/langs/ca_ES/multicompany.lang create mode 100755 htdocs/custom/multicompany/langs/de_AT/multicompany.lang create mode 100755 htdocs/custom/multicompany/langs/de_CH/multicompany.lang create mode 100755 htdocs/custom/multicompany/langs/de_DE/multicompany.lang create mode 100755 htdocs/custom/multicompany/langs/en_GB/multicompany.lang create mode 100755 htdocs/custom/multicompany/langs/en_US/multicompany.lang create mode 100755 htdocs/custom/multicompany/langs/es_CL/multicompany.lang create mode 100755 htdocs/custom/multicompany/langs/es_ES/multicompany.lang create mode 100755 htdocs/custom/multicompany/langs/es_MX/multicompany.lang create mode 100755 htdocs/custom/multicompany/langs/fr_FR/multicompany.lang create mode 100755 htdocs/custom/multicompany/langs/hu_HU/multicompany.lang create mode 100755 htdocs/custom/multicompany/langs/index.html create mode 100755 htdocs/custom/multicompany/langs/it_IT/multicompany.lang create mode 100755 htdocs/custom/multicompany/langs/nl_NL/multicompany.lang create mode 100755 htdocs/custom/multicompany/langs/pt_PT/multicompany.lang create mode 100755 htdocs/custom/multicompany/lib/PHP_Markdown/License.text create mode 100755 htdocs/custom/multicompany/lib/PHP_Markdown/Readme.text create mode 100755 htdocs/custom/multicompany/lib/PHP_Markdown/index.html create mode 100755 htdocs/custom/multicompany/lib/PHP_Markdown/markdown.php create mode 100755 htdocs/custom/multicompany/lib/index.html create mode 100755 htdocs/custom/multicompany/lib/multicompany.lib.php create mode 100755 htdocs/custom/multicompany/sql/dict/init_new_entity_c_paiement.sql create mode 100755 htdocs/custom/multicompany/sql/dict/init_new_entity_c_payment_term.sql create mode 100755 htdocs/custom/multicompany/sql/index.html create mode 100755 htdocs/custom/multicompany/sql/init_new_entity.sql create mode 100755 htdocs/custom/multicompany/sql/init_new_entity_nocrypt.sql create mode 100755 htdocs/custom/multicompany/sql/llx_entity.key.sql create mode 100755 htdocs/custom/multicompany/sql/llx_entity.sql create mode 100755 htdocs/custom/multicompany/sql/llx_entity_extrafields.sql create mode 100755 htdocs/custom/multicompany/sql/llx_entity_thirdparty.key.sql create mode 100755 htdocs/custom/multicompany/sql/llx_entity_thirdparty.sql create mode 100755 htdocs/custom/multicompany/sql/update_3.1.0-3.2.0.sql create mode 100755 htdocs/custom/multicompany/sql/update_3.6.0-3.7.0.sql create mode 100755 htdocs/custom/multicompany/sql/update_3.8.0-3.9.0.sql create mode 100755 htdocs/custom/multicompany/sql/update_5.0.0-6.0.0.sql diff --git a/htdocs/custom/multicompany/COPYING b/htdocs/custom/multicompany/COPYING new file mode 100755 index 00000000000..94a9ed024d3 --- /dev/null +++ b/htdocs/custom/multicompany/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/htdocs/custom/multicompany/ChangeLog.md b/htdocs/custom/multicompany/ChangeLog.md new file mode 100755 index 00000000000..c1860df345f --- /dev/null +++ b/htdocs/custom/multicompany/ChangeLog.md @@ -0,0 +1,335 @@ +# ChangeLog MULTICOMPANY + +## 12.0.1 + +NEW add stock warehouse sharing list +NEW add triggers create, update, delete +FIX uniformize trigger +FIX uniformize extrafields management + +## 12.0.0 + +FIX compatibility with Dolibarr 12 +FIX look and feel V12 + +## 11.0.2 + +NEW add stock warehouse sharing list + +## 11.0.1 + +FIX form is not printed to addgroups on user card in Dolibarr 11.0 + +## 11.0.0 + +FIX compatibility with Dolibarr 11 +FIX better warning for upgrade message + +## 10.0.3 + +NEW add templates of entities management +NEW pre-format modules and shares of new entities with templates +NEW possibility to duplicate usergroup rights by entities in transversal mode +NEW add label of current entity in right top menu + +## 10.0.1.3 + +FIX compatibility with Two-Factor Authentication module + +## 10.0.1.2 + +FIX missing rename facture ref field (ref instead facnumber) + +## 10.0.1.1 + +FIX wrong Font Awesome css class for check/uncheck button + +## 10.0.1 + +FIX wrong sql request for show users in transversal mode + +## 10.0.0 + +NEW add dropdown menu (look and feel v10) +NEW change logo and background of entity in login page +FIX compatibility with Dolibarr 10 + +## 9.0.4 + +FIX wrong sql request for show users in transversal mode + +## 9.0.3 + +FIX display rights of allowed entity for user when it's not entity 1 on perms card + +## 9.0.2 + +FIX better test for compatibility with multiple Dolibarr versions + +## 9.0.1 + +FIX superadmin can always edit groups of another entities +FIX need php 5.6 min +FIX possibility to hide html title with constant MULTICOMPANY\_HIDE\_HTML\_TITLE +FIX translation + +## 9.0.0 + +NEW add customer invoices sharing +NEW add proposal numbering sharing +NEW an external plugin can easily include its own sharing settings +NEW add buttons to stay in entity card +FIX compatibility between proposal sharing and proposalnumber sharing +FIX compatibility between invoice sharing and invoicenumber sharing +FIX possibility to use a different referrer for numbering sharing +FIX compatibility with Dolibarr 9 + +## 8.0.6 + +FIX backport from newest version for avoid error + +## 8.0.5.4 + +FIX display rights of allowed entity for user when it's not entity 1 on perms card + +## 8.0.5.3 + +FIX Make retrocompatibility for external modules using old method + +## 8.0.5.2 + +FIX when using switchentityautoopen, this avoid to have the autopen always after first use + +## 8.0.5.1 + +FIX missing cashdesk module authentication + +## 8.0.5 + +FIX better check entities in user permissions tab + +## 8.0.4 + +FIX autoopen of the "switch entity popup" was broken (used by DoliDroid) +FIX version checking refactorization + +## 8.0.3 + +FIX missing "printUserPasswordField" hook for mc authentication + +## 8.0.2 + +FIX use POST instead GET for avoid false positive error with firewall (datatables) +FIX avoid error when SHMOP cache is used + +## 8.0.1 + +FIX Look and feel v8 + +## 8.0.0 + +NEW can share leave requests - holidays +NEW ad possibility to change third party entity +NEW add customer proposals sharing with read/write permissions +NEW add read/write permissions for products/services sharing +NEW add entity field in products/services list +NEW add entity field in third parties list +NEW add entity field in customer proposals list +NEW add entity information in banner of elements sharing +NEW add warning message when hide the entity in login page +NEW add warning message if user not linked with group/entity (transversal mode) +NEW change icons add specific icon by theme +NEW Can set a parameter switchentityautoopen=1 on any urls to force open of the switch entity box, with no need to click: +- This is required to provide a compatibility with native android application when menu is not managed by Dolibarr but by the android application + +NEW change multiselect library +NEW add product reseller prices sharing +NEW add new parameters for enable and make visible an entity by default + +FIX compatibility with Dolibarr 8 +FIX better redirection when you switch to another entity +FIX better user/group management in transversal mode +FIX many improvements and fixes for look and performance + +## 7.0.4 + +FIX use POST instead GET for avoid false positive error with firewall (datatables) +FIX avoid error when SHMOP cache is used + +## 7.0.3 + +Fix: datatables error when "multicompany" directory is in root of dolibarr +Fix: use REQUEST_URI by default when switch to another entity +Fix: use dol_include_once() by default + +## 7.0.2 + +Fix: broken feature when dropdown list in login page is hidden + +## 7.0.1 + +Fix: hide dictionnaries sharings for the moment + +## 7.0.0 + +Fix: compatibility with Dolibarr 7 +New: add cache system (memcached) +New: use datatables for entities list +New: add multiselect entities for rights management in transverse mode + +## 6.0.1 + +Fix: compatibility with Dolibarr 7 + +## 6.0.0 + +Fix: compatibility with Dolibarr 6 +New: add members sharing +New: add possibility to customizing dictionnaries by entity (llx\_c\_paiement and llc\_c\_payment\_term) +New: getEntity function use true $shared value by default +New: big refactorization of transverse mode + +Improvements to the transverse mode: +- A module activated in the main entity is no longer activated in the child entities, each entity can have its own modules activated. +- You can define different rights per entity in the same group. +- You can customize/supplement the rights of a user by entity + +For developers: +* You can remove $multicompany_transverse_mode in conf.php +* Use $conf->global->MULTICOMPANY\_TRANSVERSE\_MODE instead $conf->multicompany->transverse_mode +* Use getEntity('xxx') instead getEntity('xxx', 1) and use getEntity('xxx', 0) instead getEntity('xxx') +* Use getEntity('thirdparty') instead getEntity('societe') +* Use getEntity('member') instead getEntity('adherent') +* Use getEntity('bankaccount') instead getEntity('bank_account') + +## 5.0.0 + +Fix: compatibility with Dolibarr 5 +New: add expense report sharing + +## 4.0.0 + +Fix: compatibility with Dolibarr 4 +New: add project sharing + +## 3.8.2 + +Fix: compatibility with transverse modes + +## 3.8.1 + +Fix: folder sharing was not working when more than 2 entities + +## 3.8.0 + +Fix: compatibility with Dolibarr 3.8.x + +## 3.7.3 + +Fix: folder sharing was not working when more than 2 entities + +## 3.7.2 + +New: add transifex management +New: change the development platform + +## 3.7.1 + +New: add extrafields +Fix: more bugs + +## 3.7.0 + +Fix: compatibility with Dolibarr 3.7.x +New: add invoice number sharing +New: add script to move master entity with another entity +New: add about page + +## 3.6.2 + +Fix: folder sharing was not working when more than 2 entities + +## 3.6.1 + +Fix: add stock sharing parameters + +## 3.6.0 + +Fix: compatibility with Dolibarr 3.6.x +Fix: show entities combobox only in transverse mode or with admin users +Fix: automatic connection to the entity of the user if the drop down list of entities is hidden (use different login strictly by entity) +New: add multicompany function login + +## 3.5.0 + +Fix: compatibility with Dolibarr 3.5.0 + +## 3.4.0 + +New: add bank sharing +New: add product prices sharing +New: add agenda sharing +New: add stock sharing +New: add Hungary translation +Fix: compatibility with Dolibarr 3.4 +Fix: grant access for user card in transverse mode +Fix: sharing services was not functional if the module product was not activated +Fix: more bugs + +## 3.2.2 + +New: add Netherland translation +Fix: minor bugs and uniformize code +Fix: add check method for login +Fix: check permission in combobox +Fix: remove constantes already defined by module +Fix: compatibility with bureau2crea theme +Fix: possibility to force entity un login page +Fix: bad rights verification + +## 3.2.1 + +no release + +## 3.2.0 + +New: add sharing system for products/services and thirdparties/contacts between entities +New: add category sharing between entities +Fix: problem with user card access and wrong carriage return +Fix: show login page options with hook manager +Fix: update es\_ES and ca\_ES translations +Fix: replace serialize by json +Fix: security +Fix: more bugs + +## 3.1.2 + +Fix: invalid path if you do not use the custom directory + +## 3.1.1 + +Fix: convert current admin to superadmin +The administrator of the primary entity was not converted into superadministrator when activating the module, +this happened during an update of a version of Dolibarr < 3.1 to >= 3.1 + +## 3.1.0 + +New: change logo +New: add italian translation +New: stay connected for switch entity +New: add options tab in module configuration +New: possibility to hide combobox in login page +New: add transverse mode +* Off mode: The rights and groups are managed in each entity: users belong to the entity for their rights +* One mode: Groups can only belong to the entity = 0 and that the user belongs to a particular entity + +Fix: translation + +## 3.0.1 + +New: add spanish translation +Fix: minor bugfix + +## 3.0.0 + +First release of this module diff --git a/htdocs/custom/multicompany/INSTALL b/htdocs/custom/multicompany/INSTALL new file mode 100755 index 00000000000..7e987f02a8f --- /dev/null +++ b/htdocs/custom/multicompany/INSTALL @@ -0,0 +1,16 @@ +INSTALL +------- + +Since version 3 it is possible to define an alternative root directory, +This allows you to store, same place, plug-ins and custom templates. +Just create a directory at the root of Dolibarr (eg custom), +then declare it in the file conf.php : + +examples : + +$dolibarr_main_url_root='http://myserver'; +$dolibarr_main_document_root='/path/of/dolibarr/htdocs'; +$dolibarr_main_url_root_alt='/custom'; +$dolibarr_main_document_root_alt='/path/of/dolibarr/htdocs/custom'; + +Copy "multicompany" directory to the root of "custom" directory. diff --git a/htdocs/custom/multicompany/README b/htdocs/custom/multicompany/README new file mode 100755 index 00000000000..6e822ca85b6 --- /dev/null +++ b/htdocs/custom/multicompany/README @@ -0,0 +1,11 @@ +Thank you for your contribution + +Developer: +Régis Houssin +https://www.inodbox.com + +Development platform: +https://git.framasoft.org/inodbox/multicompany + +Translation platform: +https://www.transifex.com/inodbox/multicompany/ diff --git a/htdocs/custom/multicompany/README.md b/htdocs/custom/multicompany/README.md new file mode 100755 index 00000000000..d453b59fca2 --- /dev/null +++ b/htdocs/custom/multicompany/README.md @@ -0,0 +1,36 @@ +Module for Multi-Company Management +========= + +This module enables multi-company to handle multiple entities on a single installation Dolibarr. + +The sharing of the base product, customer base/contacts and user base and more... + +This module required Dolibarr >= 9.0.0 stable installation + +Thank you for your contribution + +Contact +-------- +This module is developped by Régis Houssin () + +Website: +www.inodbox.com + +Heypster french social network: +iNodbox + +Development platform: +git.framasoft.org/inodbox/multicompany/ + +Translation platform: +www.transifex.com/inodbox/multicompany/ + +Licence +------- +GPLv3 or (at your option) any later version. + +See COPYING for more information. + +Other Licences +-------------- +Uses Michel Fortin's PHP Markdown Licensed under BSD to display this README. diff --git a/htdocs/custom/multicompany/README_FR b/htdocs/custom/multicompany/README_FR new file mode 100755 index 00000000000..6b22b2f1f37 --- /dev/null +++ b/htdocs/custom/multicompany/README_FR @@ -0,0 +1,14 @@ +Merci pour votre contribution + +Développeur : +Régis Houssin +https://www.inodbox.com + +Heypster réseau social français +https://www.heypster.com/fr/profile/21956 + +Plateforme de développement : +https://git.framasoft.org/inodbox/multicompany + +Plateforme de traduction : +https://www.transifex.com/inodbox/multicompany/ \ No newline at end of file diff --git a/htdocs/custom/multicompany/admin/about.php b/htdocs/custom/multicompany/admin/about.php new file mode 100755 index 00000000000..d9137aaadea --- /dev/null +++ b/htdocs/custom/multicompany/admin/about.php @@ -0,0 +1,76 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file /multicompany/admin/about.php + * \ingroup multicompany + * \brief About Page + */ + +$res=@include("../../main.inc.php"); // For root directory +if (! $res && file_exists($_SERVER['DOCUMENT_ROOT']."/main.inc.php")) + $res=@include($_SERVER['DOCUMENT_ROOT']."/main.inc.php"); // Use on dev env only +if (! $res) $res=@include("../../../main.inc.php"); // For "custom" directory + + +// Libraries +dol_include_once('/multicompany/lib/multicompany.lib.php'); +dol_include_once('/multicompany/lib/PHP_Markdown/markdown.php'); + +// Translations +$langs->loadLangs(array('admin', 'multicompany@multicompany')); + +// Security check +if (empty($user->admin) || ! empty($user->entity)) { + accessforbidden(); +} + +/* + * View + */ + +$help_url='EN:Module_MultiCompany|FR:Module_MultiSociété'; +llxHeader('', $langs->trans("Module5000Name"), $help_url); + +// Subheader +$linkback=''.$langs->trans("BackToModuleList").''; +print load_fiche_titre($langs->trans("MultiCompanySetup"), $linkback, 'multicompany@multicompany',0,'multicompany_title'); + +// Configuration header +$head = multicompany_prepare_head(); +dol_fiche_head($head, 'about', $langs->trans("Module5000Name")); + +// About page goes here + +$buffer = file_get_contents(dol_buildpath('/multicompany/README.md',0)); +print Markdown($buffer); + +print '
'; + +$url = 'https://www.inodbox.com/'; +$link = 'iNodbox'; +print $langs->trans("MulticompanyMoreModules", $link).'

'; +print ''; +print '


'; + +print ''; + +dol_fiche_end(); + +llxFooter(); + +$db->close(); diff --git a/htdocs/custom/multicompany/admin/caches.php b/htdocs/custom/multicompany/admin/caches.php new file mode 100755 index 00000000000..8d7735c92f9 --- /dev/null +++ b/htdocs/custom/multicompany/admin/caches.php @@ -0,0 +1,103 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/** + * \file /multicompany/admin/options.php + * \ingroup multicompany + * \brief Page to setup options for Multicompany module + */ + + +$res=@include("../../main.inc.php"); // For root directory +if (! $res && file_exists($_SERVER['DOCUMENT_ROOT']."/main.inc.php")) + $res=@include($_SERVER['DOCUMENT_ROOT']."/main.inc.php"); // Use on dev env only +if (! $res) $res=@include("../../../main.inc.php"); // For "custom" directory + +dol_include_once('/multicompany/lib/multicompany.lib.php'); +require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php"; + +$langs->loadLangs(array('admin', 'multicompany@multicompany')); + +// Security check +if (empty($user->admin) || ! empty($user->entity)) { + accessforbidden(); +} + +$action = GETPOST('action','alpha'); + + +/* + * Action + */ + +if ($action == 'setvalue') +{ + $result=dolibarr_set_const($db, "MULTICOMPANY_MEMCACHED_SERVER",GETPOST('MULTICOMPANY_MEMCACHED_SERVER', 'alpha'),'chaine',0,'',0); + + if ($result >= 0) + { + setEventMessage($langs->trans("SetupSaved")); + + // Force new value + $conf->global->MULTICOMPANY_MEMCACHED_SERVER=GETPOST('MULTICOMPANY_MEMCACHED_SERVER', 'alpha'); + } + else + { + dol_print_error($db); + } +} + + +/* + * View + */ + +$form=new Form($db); + +$arrayofjs=array( + '/multicompany/core/js/lib_head.js' +); + +$help_url='EN:Module_MultiCompany|FR:Module_MultiSociété'; +llxHeader('', $langs->trans("MultiCompanySetup"), $help_url, '', '', '', $arrayofjs); + + +$linkback=''.$langs->trans("BackToModuleList").''; +print load_fiche_titre($langs->trans("MultiCompanySetup"),$linkback,'multicompany@multicompany',0,'multicompany_title'); + +$head=multicompany_prepare_head(); +dol_fiche_head($head, 'caches', $langs->trans("ModuleSetup"), -1); + +print '
'.info_admin($langs->trans("MulticompanyCacheSystemInfo"), 0, 0, '1', 'clearboth').'
'; + +print '
'; +print ''; +print ''; + +dol_include_once('/multicompany/admin/tpl/caches.tpl.php'); + +print ''; + +// Boutons actions +print '
'; +print ''; +print ''."\n"; +print '
'; + +llxFooter(); +$db->close(); diff --git a/htdocs/custom/multicompany/admin/index.html b/htdocs/custom/multicompany/admin/index.html new file mode 100755 index 00000000000..e69de29bb2d diff --git a/htdocs/custom/multicompany/admin/multicompany.php b/htdocs/custom/multicompany/admin/multicompany.php new file mode 100755 index 00000000000..d1d6ace4054 --- /dev/null +++ b/htdocs/custom/multicompany/admin/multicompany.php @@ -0,0 +1,131 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/** + * \file multicompany/admin/multicompany.php + * \ingroup multicompany + * \brief Page d'administration/configuration du module Multi-societe + */ + +$res=@include("../../main.inc.php"); // For root directory +if (! $res && file_exists($_SERVER['DOCUMENT_ROOT']."/main.inc.php")) + $res=@include($_SERVER['DOCUMENT_ROOT']."/main.inc.php"); // Use on dev env only +if (! $res) $res=@include("../../../main.inc.php"); // For "custom" directory + +dol_include_once('/multicompany/class/actions_multicompany.class.php', 'ActionsMulticompany'); +require_once DOL_DOCUMENT_ROOT . '/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/core/class/html.formadmin.class.php'; +require_once DOL_DOCUMENT_ROOT . '/core/class/html.formcompany.class.php'; + +$langs->loadLangs(array('admin', 'languages', 'multicompany@multicompany')); + +if (! $user->admin || $user->entity) { + accessforbidden(); +} + +$action=GETPOST('action', 'alpha'); + +$object = new ActionsMulticompany($db); + +$form=new Form($db); +$formadmin=new FormAdmin($db); +$formcompany=new FormCompany($db); + +/* + * Actions + */ + +$object->doAdminActions($action); + +//$test = new DaoMulticompany($db); +//$test->deleteEntityRecords(4); + +/* + * View + */ + +$extrajs=''; +$extracss=''; + +if (empty($action) || $action == "update" || $action == "add") { + $extrajs = array( + '/multicompany/inc/datatables/js/jquery.dataTables.min.js', + //'/multicompany/inc/datatables/responsive/js/dataTables.responsive.min.js', + '/multicompany/inc/datatables/buttons/js/dataTables.buttons.min.js', + '/multicompany/inc/datatables/buttons/js/buttons.colVis.min.js', + '/multicompany/inc/datatables/buttons/js/buttons.html5.min.js' + ); + $extracss = array( + '/multicompany/inc/datatables/css/jquery.dataTables.min.css', + //'/multicompany/inc/datatables/responsive/css/responsive.dataTables.min.css', + '/multicompany/inc/datatables/buttons/css/buttons.dataTables.min.css' + ); +} else if (! empty($conf->global->MULTICOMPANY_SHARINGS_ENABLED)) { + $extrajs = array( + '/multicompany/inc/multiselect/js/multiselect.min.js', + //'/multicompany/inc/multiselect/js/multiselect.js' + ); + $extracss = array( + '/multicompany/inc/multiselect/css/bootstrap-iso.min.css' + ); +} + +$help_url='EN:Module_MultiCompany|FR:Module_MultiSociété'; +llxHeader('', $langs->trans("MultiCompanySetup"), $help_url, '', '', '', $extrajs, $extracss); + +$linkback=''.$langs->trans("BackToModuleList").''; +print load_fiche_titre($langs->trans("MultiCompanySetup"), $linkback, 'multicompany@multicompany', 0, 'multicompany_title'); + +$head = multicompany_prepare_head(); +dol_fiche_head($head, 'entities', $object->getTitle($action), -1); + +$level = checkMultiCompanyVersion(); +if ($level === 1 || $level === -1) +{ + $text = $langs->trans("MultiCompanyIsOlderThanDolibarr"); + if ($level === -1) $text = $langs->trans("DolibarrIsOlderThanMulticompany"); + + print '
'; + dol_htmloutput_mesg($text, '', 'warning', 1); + print '
'; + +} + +// Assign template values +$object->assign_values($action); + +// Isolate Boostrap for avoid conflicts +if (! empty($conf->global->MULTICOMPANY_SHARINGS_ENABLED) && ! empty($action) && $action != "update" && $action != "add") { + print '
'; +} + +// Show the template +$object->display(); + +// Isolate Boostrap for avoid conflicts +if (! empty($conf->global->MULTICOMPANY_SHARINGS_ENABLED) && ! empty($action) && $action != "update" && $action != "add") { + print '
'; +} + +// Card end +dol_fiche_end(); +// Footer +llxFooter(); +// Close database handler +$db->close(); diff --git a/htdocs/custom/multicompany/admin/multicompany_extrafields.php b/htdocs/custom/multicompany/admin/multicompany_extrafields.php new file mode 100755 index 00000000000..91a8d5f4081 --- /dev/null +++ b/htdocs/custom/multicompany/admin/multicompany_extrafields.php @@ -0,0 +1,115 @@ + + * Copyright (C) 2016-2020 Regis Houssin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file multicompany/admin/multicompany.php + * \ingroup multicompany + * \brief Page to setup extra fields of entities + */ + +// Dolibarr environment +$res=@include("../../main.inc.php"); // For root directory +if (! $res && file_exists($_SERVER['DOCUMENT_ROOT']."/main.inc.php")) + $res=@include($_SERVER['DOCUMENT_ROOT']."/main.inc.php"); // Use on dev env only +if (! $res) $res=@include("../../../main.inc.php"); // For "custom" directory + +require_once DOL_DOCUMENT_ROOT . '/core/class/extrafields.class.php'; +dol_include_once('/multicompany/lib/multicompany.lib.php'); + +// Security check +if (empty($user->admin) || ! empty($user->entity)) { + accessforbidden(); +} + +$langs->loadLangs(array('admin', 'other')); + +$extrafields = new ExtraFields($db); +$form = new Form($db); + +// List of supported format +$tmptype2label = ExtraFields::$type2label; +$type2label = array(''); +foreach ($tmptype2label as $key => $val) $type2label[$key] = $langs->transnoentitiesnoconv($val); + +$action = GETPOST('action', 'alpha'); +$attrname = GETPOST('attrname', 'alpha'); +$elementtype = 'entity'; // Must be the $table_element of the class that manage extrafield + + +/* + * Actions + */ + +require DOL_DOCUMENT_ROOT . '/core/actions_extrafields.inc.php'; + + +/* + * View + */ + +$textobject = $langs->transnoentitiesnoconv("Entities"); + +$help_url='EN:Module_MultiCompany|FR:Module_MultiSociété'; +llxHeader('', $langs->trans("MultiCompanySetup"), $help_url); + +$linkback = '' . $langs->trans("BackToModuleList") . ''; +print load_fiche_titre($langs->trans("MultiCompanySetup"), $linkback, 'multicompany@multicompany',0,'multicompany_title'); + +// Configuration header +$head = multicompany_prepare_head(); +dol_fiche_head($head, 'attributes', $langs->trans("ModuleSetup"), -1); + +require DOL_DOCUMENT_ROOT.'/core/tpl/admin_extrafields_view.tpl.php'; + +dol_fiche_end(); + +// Buttons +if ($action != 'create' && $action != 'edit') { + print ''; +} + +/* ************************************************************************* */ +/* */ +/* Creation d'un champ optionnel */ +/* */ +/* ************************************************************************** */ + +if ($action == 'create') { + print "
"; + print load_fiche_titre($langs->trans('NewAttribute')); + + require DOL_DOCUMENT_ROOT . '/core/tpl/admin_extrafields_add.tpl.php'; +} + +/* ************************************************************************* */ +/* */ +/* Edition d'un champ optionnel */ +/* */ +/* ************************************************************************** */ +if ($action == 'edit' && ! empty($attrname)) { + print "
"; + print load_fiche_titre($langs->trans("FieldEdition", $attrname)); + + require DOL_DOCUMENT_ROOT . '/core/tpl/admin_extrafields_edit.tpl.php'; +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/custom/multicompany/admin/options.php b/htdocs/custom/multicompany/admin/options.php new file mode 100755 index 00000000000..806a45caf6d --- /dev/null +++ b/htdocs/custom/multicompany/admin/options.php @@ -0,0 +1,494 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/** + * \file multicompany/admin/parameters.php + * \ingroup multicompany + * \brief Page d'administration/configuration du module Multi-Company + */ + +$res=@include("../../main.inc.php"); // For root directory +if (! $res && file_exists($_SERVER['DOCUMENT_ROOT']."/main.inc.php")) + $res=@include($_SERVER['DOCUMENT_ROOT']."/main.inc.php"); // Use on dev env only +if (! $res) $res=@include("../../../main.inc.php"); // For "custom" directory + +require_once DOL_DOCUMENT_ROOT . '/core/lib/admin.lib.php'; +dol_include_once('/multicompany/class/actions_multicompany.class.php', 'ActionsMulticompany'); + +$langs->loadLangs(array('admin', 'multicompany@multicompany')); + +// Security check +if (empty($user->admin) || ! empty($user->entity)) { + accessforbidden(); +} + +$action=GETPOST('action','alpha'); + +$object = new ActionsMulticompany($db); + + +/* + * Action + */ + + +/* + * View + */ + +$extrajs = array( + '/multicompany/core/js/lib_head.js' +); + +$help_url='EN:Module_MultiCompany|FR:Module_MultiSociété'; +llxHeader('', $langs->trans("MultiCompanySetup"), $help_url,'','','',$extrajs); + +$linkback=''.$langs->trans("BackToModuleList").''; +print load_fiche_titre($langs->trans("MultiCompanySetup"),$linkback,'multicompany@multicompany',0,'multicompany_title'); + +$head = multicompany_prepare_head(); +dol_fiche_head($head, 'options', $langs->trans("ModuleSetup"), -1); + +$level = checkMultiCompanyVersion(); +if ($level === 1 || $level === -1) +{ + $text = $langs->trans("MultiCompanyIsOlderThanDolibarr"); + if ($level === -1) $text = $langs->trans("DolibarrIsOlderThanMulticompany"); + + print '
'; + dol_htmloutput_mesg($text, '', 'warning', 1); + print '
'; + +} + +$form=new Form($db); + +$hidden=true; +$checkconfig = checkMulticompanyAutentication(); +if ($checkconfig !== true) { + if (! empty($conf->global->MULTICOMPANY_HIDE_LOGIN_COMBOBOX)) { + $hidden=false; + } + print ''; +} else { + if (empty($conf->global->MULTICOMPANY_HIDE_LOGIN_COMBOBOX)) { + $hidden=false; + } + print ''; +} + +print ''; +print ''; +print ''."\n"; +print ''; +print ''."\n"; +print ''; + +/* + * System parameters + */ + +// Login page combobox activation +print ''; +print ''; +print ''; +print ''; + +// Replace entity logo in login page +print 'global->MULTICOMPANY_HIDE_LOGIN_COMBOBOX) ? ' style="display:none;"' : '').'>'; +print ''; +print ''; + +print ''; + +// Replace entity background in login page +print 'global->MULTICOMPANY_LOGIN_LOGO_BY_ENTITY) ? ' style="display:none;"' : '').'>'; +print ''; +print ''; +print ''; + +// Disable the new dropdown menu +print ''; +print ''; +print ''; +print ''; + +// Hide/View top menu entity label +print ''; +print ''; +print ''; +print ''; + +// Active by default during create +print ''; +print ''; +print ''; +print ''; + +// Visible by default during create +print 'global->MULTICOMPANY_ACTIVE_BY_DEFAULT) ? ' style="display:none;"' : '').'>'; +print ''; +print ''; +print ''; + +// Template management +$text = img_picto('', 'info','class="linkobject"'); +$htmltext = $langs->trans("TemplateOfEntityManagementInfo"); + +print ''; +print ''; +print ''; +print ''; + +/* + * Sharings parameters + */ +print ''; +print ''."\n"; +print ''; +print ''."\n"; +print ''; + +/* Mode de gestion des droits : + * Mode Off : mode Off : pyramidale. Les droits et les groupes sont gérés dans chaque entité : les utilisateurs appartiennent au groupe de l'entity pour obtenir leurs droits + * Mode On : mode On : transversale : Les groupes ne peuvent appartenir qu'a l'entity = 0 et c'est l'utilisateur qui appartient à tel ou tel entity + */ + +$text = img_picto('', 'info','class="linkobject"'); +$htmltext = $langs->trans("GroupModeTransversalInfoFull"); + +print ''; +print ''; +print ''; + +print ''; + +// Enable global sharings +if (! empty($conf->societe->enabled) + || ! empty($conf->product->enabled) + || ! empty($conf->service->enabled) + || ! empty($conf->categorie->enabled) + || ! empty($conf->adherent->enabled) + || ! empty($conf->agenda->enabled)) +{ + print ''; + print ''; + print ''; + + print ''; +} + +$text = img_picto('', 'info','class="linkobject"'); +$htmltext = $langs->trans("GlobalSharingsInfo"); + +print 'global->MULTICOMPANY_SHARINGS_ENABLED) ? ' style="display:none;"' : '').'>'; +print ''."\n"; +print ''; +print ''."\n"; +print ''; + +// Share thirparties and contacts +if (! empty($conf->societe->enabled)) +{ + print 'global->MULTICOMPANY_SHARINGS_ENABLED) ? ' style="display:none;"' : '').'>'; + print ''; + print ''; + + print ''; +} + +// Elements sharings +$text = img_picto('', 'info','class="linkobject"'); + +foreach ($object->sharingelements as $element => $params) +{ + if (! isset($params['disable']) && $params['type'] === 'element') + { + $tooltip = null; + $display = ! empty($conf->global->MULTICOMPANY_SHARINGS_ENABLED); + $module = ((isset($object->sharingmodulename[$element]) && !empty($object->sharingmodulename[$element])) ? $object->sharingmodulename[$element] : $element); + $enabled = (! empty($params['enable']) ? dol_eval($params['enable'], 1) : $conf->$module->enabled); + if (! empty($enabled)) + { + $icon = (! empty($params['icon'])?$params['icon']:'cogs'); + + if (! empty($params['lang'])) { + $langs->load($params['lang']); + } + + if (! empty($params['tooltip'])) { + $htmltext = $langs->trans($params['tooltip']); + $tooltip = $form->textwithtooltip('', $htmltext, 2, 1, $text); + } + + if (! empty($params['display'])) { + $display = ($display && dol_eval($params['display'], 1)); + } + + $display = ($display ? '' : ' style="display:none;"'); + + print ''; + print ''; + print ''; + + print ''; + } + } +} + +// Objects sharings +$text = img_picto('', 'info','class="linkobject"'); +$htmltext = $langs->trans("ObjectSharingsInfo"); +$display=(! empty($conf->global->MULTICOMPANY_SHARINGS_ENABLED) && ! empty($conf->global->MULTICOMPANY_THIRDPARTY_SHARING_ENABLED) ? '' : ' style="display:none;"'); +print ''; +print ''."\n"; +print ''; +print ''."\n"; +print ''; + +foreach ($object->sharingelements as $element => $params) +{ + if (! isset($params['disable']) && ($params['type'] === 'object' || $params['type'] === 'objectnumber')) + { + $tooltip = null; + $display = ! empty($conf->global->MULTICOMPANY_SHARINGS_ENABLED); + $module = ((isset($object->sharingmodulename[$element]) && !empty($object->sharingmodulename[$element])) ? $object->sharingmodulename[$element] : $element); + $enabled = (! empty($params['enable']) ? dol_eval($params['enable'], 1) : $conf->$module->enabled); + if (! empty($enabled)) + { + $icon = (! empty($params['icon'])?$params['icon']:'cogs'); + + if (! empty($params['lang'])) { + $langs->load($params['lang']); + } + + if (! empty($params['tooltip'])) { + $htmltext = $langs->trans($params['tooltip']); + $tooltip = $form->textwithtooltip('', $htmltext, 2, 1, $text); + } + + if (! empty($params['display'])) { + $display = ($display && dol_eval($params['display'], 1)); + } + + $display = ($display ? '' : ' style="display:none;"'); + + print ''; + print ''; + print ''; + + print ''; + } + } +} + +// Dictionnaries +if (1==2 && ! empty($object->sharingdicts)) +{ + $text = img_picto('', 'info','class="linkobject"'); + $htmltext = $langs->trans("DictsSharingsInfo"); + + print ''; + print ''."\n"; + print ''; + print ''."\n"; + print ''; + + foreach ($object->sharingdicts as $dict => $data) + { + print ''; + print ''; + print ''; + + print ''; + } +} + +print '
'.$langs->trans("Parameters").' '.$langs->trans("Value").'
'.$langs->trans("HideLoginCombobox").' '; +if ($checkconfig !== true) { + $input = array( + 'showhide' => array( + '#mc_hide_login_combobox_error' + ) + ); +} else { + $input = array( + 'hideshow' => array( + '#dol_hide_login_combobox_error' + ) + ); +} +$input['hideshow'][] = '#changeloginlogo'; +$input['hideshow'][] = '#changeloginbackground'; +$input['del'] = array('MULTICOMPANY_LOGIN_LOGO_BY_ENTITY', 'MULTICOMPANY_LOGIN_BACKGROUND_BY_ENTITY'); +print ajax_mcconstantonoff('MULTICOMPANY_HIDE_LOGIN_COMBOBOX', $input, 0); +print '
'.$langs->trans("EntityBackgroundInLoginPage").' '; +print ajax_mcconstantonoff('MULTICOMPANY_LOGIN_BACKGROUND_BY_ENTITY', '', 0); +print '
'.$langs->trans("DisableSwitchEntityDropdownMenu").' '; +$input = array( + 'reload' => true +); +print ajax_mcconstantonoff('MULTICOMPANY_DROPDOWN_MENU_DISABLED', $input, 0); +print '
'.$langs->trans("ShowTopMenuEntityLabel").' '; +$input = array( + 'reload' => true +); +print ajax_mcconstantonoff('MULTICOMPANY_NO_TOP_MENU_ENTITY_LABEL', $input, 0, 1); +print '
'.$langs->trans("EntityActiveByDefault").' '; +$input = array( + 'showhide' => array( + '#visiblebydefault' + ), + 'del' => array( + 'MULTICOMPANY_VISIBLE_BY_DEFAULT' + ) +); +print ajax_mcconstantonoff('MULTICOMPANY_ACTIVE_BY_DEFAULT', $input, 0); +print '
'.$langs->trans("EntityVisibleByDefault").' '; +print ajax_mcconstantonoff('MULTICOMPANY_VISIBLE_BY_DEFAULT', '', 0); +print '
'.$langs->trans("TemplateOfEntityManagement").' '.$form->textwithtooltip('',$htmltext,2,1,$text).' '; +print ajax_mcconstantonoff('MULTICOMPANY_TEMPLATE_MANAGEMENT', '', 0); +print '
'.$langs->trans("Parameters").' '.$langs->trans("Value").'
'.$langs->trans("GroupModeTransversal").' '.$form->textwithtooltip('',$htmltext,2,1,$text).' '; +$input = array( + 'alert' => array( + 'set' => array( + 'info' => true, + 'height' => 200, + 'yesButton' => $langs->trans('Ok'), + 'title' => $langs->transnoentities('GroupModeTransversalTitle'), + 'content' => img_warning().' '.$langs->trans('GroupModeTransversalInfo') + ) + ) +); +print ajax_mcconstantonoff('MULTICOMPANY_TRANSVERSE_MODE', $input, 0); +print '
'.$langs->trans("EnableGlobalSharings").' '; + $input = array( + 'alert' => array( + 'set' => array( + 'info' => true, + 'yesButton' => $langs->trans('Ok'), + 'title' => $langs->transnoentities('GlobalSharings'), + 'content' => img_warning().' '.$langs->trans('GlobalSharingsInfo') + ) + ), + 'showhide' => array( + '#shareelementtitle', + '#sharethirdparty' + ), + 'hide' => array( + '#shareelementtitle', + '#shareobjecttitle', + '#sharethirdparty' + ), + 'del' => array( + 'MULTICOMPANY_THIRDPARTY_SHARING_ENABLED' + ) + ); + foreach ($object->sharingelements as $key => $values) + { + if (! isset($values['disable'])) { + if (isset($values['input']) && isset($values['input']['global'])) { + if (isset($values['input']['global']['showhide']) && $values['input']['global']['showhide'] === true) { + if (! isset($input['showhide'])) $input['showhide'] = array(); + array_push($input['showhide'], '#share'.$key); + } + if (isset($values['input']['global']['hide']) && $values['input']['global']['hide'] === true) { + if (! isset($input['hide'])) $input['hide'] = array(); + array_push($input['hide'], '#share'.$key); + } + if (isset($values['input']['global']['del']) && $values['input']['global']['del'] === true) { + if (! isset($input['del'])) $input['del'] = array(); + array_push($input['del'], 'MULTICOMPANY_'.strtoupper($key).'_SHARING_ENABLED'); + } + } + } + } + print ajax_mcconstantonoff('MULTICOMPANY_SHARINGS_ENABLED', $input, 0); + print '
'.$langs->trans("ActivatingShares").' '.$form->textwithtooltip('',$htmltext,2,1,$text).' '.$langs->trans("Value").'
'.$langs->trans("ShareThirdpartiesAndContacts").' '; + $input = array( + 'showhide' => array( + '#shareobjecttitle' + ) + ); + foreach ($object->sharingelements as $key => $values) + { + if (! isset($values['disable']) && ($values['type'] === 'object' || $values['type'] === 'objectnumber')) + { + if (isset($values['input']) && isset($values['input']['thirdparty'])) { + if (isset($values['input']['thirdparty']['showhide']) && $values['input']['thirdparty']['showhide'] === true) { + if (! isset($input['showhide'])) $input['showhide'] = array(); + array_push($input['showhide'], '#share'.$key); + } + if (isset($values['input']['thirdparty']['hide']) && $values['input']['thirdparty']['hide'] === true) { + if (! isset($input['hide'])) $input['hide'] = array(); + array_push($input['hide'], '#share'.$key); + } + if (isset($values['input']['thirdparty']['del']) && $values['input']['thirdparty']['del'] === true) { + if (! isset($input['del'])) $input['del'] = array(); + array_push($input['del'], 'MULTICOMPANY_'.strtoupper($key).'_SHARING_ENABLED'); + } + } + } + } + print ajax_mcconstantonoff('MULTICOMPANY_THIRDPARTY_SHARING_ENABLED', $input, 0); + print '
'; + print ''.$langs->trans("Share".ucfirst($element)).(! empty($tooltip) ? ' '.$tooltip : '').' '; + + $input = array(); + foreach ($object->sharingelements as $key => $values) { + if (! isset($values['disable']) && isset($values['input']) && isset($values['input'][$element])) { + if (isset($values['input'][$element]['showhide']) && $values['input'][$element]['showhide'] === true) { + if (! isset($input['showhide'])) $input['showhide'] = array(); + array_push($input['showhide'], '#share'.$key); + } + if (isset($values['input'][$element]['hide']) && $values['input'][$element]['hide'] === true) { + if (! isset($input['hide'])) $input['hide'] = array(); + array_push($input['hide'], '#share'.$key); + } + if (isset($values['input'][$element]['del']) && $values['input'][$element]['del'] === true) { + if (! isset($input['del'])) $input['del'] = array(); + array_push($input['del'], 'MULTICOMPANY_'.strtoupper($key).'_SHARING_ENABLED'); + } + } + } + + print ajax_mcconstantonoff('MULTICOMPANY_'.strtoupper($element).'_SHARING_ENABLED', $input, 0); + print '
'.$langs->trans("ActivatingObjectShares").' '.$form->textwithtooltip('', $htmltext, 2, 1, $text).' '.$langs->trans("Value").'
'; + print ''.$langs->trans("Share".ucfirst($element)).(! empty($tooltip) ? ' '.$tooltip : '').' '; + $input = array(); + print ajax_mcconstantonoff('MULTICOMPANY_'.strtoupper($element).'_SHARING_ENABLED', $input, 0); + print '
'.$langs->trans("ActivatingDictsShares").' '.$form->textwithtooltip('',$htmltext,2,1,$text).' '.$langs->trans("Value").'
'.$langs->trans("Share".ucfirst($dict)).' '; + print ajax_mcconstantonoff('MULTICOMPANY_'.strtoupper($dict).'_SHARING_DISABLED', '', 0); + print '
'; + +// Card end +dol_fiche_end(); +// Footer +llxFooter(); +// Close database handler +$db->close(); diff --git a/htdocs/custom/multicompany/admin/tpl/caches.tpl.php b/htdocs/custom/multicompany/admin/tpl/caches.tpl.php new file mode 100755 index 00000000000..8e4357cd6f7 --- /dev/null +++ b/htdocs/custom/multicompany/admin/tpl/caches.tpl.php @@ -0,0 +1,118 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +global $form; +?> + + +
+
"> +
trans("MulticompanySession"); ?>
trans('MulticompanySessionDescription'); ?>

+
+
+
+
+ array('MULTICOMPANY_MEMCACHED_ENABLED','MULTICOMPANY_SHMOP_ENABLED'), + 'disabled' => array('MULTICOMPANY_MEMCACHED_SERVER') + ); + echo ajax_mcconstantonoff('MULTICOMPANY_SESSION_ENABLED', $input, 0); + ?> +
+
+
+ +
+
"> +
trans("MulticompanyMemcached"); ?>
trans('MulticompanyMemcachedDescription'); ?>

+
+
+ global->MULTICOMPANY_MEMCACHED_SERVER)?$conf->global->MULTICOMPANY_MEMCACHED_SERVER:(!empty($conf->global->MEMCACHED_SERVER)?$conf->global->MEMCACHED_SERVER:'127.0.0.1:11211')); + + $tmparray=explode(':',$serveraddress); + $server=$tmparray[0]; + $port=$tmparray[1]?$tmparray[1]:11211; + + $result=$m->addServer($server, $port); + $arraycache=$m->getStats(); + + if (is_array($arraycache)) + echo $form->textwithtooltip('',$langs->trans("MemcachedServerIsReady"),2,1,img_picto('','tick'),'',3); + else + echo $form->textwithtooltip('',$langs->trans("MemcachedServerIsNotReady"),2,1,img_warning(''),'',3); + + echo ' global->MULTICOMPANY_MEMCACHED_ENABLED) ? ' disabled="disabled"' : '').' />'; + } + else + echo img_warning($langs->trans("MulticompanyMemcachedUnavailable")).' '.$langs->trans("MulticompanyMemcachedUnavailable"); + ?> +
+
+
+ array('MULTICOMPANY_SHMOP_ENABLED','MULTICOMPANY_SESSION_ENABLED'), + 'disabledenabled' => array('MULTICOMPANY_MEMCACHED_SERVER') + ); + echo ajax_mcconstantonoff('MULTICOMPANY_MEMCACHED_ENABLED', $input, 0); + } + else + echo ''.img_picto($langs->trans("Disabled"),'switch_off', 'class="button-not-allowed"').''; + ?> +
+
+
+ +
+
"> +
trans("MulticompanyShmop"); ?>
trans('MulticompanyShmopDescription'); ?>

+
+
+ trans("MulticompanyShmopAvailable"),'tick').' '.$langs->trans("MulticompanyShmopAvailable"); + else + echo img_warning($langs->trans("MulticompanyShmopUnavailable")).' '.$langs->trans("MulticompanyShmopUnavailable"); + ?> +
+
+
+ array('MULTICOMPANY_MEMCACHED_ENABLED','MULTICOMPANY_SESSION_ENABLED'), + 'disabled' => array('MULTICOMPANY_MEMCACHED_SERVER') + ); + echo ajax_mcconstantonoff('MULTICOMPANY_SHMOP_ENABLED', $input, 0); + } + else + echo ''.img_picto($langs->trans("Disabled"),'switch_off', 'class="button-not-allowed"').''; + ?> +
+
+
+ \ No newline at end of file diff --git a/htdocs/custom/multicompany/admin/tpl/card.tpl.php b/htdocs/custom/multicompany/admin/tpl/card.tpl.php new file mode 100755 index 00000000000..b41ff737d7c --- /dev/null +++ b/htdocs/custom/multicompany/admin/tpl/card.tpl.php @@ -0,0 +1,386 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ +?> + + + +
" method="POST"> + + +tpl['action'] === 'create') { ?> + + + + + + + + + + + + + + + + + + + +global->MULTICOMPANY_TEMPLATE_MANAGEMENT)) { + if ($this->tpl['action'] === 'create') { ?> + + + + + + + + +tpl['template'] === 1) { ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +tpl['extrafields']->attribute_label)) { + print $this->dao->showOptionals($this->tpl['extrafields'], 'edit'); +} +if (! empty($conf->global->MULTICOMPANY_SHARINGS_ENABLED)) { + +foreach($this->sharingelements as $element => $params) { + if ($params['type'] === 'element' && ! empty($this->tpl['multiselect_from_' . $element])) { + $uppername = strtoupper($element); + $icon = (! empty($params['icon'])?$params['icon']:'edit'); +?> + + + + + + + +global->MULTICOMPANY_TEMPLATE_MANAGEMENT)) { ?> + + + + + + + + + +sharingelements as $element => $params) { + if ($params['type'] !== 'element' && ! empty($this->tpl['multiselect_from_' . $element])) { + $uppername = strtoupper($element); + $icon = (! empty($params['icon'])?$params['icon']:'edit'); +?> + + + + + + + + +global->MULTICOMPANY_PROPOSALNUMBER_SHARING_ENABLED)) { ?> + + + + + + + +global->MULTICOMPANY_INVOICENUMBER_SHARING_ENABLED)) { ?> + + + + + + + +global->MULTICOMPANY_TEMPLATE_MANAGEMENT)) { ?> + + + + + + + + + +
trans("CompanyInfo"); ?>trans("Value"); ?>
trans("Label"); ?>
trans("CompanyName"); ?>
trans("TemplateOfCompany"); ?>tpl['template']; ?>
trans("SelectTemplateOfCompany"); ?>tpl['select_template']; ?>
trans("WarningThisIsATemplate"); ?>
trans("CompanyAddress"); ?>
trans("CompanyZip"); ?>tpl['select_zip']; ?>
trans("CompanyTown"); ?>tpl['select_town']; ?>
trans("Country"); ?>tpl['select_country'].$this->tpl['info_admin']; ?>
trans("State"); ?>tpl['select_state']; ?>
trans("CompanyCurrency"); ?>tpl['select_currency']; ?>
trans("DefaultLanguage"); ?>tpl['select_language']; ?>
trans("Description"); ?>
trans($uppername . "Sharing"); ?>
trans($uppername . "SharingDescription"); ?> +
+
+
trans("EntitiesSelected"); ?>
+ tpl['multiselect_to_' . $element]; ?> +
+
+ + + + + + +
+
+
trans("EntitiesAvailable"); ?>
+ tpl['multiselect_from_' . $element]; ?> +
+
+
trans("AddNewEntityInAllOtherEntities"); ?>tpl['addtoallother_' . $element]; ?>
 
trans($uppername . "Sharing"); ?>
trans($uppername . "SharingDescription"); ?> +
+
+
trans("EntitiesSelected"); ?>
+ tpl['multiselect_to_' . $element]; ?> +
+
+ + + + + + +
+
+
trans("EntitiesAvailable"); ?>
+ tpl['multiselect_from_' . $element]; ?> +
+
+
trans("ReferringEntityForProposalNumber"); ?>tpl['select_proposalnumber_entity']; ?>
 
trans("ReferringEntityForInvoiceNumber"); ?>tpl['select_invoicenumber_entity']; ?>
 
trans("AddNewEntityInAllOtherEntities"); ?>tpl['addtoallother_' . $element]; ?>
 
+ + +
+tpl['action'] === 'create') { ?> + +" /> + + + +" /> + +" /> +
+ +
+ + diff --git a/htdocs/custom/multicompany/admin/tpl/index.html b/htdocs/custom/multicompany/admin/tpl/index.html new file mode 100755 index 00000000000..e69de29bb2d diff --git a/htdocs/custom/multicompany/admin/tpl/list.tpl.php b/htdocs/custom/multicompany/admin/tpl/list.tpl.php new file mode 100755 index 00000000000..81d297f88bc --- /dev/null +++ b/htdocs/custom/multicompany/admin/tpl/list.tpl.php @@ -0,0 +1,230 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +dol_include_once('/multicompany/admin/tpl/switch.tpl.php'); + +$colHidden = (! empty($conf->global->MULTICOMPANY_COLHIDDEN) ? implode(",", json_decode($conf->global->MULTICOMPANY_COLHIDDEN, true)) : null); +$colOrder = (! empty($conf->global->MULTICOMPANY_COLORDER) ? json_decode($conf->global->MULTICOMPANY_COLORDER, true) : array('id' => 0, 'direction' => 'asc')); + +$columns = array(); + +$columns['id'] = array( + 'label' => 'ID', + 'sortable' => true, + 'searchable' => true, + 'priority' => 12, + 'center' => 'dt-center' +); +$columns['label'] = array( + 'label' => 'Label', + 'sortable' => true, + 'searchable' => true, + 'priority' => 1, +); +$columns['description'] = array( + 'label' => 'Description', + 'sortable' => true, + 'searchable' => true, + 'priority' => 11, +); +$columns['name'] = array( + 'label' => 'Name', + 'priority' => 10, + 'center' => 'dt-center' +); +$columns['zip'] = array( + 'label' => 'Zip', + 'priority' => 9, + 'center' => 'dt-center' +); +$columns['town'] = array( + 'label' => 'Town', + 'priority' => 8, + 'center' => 'dt-center' +); +$columns['country'] = array( + 'label' => 'Country', + 'priority' => 7, + 'center' => 'dt-center' +); +$columns['currency'] = array( + 'label' => 'Currency', + 'priority' => 6, + 'center' => 'dt-center' +); +$columns['language'] = array( + 'label' => 'DefaultLanguageShort', + 'priority' => 5, + 'center' => 'dt-center' +); +if (! empty($this->tpl['extrafields']->attribute_label)) { + foreach ($this->tpl['extrafields']->attribute_label as $key => $value) + { + $columns[$key] = array( + 'label' => $value, + 'center' => 'dt-center' + ); + } +} +$columns['visible'] = array( + 'label' => 'Visible', + 'width' => '20px', + 'priority' => 3, + 'center' => 'dt-center' +); +$columns['active'] = array( + 'label' => 'Status', + 'width' => '20px', + 'priority' => 2, + 'center' => 'dt-center' +); +$columns['tools'] = array( + 'label' => 'Tools', + 'width' => '50px', + 'priority' => 4, + 'center' => 'dt-center' +); + +//var_dump($columns); + +?> + + + + + + + $values) { + //$moreattr = (! empty($values['priority'])?'data-priority="'.$values['priority'].'"':''); + echo getTitleFieldOfList($values['label'], 1, '', '', '', '', $moreattr, '', '', 'entity_' . $key . ' '); + } + ?> + + + + + + + +
trans('LoadingDataFromServer'); ?>
+ + \ No newline at end of file diff --git a/htdocs/custom/multicompany/admin/tpl/switch.tpl.php b/htdocs/custom/multicompany/admin/tpl/switch.tpl.php new file mode 100755 index 00000000000..4261a0ef6c2 --- /dev/null +++ b/htdocs/custom/multicompany/admin/tpl/switch.tpl.php @@ -0,0 +1,122 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ +?> + + +
+

trans('ConfirmDeleteEntity'); ?>

+
+ + \ No newline at end of file diff --git a/htdocs/custom/multicompany/class/actions_multicompany.class.php b/htdocs/custom/multicompany/class/actions_multicompany.class.php new file mode 100755 index 00000000000..f73d69db5bd --- /dev/null +++ b/htdocs/custom/multicompany/class/actions_multicompany.class.php @@ -0,0 +1,4608 @@ + + * Copyright (C) 2011 Herve Prot + * Copyright (C) 2014 Philippe Grand + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/** + * \file htdocs/multicompany/actions_multicompany.class.php + * \ingroup multicompany + * \brief File Class multicompany + */ + +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +dol_include_once('/multicompany/class/dao_multicompany.class.php', 'DaoMulticompany'); +dol_include_once('/multicompany/lib/multicompany.lib.php'); + +/** + * Class Actions of the module multicompany + */ +class ActionsMulticompany +{ + /** @var DoliDB */ + var $db; + /** @var DaoMulticompany */ + var $dao; + + var $mesg; + var $error; + var $errors=array(); + //! Numero de l'erreur + var $errno = 0; + + var $template_dir; + var $template; + + var $label; + var $description; + + var $referent; + + var $sharings=array(); + var $options=array(); + var $entities=array(); + var $dict=array(); + var $tpl=array(); + + var $addzero=array(); + var $sharingelements=array(); + var $sharingobjects=array(); + var $sharingdicts=array(); + + private $config=array(); + + // For Hookmanager return + var $resprints; + var $results=array(); + + + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + public function __construct($db) + { + global $conf; + + $this->db = $db; + + $this->addzero = array( + 'user', + 'usergroup', + 'c_email_templates', + 'email_template', + 'default_values' + ); + + // Default sharing elements + $this->sharingelements = array( + 'thirdparty' => array( + 'type' => 'element', + 'icon' => 'building', + 'active' => true, // for setEntity() function + 'disable' => true // disable in options tab + ), + 'member' => array( + 'type' => 'element', + 'icon' => 'address-card', + 'input' => array( + 'global' => array( + 'showhide' => true, + 'hide' => true, + 'del' => true + ) + ) + ), + 'member_type' => array( + 'type' => 'element', + 'icon' => 'address-card', + 'display' => '! empty($conf->global->MULTICOMPANY_MEMBER_SHARING_ENABLED)', + 'input' => array( + 'global' => array( + 'hide' => true, + 'del' => true + ), + 'member' => array( + 'showhide' => true, + 'del' => true + ) + ) + ), + 'product' => array( + 'type' => 'element', + 'icon' => 'cube', + 'tooltip' => 'ProductSharingInfo', + 'enable' => '(! empty($conf->product->enabled) || ! empty($conf->service->enabled))', + 'input' => array( + 'global' => array( + 'showhide' => true, + 'hide' => true, + 'del' => true + ) + ), + 'active' => true + ), + 'productprice' => array( + 'type' => 'element', + 'icon' => 'money', + 'tooltip' => 'ProductPriceSharingInfo', + 'enable' => '(! empty($conf->product->enabled) || ! empty($conf->service->enabled))', + 'display' => '! empty($conf->global->MULTICOMPANY_PRODUCT_SHARING_ENABLED)', + 'input' => array( + 'global' => array( + 'hide' => true, + 'del' => true + ), + 'product' => array( + 'showhide' => true, + 'del' => true + ) + ) + ), + 'productsupplierprice' => array( + 'type' => 'element', + 'icon' => 'money', + 'enable' => '((! empty($conf->product->enabled) || ! empty($conf->service->enabled)) && ! empty($conf->fournisseur->enabled))', + 'display' => '! empty($conf->global->MULTICOMPANY_PRODUCT_SHARING_ENABLED)', + 'input' => array( + 'global' => array( + 'hide' => true, + 'del' => true + ), + 'product' => array( + 'showhide' => true, + 'del' => true + ) + ), + ), + 'stock' => array( + 'type' => 'element', + 'icon' => 'cubes', + //'tooltip' => 'SharingStockInfo', + 'enable' => '(! empty($conf->stock->enabled) && (! empty($conf->product->enabled) || ! empty($conf->service->enabled)))', + 'display' => '! empty($conf->global->MULTICOMPANY_PRODUCT_SHARING_ENABLED)', + 'input' => array( + 'global' => array( + 'hide' => true, + 'del' => true + ), + 'product' => array( + 'showhide' => true, + 'del' => true + ) + ) + ), + 'category' => array( + 'type' => 'element', + 'icon' => 'paperclip', + 'input' => array( + 'global' => array( + 'showhide' => true, + 'hide' => true, + 'del' => true + ) + ) + ), + 'agenda' => array( + 'type' => 'element', + 'icon' => 'calendar', + 'input' => array( + 'global' => array( + 'showhide' => true, + 'hide' => true, + 'del' => true + ) + ) + ), + 'bankaccount' => array( + 'type' => 'element', + 'icon' => 'bank', + 'input' => array( + 'global' => array( + 'showhide' => true, + 'hide' => true, + 'del' => true + ) + ) + ), + 'expensereport' => array( + 'type' => 'element', + 'icon' => 'edit', + 'input' => array( + 'global' => array( + 'showhide' => true, + 'hide' => true, + 'del' => true + ) + ) + ), + 'holiday' => array( + 'type' => 'element', + 'icon' => 'paper-plane-o', + 'input' => array( + 'global' => array( + 'showhide' => true, + 'hide' => true, + 'del' => true + ) + ) + ), + 'project' => array( + 'type' => 'element', + 'icon' => 'code-fork', + 'input' => array( + 'global' => array( + 'showhide' => true, + 'hide' => true, + 'del' => true + ) + ) + ), + + // Object + + 'proposal' => array( + 'type' => 'object', + 'icon' => 'file-pdf-o', + 'mandatory' => 'thirdparty', + 'enable' => '(! empty($conf->propal->enabled) && ! empty($conf->societe->enabled))', + 'display' => '! empty($conf->global->MULTICOMPANY_THIRDPARTY_SHARING_ENABLED)', + 'input' => array( + 'global' => array( + 'hide' => true, + 'del' => true + ), + 'thirdparty' => array( + 'showhide' => true, + 'hide' => true, + 'del' => true + ) + ), + 'active' => true + ), + 'proposalnumber' => array( + 'type' => 'objectnumber', + 'icon' => 'cogs', + 'mandatory' => 'thirdparty', + 'tooltip' => 'ProposalNumberSharingInfo', + 'enable' => '(! empty($conf->propal->enabled) && ! empty($conf->societe->enabled))', + 'display' => '! empty($conf->global->MULTICOMPANY_THIRDPARTY_SHARING_ENABLED)', + 'input' => array( + 'global' => array( + 'hide' => true, + 'del' => true + ), + 'thirdparty' => array( + 'showhide' => true, + 'hide' => true, + 'del' => true + ) + ) + ), + 'order' => array( + 'type' => 'object', + 'icon' => 'file-pdf-o', // Font Awesome icon + 'mandatory' => 'thirdparty', + 'enable' => '(! empty($conf->commande->enabled) && ! empty($conf->societe->enabled))', + 'display' => '! empty($conf->global->MULTICOMPANY_THIRDPARTY_SHARING_ENABLED)', + 'input' => array( + 'global' => array( + 'hide' => true, + 'del' => true + ), + 'thirdparty' => array( + 'showhide' => true, + 'hide' => true, + 'del' => true + ) + ), + 'active' => true, + //'disable' => true // Disable if not stable + ), + 'ordernumber' => array( + 'type' => 'objectnumber', + 'icon' => 'cogs', + 'mandatory' => 'thirdparty', + 'tooltip' => 'OrderNumberSharingInfo', + 'enable' => '(! empty($conf->commande->enabled) && ! empty($conf->societe->enabled))', + 'display' => '! empty($conf->global->MULTICOMPANY_THIRDPARTY_SHARING_ENABLED)', + 'input' => array( + 'global' => array( + 'hide' => true, + 'del' => true + ), + 'thirdparty' => array( + 'showhide' => true, + 'hide' => true, + 'del' => true + ) + ), + //'disable' => true + ), + 'invoice' => array( + 'type' => 'object', + 'icon' => 'file-pdf-o', + 'mandatory' => 'thirdparty', + 'enable' => '(! empty($conf->facture->enabled) && ! empty($conf->societe->enabled))', + 'display' => '! empty($conf->global->MULTICOMPANY_THIRDPARTY_SHARING_ENABLED)', + 'input' => array( + 'global' => array( + 'hide' => true, + 'del' => true + ), + 'thirdparty' => array( + 'showhide' => true, + 'hide' => true, + 'del' => true + ) + ), + 'active' => true + ), + 'invoicenumber' => array( + 'type' => 'objectnumber', + 'icon' => 'cogs', + 'mandatory' => 'thirdparty', + 'tooltip' => 'InvoiceNumberSharingInfo', + 'enable' => '(! empty($conf->facture->enabled) && ! empty($conf->societe->enabled))', + 'display' => '! empty($conf->global->MULTICOMPANY_THIRDPARTY_SHARING_ENABLED)', + 'input' => array( + 'global' => array( + 'hide' => true, + 'del' => true + ), + 'thirdparty' => array( + 'showhide' => true, + 'hide' => true, + 'del' => true + ) + ) + ), + 'supplier_proposal' => array( + 'type' => 'object', + 'icon' => 'file-pdf-o', + 'input' => array( + 'global' => array( + 'hide' => true, + 'del' => true + ) + ), + 'disable' => true + ), + 'supplier_order' => array( + 'type' => 'object', + 'icon' => 'file-pdf-o', + 'input' => array( + 'global' => array( + 'hide' => true, + 'del' => true + ) + ), + 'disable' => true + ), + 'supplier_invoice' => array( + 'type' => 'object', + 'icon' => 'file-pdf-o', + 'input' => array( + 'global' => array( + 'hide' => true, + 'del' => true + ) + ), + 'disable' => true + ), + 'intervention' => array( + 'type' => 'object', + 'icon' => 'wrench', + 'input' => array( + 'global' => array( + 'hide' => true, + 'del' => true + ) + ), + 'disable' => true + ) + ); + + // Module name if different of object name (eg $conf->commande->enabled) + $this->sharingmodulename = array( + 'thirdparty' => 'societe', + 'proposal' => 'propal', + 'proposalnumber' => 'propal', + 'order' => 'commande', + 'ordernumber' => 'commande', + 'invoice' => 'facture', + 'invoicenumber' => 'facture', + 'product' => (empty($conf->product->enabled) && !empty($conf->service->enabled) ? 'service' : 'product'), + 'productprice' => 'product', + 'productsupplierprice' => 'product', + 'project' => 'projet', + 'member' => 'adherent', + 'membertype' => 'adherent', + 'member_type' => 'adherent', // deprecated + //'membertype' => 'member_type', // deprecated + 'intervention' => 'ficheinter', + 'category' => 'categorie', + 'bankaccount' => 'banque', + 'bank_account' => 'banque', // deprecated + //'bankaccount' => 'banque_account', // deprecated + ); + + $this->sharingdicts = array( + 'c_paiement' => array( + 'societe' => array( + 'mode_reglement', + 'mode_reglement_supplier' + ), + 'propal' => 'fk_mode_reglement', + 'commande' => 'fk_mode_reglement', + 'facture' => 'fk_mode_reglement', + 'facture_rec' => 'fk_mode_reglement', + 'commande_fournisseur' => 'fk_mode_reglement', + 'facture_fourn' => 'fk_mode_reglement', + 'supplier_proposal' => 'fk_mode_reglement', + 'chargesociales' => 'fk_mode_reglement', + 'don' => 'fk_payment', + 'paiement' => 'fk_paiement', + 'paiementfourn' => 'fk_paiement', + 'paiement_facture' => 'fk_paiement', + 'expensereport' => 'fk_c_paiement', + 'paiementcharge' => 'fk_typepaiement', + 'tva' => 'fk_typepayment', + 'payment_various' => 'fk_typepayment', + 'payment_salary' => 'fk_typepayment', + 'payment_expensereport' => 'fk_typepayment', + 'payment_donation' => 'fk_typepayment', + 'loan_schedule' => 'fk_typepayment', + 'payment_loan' => 'fk_typepayment' + ), + 'c_payment_term' => array( + 'societe' => array( + 'cond_reglement', + 'cond_reglement_supplier' + ), + 'propal' => 'fk_cond_reglement', + 'commande' => 'fk_cond_reglement', + 'facture' => 'fk_cond_reglement', + 'facture_rec' => 'fk_cond_reglement', + 'commande_fournisseur' => 'fk_cond_reglement', + 'facture_fourn' => 'fk_cond_reglement', + 'supplier_proposal' => 'fk_cond_reglement' + ) + ); + + if (! empty($conf->global->MULTICOMPANY_EXTERNAL_MODULES_SHARING)) + { + $externalmodules = json_decode($conf->global->MULTICOMPANY_EXTERNAL_MODULES_SHARING, true); + + if (is_array($externalmodules) && ! empty($externalmodules)) + { + foreach($externalmodules as $params) + { + if (is_array($params) && ! empty($params)) + { + if (is_array($params['addzero']) && ! empty($params['addzero'])) { + array_push($this->addzero, $params['addzero']); + } + + if (is_array($params['sharingelements']) && ! empty($params['sharingelements'])) { + $this->sharingelements = array_merge($this->sharingelements, $params['sharingelements']); + } + + if (is_array($params['sharingmodulename']) && ! empty($params['sharingmodulename'])) + { + $this->sharingmodulename = array_merge($this->sharingmodulename, $params['sharingmodulename']); + } + } + } + } + } + } + + /** + * Instantiation of DAO class + * + * @return void + */ + private function getInstanceDao() + { + if (! is_object($this->dao)) + { + $this->dao = new DaoMulticompany($this->db); + } + } + + + /** + * setHtmlTitle + * + * @param array $parameters Hook metadatas (context, etc...) + */ + public function setHtmlTitle($parameters=false) + { + global $conf; + + if (empty($conf->global->MULTICOMPANY_HIDE_HTML_TITLE)) { + $this->resprints = ' + multicompany'; + } + + return 0; + } + + + /** + * Enter description here ... + * + * @param string $action Action type + */ + public function doAdminActions(&$action='') + { + global $conf, $user, $langs; + + $this->getInstanceDao(); + + $id = GETPOST('id','int'); + $label = GETPOST('label','alpha'); + $name = GETPOST('name','alpha'); + $description = GETPOST('description','alpha'); + $cancel = GETPOST('cancel', 'alpha'); + $addandstay = GETPOST('addandstay', 'alpha'); + $cancelandstay = GETPOST('cancelandstay', 'alpha'); + $updateandstay = GETPOST('updateandstay', 'alpha'); + $template = (empty($conf->global->MULTICOMPANY_TEMPLATE_MANAGEMENT) ? null : GETPOST('template', 'int')); + $usetemplate = (empty($conf->global->MULTICOMPANY_TEMPLATE_MANAGEMENT) ? null : GETPOST('usetemplate', 'int')); + $visible = GETPOST('visible', 'int'); + $active = GETPOST('active', 'int'); + + if ($action === 'add' && empty($cancel) && $user->admin && ! $user->entity) + { + $error=0; + + if (empty($label)) + { + $error++; + setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentities("Label")), 'errors'); + $action = 'create'; + } + else if (empty($name)) + { + $error++; + setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentities("CompanyName")), 'errors'); + $action = 'create'; + } + + // Verify if label already exist in database + if (! $error) + { + $this->dao->getEntities(); + if (! empty($this->dao->entities)) + { + foreach($this->dao->entities as $entity) + { + if (strtolower($entity->label) == strtolower($label)) $error++; + } + if ($error) + { + setEventMessage($langs->trans("ErrorEntityLabelAlreadyExist"), 'errors'); + $action = 'create'; + } + } + } + + if (! $error) + { + $this->db->begin(); + + $this->dao->label = $label; + $this->dao->description = $description; + $this->dao->visible = ((! empty($template) && empty($usetemplate)) ? 2 : ((! empty($visible) || ! empty($conf->global->MULTICOMPANY_VISIBLE_BY_DEFAULT)) ? 1 : 0)); + $this->dao->active = ((! empty($active) || ! empty($conf->global->MULTICOMPANY_ACTIVE_BY_DEFAULT))?1:0); + + if (! empty($conf->global->MULTICOMPANY_SHARINGS_ENABLED)) { + $this->dao->options['proposalnumber_referent'] = (GETPOST('proposalnumber_referring_entity', 'int') ? GETPOST('proposalnumber_referring_entity', 'int') : null); + $this->dao->options['invoicenumber_referent'] = (GETPOST('invoicenumber_referring_entity', 'int') ? GETPOST('invoicenumber_referring_entity', 'int') : null); + foreach ($this->sharingelements as $element => $params) { + if ((($params['object'] || $params['objectnumber']) && ! isset($params['disable'])) && (empty($conf->societe->enabled) || empty($conf->global->MULTICOMPANY_THIRDPARTY_SHARING_ENABLED))) continue; + $uppername = strtoupper($element); + $constname = 'MULTICOMPANY_' . $uppername . '_SHARING_ENABLED'; + if (! empty($conf->global->$constname)) { + $shareentities = GETPOST($element.'_to', 'array'); + $shareentities = array_unique($shareentities); sort($shareentities); + $this->dao->options['sharings'][$element] = (! empty($shareentities) ? $shareentities : null); + if (! empty($conf->global->MULTICOMPANY_TEMPLATE_MANAGEMENT)) { + $this->dao->options['addtoallother'][$element] = GETPOST('addtoallother_'.$element, 'int'); + } + } + } + } + + $extrafields = new ExtraFields($this->db); + $extralabels = $extrafields->fetch_name_optionals_label($this->dao->table_element, true); + $extrafields->setOptionalsFromPost($extralabels, $this->dao); + + $id = $this->dao->create($user); + if ($id <= 0) + { + $error++; + $errors=($this->dao->error ? array($this->dao->error) : $this->dao->errors); + setEventMessage($errors, 'errors'); + $action = 'create'; + } + + if (! $error && $id > 0) + { + if (! empty($usetemplate) && is_numeric($usetemplate)) + { + $const = $this->dao->getEntityConfig($usetemplate); + if (! empty($const)) + { + // Reload modules + foreach ($const as $key => $value) + { + if (preg_match('/^MAIN\_MODULE\_([0-9A-Z]+)$/', $key, $reg)) + { + if (! empty($reg[1])) + { + $classname = 'mod' . ucfirst(strtolower($reg[1])); + + $res = @include_once DOL_DOCUMENT_ROOT.'/core/modules/'.$classname.'.class.php'; + + if ($res) { + dol_syslog(get_class($this)."::reloadModules template=".$usetemplate." module=".$key." classname=".$classname, LOG_DEBUG); + $mod=new $classname($this->db); + $mod->init('forceactivate'); + } else { + dol_syslog(get_class($this)."::reloadModules template=".$usetemplate." module=".$key." classname=".$classname, LOG_ERR); + } + } + } + } + + // Overwrite with template + foreach ($const as $key => $value) + { + dolibarr_set_const($this->db, $key, $value, 'chaine', 0, '', $id); + } + } + } + + $country_id = GETPOST('country_id', 'int'); + $country = getCountry($country_id, 'all'); + $country_code = $country['code']; + $country_label = $country['label']; + + dolibarr_set_const($this->db, "MAIN_INFO_SOCIETE_COUNTRY", $country_id.':'.$country_code.':'.$country_label,'chaine',0,'',$id); + dolibarr_set_const($this->db, "MAIN_INFO_SOCIETE_NOM",$name,'chaine',0,'',$id); + dolibarr_set_const($this->db, "MAIN_INFO_SOCIETE_ADDRESS",GETPOST('address', 'alpha'),'chaine',0,'',$id); + dolibarr_set_const($this->db, "MAIN_INFO_SOCIETE_TOWN",GETPOST('town', 'alpha'),'chaine',0,'',$id); + dolibarr_set_const($this->db, "MAIN_INFO_SOCIETE_ZIP",GETPOST('zipcode', 'alpha'),'chaine',0,'',$id); + dolibarr_set_const($this->db, "MAIN_INFO_SOCIETE_STATE",GETPOST('departement_id', 'int'),'chaine',0,'',$id); + dolibarr_set_const($this->db, "MAIN_MONNAIE",GETPOST('currency_code', 'alpha'),'chaine',0,'',$id); + dolibarr_set_const($this->db, "MAIN_LANG_DEFAULT",GETPOST('main_lang_default', 'alpha'),'chaine',0,'',$id); + + if (empty($usetemplate)) + { + $dir = "/multicompany/sql/"; + + // Load sql init_new_entity.sql file + $file = 'init_new_entity_nocrypt.sql'; + if (! empty($conf->db->dolibarr_main_db_encryption) && ! empty($conf->db->dolibarr_main_db_cryptkey)) + { + $file = 'init_new_entity.sql'; + } + $fullpath = dol_buildpath($dir.$file); + + if (file_exists($fullpath)) + { + $result=run_sql($fullpath,1,$id); + } + + $dir = "/multicompany/sql/dict/"; + + foreach($this->sharingdicts as $dict => $data) + { + // Load sql init_new_entity_dict.sql file + $file = 'init_new_entity_'.$dict.'.sql'; + $fullpath = dol_buildpath($dir.$file); + + if (file_exists($fullpath)) + { + $result = run_sql($fullpath, 1, $id); + } + } + } + else + { + require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + + $modulesdir = dolGetModulesDirs(); + + foreach ($modulesdir as $dir) + { + // Load modules attributes in arrays (name, numero, orders) from dir directory + //print $dir."\n
"; + $handle=@opendir(dol_osencode($dir)); + if (is_resource($handle)) + { + while (($file = readdir($handle))!==false) + { + if (is_readable($dir.$file) && substr($file, 0, 3) == 'mod' && substr($file, dol_strlen($file) - 10) == '.class.php') + { + $modName = substr($file, 0, dol_strlen($file) - 10); + + if ($modName) + { + include_once $dir."/".$file; + $objMod = new $modName($this->db); + // Load all lang files of module + if (isset($objMod->langfiles) && is_array($objMod->langfiles)) + { + foreach($objMod->langfiles as $domain) + { + $langs->load($domain); + } + } + // Load all permissions + if ($objMod->rights_class) + { + $ret=$objMod->insert_permissions(0, $id); + } + } + } + } + } + } + + // Add entity to all others entities + if (! empty($this->dao->options['addtoallother'])) + { + $this->dao->getEntities(true, array($id), false); + foreach ($this->dao->entities as $entity) + { + if (! is_array($entity->options)) $entity->options = array(); + if (! is_array($entity->options['sharings'])) $entity->options['sharings'] = array(); + + foreach($this->dao->options['sharings'] as $element => $values) + { + if (! is_array($entity->options['sharings'][$element])) $entity->options['sharings'][$element] = array(); + + if ($this->dao->options['addtoallother'][$element] == '1') + { + array_push($entity->options['sharings'][$element], (string) $id); + $entity->update($entity->id, $user); + } + } + } + } + + $listofgroups = $this->dao->getListOfGroups(); + if (! empty($listofgroups)) + { + foreach($listofgroups as $groupid) + { + // Duplicate usergroup rights + $ret = $this->duplicateUserGroupRights($groupid, $usetemplate, array($id)); + if ($ret < 0) $error++; + + // Add users to groups if linked with template + $userslist = $this->dao->getListOfUsersInGroupByTemplate($groupid, $usetemplate); + if ($userslist < 0) $error++; + elseif (! empty($userslist)) + { + foreach($userslist as $usertemplate) + { + $result = $usertemplate->SetInGroup($groupid, $id); + if ($result < 0) + { + $error++; + break; + } + } + } + } + } + } + + if (! $error) + { + $this->db->commit(); + } + else + { + $this->db->rollback(); + } + + if (! empty($addandstay)) + { + header("Location: " . $_SERVER['PHP_SELF'].'?action=edit&id='.$id); + exit; + } + } + else + { + $this->db->rollback(); + } + } + } + else if ($action === 'edit' && $user->admin && ! $user->entity) + { + $error=0; + + if (! empty($cancel)) + { + header("Location: " . $_SERVER['PHP_SELF']); + exit; + } + + if ($this->dao->fetch($id) < 0) + { + $error++; + setEventMessage($langs->trans("ErrorEntityIsNotValid"), 'errors'); + $action = ''; + } + } + else if ($action === 'update' && empty($cancel) && $id > 0 && $user->admin && ! $user->entity) + { + $error=0; + + if (! empty($cancelandstay)) + { + $action = 'edit'; + return; + } + + $ret = $this->dao->fetch($id); + if ($ret < 0) + { + $error++; + setEventMessage($langs->trans("ErrorEntityIsNotValid"), 'errors'); + $action = ''; + } + else if (empty($label)) + { + $error++; + setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentities("Label")), 'errors'); + $action = 'edit'; + } + else if (empty($name)) + { + $error++; + setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentities("CompanyName")), 'errors'); + $action = 'edit'; + } + + // Verify if label already exist in database + if (! $error) + { + $this->dao->getEntities(); + if (! empty($this->dao->entities)) + { + foreach($this->dao->entities as $entity) + { + if ($entity->id == $this->dao->id) continue; + if (strtolower($entity->label) == strtolower($label)) $error++; + } + if ($error) + { + setEventMessage($langs->trans("ErrorEntityLabelAlreadyExist"), 'errors'); + $action = 'edit'; + } + } + } + + if (! $error) + { + $this->db->begin(); + + $this->dao->label = $label; + $this->dao->description = $description; + + if (! empty($conf->global->MULTICOMPANY_SHARINGS_ENABLED)) { + $this->dao->options['proposalnumber_referent'] = (GETPOST('proposalnumber_referring_entity', 'int') ? GETPOST('proposalnumber_referring_entity', 'int') : null); + $this->dao->options['invoicenumber_referent'] = (GETPOST('invoicenumber_referring_entity', 'int') ? GETPOST('invoicenumber_referring_entity', 'int') : null); + foreach ($this->sharingelements as $element => $params) { + if ((($params['object'] || $params['objectnumber']) && ! isset($params['disable'])) && (empty($conf->societe->enabled) || empty($conf->global->MULTICOMPANY_THIRDPARTY_SHARING_ENABLED))) continue; + $uppername = strtoupper($element); + $constname = 'MULTICOMPANY_' . $uppername . '_SHARING_ENABLED'; + if (! empty($conf->global->$constname)) { + $shareentities = GETPOST($element.'_to', 'array'); + $shareentities = array_unique($shareentities); sort($shareentities); + $this->dao->options['sharings'][$element] = (! empty($shareentities) ? $shareentities : null); + if (! empty($conf->global->MULTICOMPANY_TEMPLATE_MANAGEMENT)) { + $this->dao->options['addtoallother'][$element] = GETPOST('addtoallother_'.$element, 'int'); + } + } + } + } + + $extrafields = new ExtraFields($this->db); + $extralabels = $extrafields->fetch_name_optionals_label($this->dao->table_element, true); + $extrafields->setOptionalsFromPost($extralabels, $this->dao); + + $ret = $this->dao->update($this->dao->id, $user); + if ($ret <= 0) + { + $error++; + $errors=($this->dao->error ? array($this->dao->error) : $this->dao->errors); + setEventMessage($errors, 'errors'); + $action = 'edit'; + } + + if (! $error && $ret > 0) + { + $country_id = GETPOST('country_id', 'int'); + $country = getCountry($country_id, 'all'); + $country_code = $country['code']; + $country_label = $country['label']; + + dolibarr_set_const($this->db, "MAIN_INFO_SOCIETE_COUNTRY", $country_id.':'.$country_code.':'.$country_label,'chaine',0,'',$this->dao->id); + dolibarr_set_const($this->db, "MAIN_INFO_SOCIETE_NOM",$name,'chaine',0,'',$this->dao->id); + dolibarr_set_const($this->db, "MAIN_INFO_SOCIETE_ADDRESS",GETPOST('address', 'alpha'),'chaine',0,'',$this->dao->id); + dolibarr_set_const($this->db, "MAIN_INFO_SOCIETE_TOWN",GETPOST('town', 'alpha'),'chaine',0,'',$this->dao->id); + dolibarr_set_const($this->db, "MAIN_INFO_SOCIETE_ZIP",GETPOST('zipcode', 'alpha'),'chaine',0,'',$this->dao->id); + dolibarr_set_const($this->db, "MAIN_INFO_SOCIETE_STATE",GETPOST('departement_id', 'int'),'chaine',0,'',$this->dao->id); + dolibarr_set_const($this->db, "MAIN_MONNAIE",GETPOST('currency_code', 'alpha'),'chaine',0,'',$this->dao->id); + dolibarr_set_const($this->db, "MAIN_LANG_DEFAULT",GETPOST('main_lang_default', 'alpha'),'chaine',0,'',$this->dao->id); + + $this->db->commit(); + + if (! empty($updateandstay)) { + $action = 'edit'; + } + } + else + { + $this->db->rollback(); + } + } + } + } + + /** + * Return action of hook + * @param object Linked object + */ + public function doActions($parameters=false, &$object, &$action='') + { + global $conf, $user; + global $mc; + + if (empty($conf->multicompany->enabled)) return 0; + + if (is_array($parameters) && ! empty($parameters)) + { + foreach($parameters as $key=>$value) + { + $$key=$value; + } + } + + $currentcontext = explode(':', $parameters['context']); + + // Clear constants cache after company infos update + if (is_array($currentcontext)) + { + if ((in_array('admincompany', $currentcontext) || in_array('adminihm', $currentcontext)) && ($action == 'update' || $action == 'updateedit')) + { + clearCache($conf->entity); + clearCache('constants_' . $conf->entity); + } + else if ((in_array('groupcard', $currentcontext) || in_array('groupperms', $currentcontext)) && $object->element == 'usergroup') + { + global $entity; + + // Users/Groups management only in master entity if transverse mode + if ($conf->entity > 1 && ! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) { + accessforbidden(); + } + + if (! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) { + $entity=(GETPOST('entity','int') ? GETPOST('entity','int') : $conf->entity); + } else { + $entity=(! empty($object->entity) ? $object->entity : $conf->entity); + } + + // Add/Remove user into group + if (! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE) && in_array('groupcard', $currentcontext) && ($action == 'adduser' || $action =='removeuser') && (! empty($userid) && $userid > 0) && $caneditperms) + { + if ($action == 'adduser') + { + $entities = GETPOST("entities", "array", 3); + + if (is_array($entities) && ! empty($entities)) + { + $error=0; + + foreach ($entities as $entity_id) + { + $object->fetch($id); + $object->oldcopy = clone $object; + + $edituser = new User($this->db); + $edituser->fetch($userid); + $result=$edituser->SetInGroup($object->id, $entity_id); + if ($result < 0) + { + $error++; + break; + } + } + if (!$error) + { + header("Location: " . $_SERVER['PHP_SELF'] . '?id=' . $object->id); + exit; + } + else + { + $this->error = $edituser->error; + $this->errors = $edituser->errors; + return -1; + } + } + } + else if ($action == 'removeuser') + { + $object->fetch($id); + $object->oldcopy = clone $object; + + $edituser = new User($this->db); + $edituser->fetch($userid); + $result=$edituser->RemoveFromGroup($object->id, $entity); + + if ($result > 0) + { + header("Location: " . $_SERVER['PHP_SELF'] . "?id=" . $object->id); + exit; + } + else + { + $this->error = $object->error; + $this->errors = $object->errors; + return -1; + } + } + return 1; + } + } + else if ((in_array('usercard', $currentcontext) || in_array('userperms', $currentcontext)) && $object->element == 'user') + { + global $entity, $caneditperms; + + // Users/Groups management only in master entity if transverse mode + if ($conf->entity > 1 && $conf->global->MULTICOMPANY_TRANSVERSE_MODE) + { + if (in_array('usercard', $currentcontext) && ($action == 'create' || $action == 'adduserldap')) { + accessforbidden(); + } else if (in_array('userperms', $currentcontext)) { + $caneditperms = false; + } + } + + if (! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) { + if (GETPOSTISSET('entity')) { + + $entity = GETPOST('entity','int'); + + } else { + + $entity = $conf->entity; + + // Check usergroup if user not in master entity + if (in_array('userperms', $currentcontext) && ! empty($user->admin) && empty($user->entity) && $conf->entity == 1) + { + require_once DOL_DOCUMENT_ROOT.'/user/class/usergroup.class.php'; + $group = new UserGroup($this->db); + $ret = $group->listGroupsForUser($object->id, false); + if (! empty(current($ret)->usergroup_entity)) { + sort(current($ret)->usergroup_entity); + if (current($ret)->usergroup_entity[0] > 1) { + $entity = current($ret)->usergroup_entity[0]; + } + } + } + } + } else { + $entity=(! empty($object->entity) ? $object->entity : $conf->entity); + } + + // Action add usergroup + if (! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE) && in_array('usercard', $currentcontext) && ($action == 'addgroup' || $action == 'removegroup') && (! empty($group) && $group > 0) && $caneditgroup) + { + if ($action == 'addgroup') + { + $entities = GETPOST("entities", "array", 3); + + if (is_array($entities) && ! empty($entities)) + { + $error=0; + + foreach ($entities as $entity_id) + { + $object->fetch($id); + $result = $object->SetInGroup($group, $entity_id); + if ($result < 0) + { + $error++; + break; + } + } + if ($error) + { + $this->error = $object->error; + $this->errors = $object->errors; + return -1; + } + else + { + header("Location: " . $_SERVER['PHP_SELF'] . '?id=' . $object->id); + exit; + } + } + } + else if ($action == 'removegroup') + { + $object->fetch($id); + $result = $object->RemoveFromGroup($group, $entity); + if ($result > 0) { + header("Location: " . $_SERVER['PHP_SELF'] . '?id=' . $object->id); + exit; + } + else + { + $this->error = $object->error; + $this->errors = $object->errors; + return -1; + } + } + return 1; + } + } + else if (in_array('productcard', $currentcontext) && ($object->element == 'product' || $object->element == 'service')) + { + if ($action != 'create' && $action != 'add') + { + if ($object->entity != $conf->entity) + { + global $usercanread, $usercancreate, $usercandelete; + + /*if (empty($user->rights->multicompany->product->read)) { + $usercanread = false; + }*/ + if (empty($user->rights->multicompany->product->write)) { + $usercancreate = false; + } + if (empty($user->rights->multicompany->product->delete)) { + $usercandelete = false; + } + } + } + } + else if (in_array('propalcard', $currentcontext) && $object->element == 'propal') + { + if ($action != 'create' && $action != 'add') + { + if ($object->entity != $conf->entity) + { + global $usercanread, $usercancreate, $usercandelete, $usercanvalidate, $usercansend, $usercanclose; + global $permissionnote, $permissiondellink, $permissiontoedit; + global $disableedit, $disablemove, $disableremove; + + $this->getInstanceDao(); + + $constants = array( + 'PROPALE_ADDON', + 'PROPALE_SAPHIR_MASK', + 'PROPALE_ADDON_PDF', + 'PROPALE_ADDON_PDF_ODT_PATH' + ); + + if (empty($conf->global->MULTICOMPANY_PROPOSALNUMBER_SHARING_ENABLED) || empty($mc->sharings['proposalnumber'])) // Check if current entity not use the proposalnumber sharing + { + foreach ($constants as $constname) + { + $res = $this->dao->getEntityConfig($object->entity, $constname); + if (! empty($res[$constname])) { + $conf->global->$constname = $res[$constname]; // override current entity config with object entity config + } + } + } + else + { + foreach ($constants as $constname) + { + $referent = (! empty($mc->proposalnumber_referent)?$mc->proposalnumber_referent:1); + $res = $this->dao->getEntityConfig($referent, $constname); + if (! empty($res[$constname])) { + $conf->global->$constname = $res[$constname]; // override current entity config with referent config + } + } + } + + // Override $mysoc with data of object entity + if ($action == 'builddoc') + { + global $mysoc; + + $current = $this->dao->getEntityConfig($conf->entity, 'MAIN_INFO_*'); + if (! empty($current)) + { + foreach($current as $constname => $value) + { + unset($conf->global->$constname); + } + } + + $other = $this->dao->getEntityConfig($object->entity, 'MAIN_INFO_*'); + if (! empty($other)) + { + foreach($other as $constname => $value) + { + $conf->global->$constname = $value; // override current entity config with referent config + } + } + + $mysoc->setMysoc($conf); + } + + if (empty($user->rights->multicompany->propal->read)) { + $usercanread = false; + } + if (empty($user->rights->multicompany->propal->write)) { + $usercancreate = false; + + $permissionnote = $usercancreate; // Used by the include of actions_setnotes.inc.php + $permissiondellink = $usercancreate; // Used by the include of actions_dellink.inc.php + $permissiontoedit = $usercancreate; // Used by the include of actions_lineupdown.inc.php + + // for object lines + $disableedit = true; + $disablemove = true; + $disableremove = true; + } + if (empty($user->rights->multicompany->propal->delete)) { + $usercandelete = false; + } + if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($usercancreate)) || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->multicompany->propal_advance->validate))) { + $usercanvalidate = false; + } + if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($usercanread)) || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->multicompany->propal_advance->send))) { + $usercansend = false; + } + if (empty($user->rights->multicompany->propal->close)) { + $usercanclose = false; + } + } + } + } + else if (in_array('ordercard', $currentcontext) && $object->element == 'commande') + { + if ($action != 'create' && $action != 'add') + { + if ($object->entity != $conf->entity) + { + global $usercanread, $usercancreate, $usercandelete, $usercanvalidate, $usercansend, $usercanclose, $usercancancel; + global $permissionnote, $permissiondellink, $permissiontoedit; + global $disableedit, $disablemove, $disableremove; + + $this->getInstanceDao(); + + $constants = array( + 'COMMANDE_ADDON', + 'COMMANDE_SAPHIR_MASK', + 'COMMANDE_ADDON_PDF', + 'COMMANDE_ADDON_PDF_ODT_PATH' + ); + + if (empty($conf->global->MULTICOMPANY_ORDERNUMBER_SHARING_ENABLED) || empty($mc->sharings['ordernumber'])) // Check if current entity not use the proposalnumber sharing + { + foreach ($constants as $constname) + { + $res = $this->dao->getEntityConfig($object->entity, $constname); + if (! empty($res[$constname])) { + $conf->global->$constname = $res[$constname]; // override current entity config with object entity config + } + } + } + else + { + foreach ($constants as $constname) + { + $referent = (! empty($mc->ordernumber_referent)?$mc->ordernumber_referent:1); + $res = $this->dao->getEntityConfig($referent, $constname); + if (! empty($res[$constname])) { + $conf->global->$constname = $res[$constname]; // override current entity config with referent config + } + } + } + + // Override $mysoc with data of object entity + if ($action == 'builddoc') + { + global $mysoc; + + $current = $this->dao->getEntityConfig($conf->entity, 'MAIN_INFO_*'); + if (! empty($current)) + { + foreach($current as $constname => $value) + { + unset($conf->global->$constname); + } + } + + $other = $this->dao->getEntityConfig($object->entity, 'MAIN_INFO_*'); + if (! empty($other)) + { + foreach($other as $constname => $value) + { + $conf->global->$constname = $value; // override current entity config with referent config + } + } + + $mysoc->setMysoc($conf); + } + + if (empty($user->rights->multicompany->order->read)) { + $usercanread = false; + } + if (empty($user->rights->multicompany->order->write)) { + $usercancreate = false; + + $permissionnote = $usercancreate; // Used by the include of actions_setnotes.inc.php + $permissiondellink = $usercancreate; // Used by the include of actions_dellink.inc.php + $permissiontoedit = $usercancreate; // Used by the include of actions_lineupdown.inc.php + + // for object lines + $disableedit = true; + $disablemove = true; + $disableremove = true; + } + if (empty($user->rights->multicompany->order->delete)) { + $usercandelete = false; + } + if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($usercancreate)) || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->multicompany->order_advance->validate))) { + $usercanvalidate = false; + } + if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($usercancreate)) || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->multicompany->order_advance->cancel))) { + $usercancancel = false; + } + if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($usercanread)) || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->multicompany->order_advance->send))) { + $usercansend = false; + } + if (empty($user->rights->multicompany->order->close)) { + $usercanclose = false; + } + } + } + } + else if (in_array('invoicecard', $currentcontext) && $object->element == 'facture') + { + if ($action != 'create' && $action != 'add') + { + if ($object->entity != $conf->entity) + { + global $usercanread, $usercancreate, $usercandelete, $usercanvalidate, $usercansend, $usercanreopen, $usercanunvalidate; + global $permissionnote, $permissiondellink, $permissiontoedit; + global $disableedit, $disablemove, $disableremove; + + $this->getInstanceDao(); + + $constants = array( + 'FACTURE_ADDON', + 'FACTURE_MERCURE_MASK_INVOICE', + 'FACTURE_MERCURE_MASK_CREDIT', + 'FACTURE_MERCURE_MASK_DEPOSIT', + 'FACTURE_MERCURE_MASK_REPLACEMENT', + 'PROPALE_ADDON_PDF', + 'FACTURE_ADDON_PDF_ODT_PATH' + ); + + if (empty($conf->global->MULTICOMPANY_INVOICENUMBER_SHARING_ENABLED) || empty($mc->sharings['invoicenumber'])) // Check if current entity not use the proposalnumber sharing + { + foreach ($constants as $constname) + { + $res = $this->dao->getEntityConfig($object->entity, $constname); + if (! empty($res[$constname])) { + $conf->global->$constname = $res[$constname]; // override current entity config with object entity config + } + } + } + else + { + foreach ($constants as $constname) + { + $referent = (! empty($mc->invoicenumber_referent)?$mc->invoicenumber_referent:1); + $res = $this->dao->getEntityConfig($referent, $constname); + if (! empty($res[$constname])) { + $conf->global->$constname = $res[$constname]; // override current entity config with referent config + } + } + } + + // Override $mysoc with data of object entity + if ($action == 'builddoc') + { + global $mysoc; + + $current = $this->dao->getEntityConfig($conf->entity, 'MAIN_INFO_*'); + if (! empty($current)) + { + foreach($current as $constname => $value) + { + unset($conf->global->$constname); + } + } + + $other = $this->dao->getEntityConfig($object->entity, 'MAIN_INFO_*'); + if (! empty($other)) + { + foreach($other as $constname => $value) + { + $conf->global->$constname = $value; // override current entity config with referent config + } + } + + $mysoc->setMysoc($conf); + } + + if (empty($user->rights->multicompany->invoice->read)) { + $usercanread = false; + } + if (empty($user->rights->multicompany->invoice->write)) { + $usercancreate = false; + + $permissionnote = $usercancreate; // Used by the include of actions_setnotes.inc.php + $permissiondellink = $usercancreate; // Used by the include of actions_dellink.inc.php + $permissiontoedit = $usercancreate; // Used by the include of actions_lineupdown.inc.php + + // for object lines + $disableedit = true; + $disablemove = true; + $disableremove = true; + } + if (empty($user->rights->multicompany->invoice->delete)) { + $usercandelete = false; + } + if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($usercancreate)) || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->multicompany->invoice_advance->validate))) { + $usercanvalidate = false; + } + if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($usercanread)) || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->multicompany->invoice_advance->send))) { + $usercansend = false; + } + if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($usercancreate)) || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->multicompany->invoice_advance->reopen))) { + $usercanreopen = false; + } + if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($usercancreate)) || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->multicompany->invoice_advance->unvalidate))) { + $usercanunvalidate = false; + } + } + } + } + } + + //var_dump($_POST); +/* + if (empty($_SESSION['dol_tables_list_fk_soc'])) + { + $_SESSION['dol_tables_list_fk_soc'] = getTablesWithField('fk_soc', array()); + } + var_dump($_SESSION['dol_tables_list_fk_soc']); +*/ + //$include=false; + //$exclude=false; +/* + $exclude = array( + MAIN_DB_PREFIX . 'user', + MAIN_DB_PREFIX . 'user_employment', + MAIN_DB_PREFIX . 'user_param', + MAIN_DB_PREFIX . 'user_rib', + MAIN_DB_PREFIX . 'user_rights', + MAIN_DB_PREFIX . 'usergroup', + MAIN_DB_PREFIX . 'usergroup_rights', + MAIN_DB_PREFIX . 'usergroup_user', + MAIN_DB_PREFIX . 'rights_def', + ); +*/ + //$exclude = '/(const|user|rights\_def)+/'; + //$include = '/(const|user|rights\_def)+/'; + + //if (empty($_SESSION['dol_tables_list_entity'])) +/* { + $_SESSION['dol_tables_list_entity'] = getTablesWithField('entity', $exclude, $include); + } + + var_dump($_SESSION['dol_tables_list_entity']); +*/ +/* + if (! empty($conf->global->MULTICOMPANY_SHARINGS_ENABLED) && ! empty($conf->global->MULTICOMPANY_THIRDPARTY_SHARING_ENABLED) && ! empty($mc->sharings['thirdparty'])) + { + if (in_array($contextpage, $this->thirdpartycontextlist) || in_array($contextpage, $this->contactcontextlist)) + { + if (GETPOST('confirmmassaction') && GETPOST('massaction') == 'modify_entity') + { + var_dump($_POST['toselect']); + } + } + } +*/ + return 0; + } + + /** + * + */ + public function showLinkedObjectBlock($parameters=false, &$object, &$action='') + { + global $conf, $user, $langs; + global $mc; + + if (empty($conf->multicompany->enabled)) return 0; + + if (is_array($parameters) && ! empty($parameters)) + { + foreach($parameters as $key=>$value) + { + $$key=$value; + } + } + + $currentcontext = explode(':', $parameters['context']); + + //var_dump($object->linkedObjects); + + foreach($object->linkedObjects as $objecttype => $objects) + { + foreach($objects as $key => $tmpobj) + { + if (empty($tmpobj->entity)) continue; // for debug + + if ($tmpobj->entity != $conf->entity) + { + $element = $objecttype; + if ($objecttype == 'propal') $element = 'proposal'; + if ($objecttype == 'commande') $element = 'order'; + if ($objecttype == 'facture') $element = 'invoice'; + + //var_dump($element);var_dump($mc->sharings[$element]); + //var_dump($object->linkedObjects[$objecttype][$key]); + + if (! empty($mc->sharings[$element]) && in_array($tmpobj->entity, $mc->sharings[$element])) + { + //nothing + } + else + { + unset($object->linkedObjects[$objecttype][$key]); + } + } + } + } + + return 0; + } + + /** + * + */ + public function showLinkToObjectBlock($parameters=false, &$object, &$action='') + { + global $conf, $user, $langs; + + if (empty($conf->multicompany->enabled)) return 0; + + if (is_array($parameters) && ! empty($parameters)) + { + foreach($parameters as $key=>$value) + { + $$key=$value; + } + } + + $currentcontext = explode(':', $parameters['context']); + + $perms = 1; + $propalperms = 1; + $orderperms = 1 ; + $invoiceperms = 1 ; + + if (in_array('propalcard', $currentcontext) && $object->element == 'propal') + { + if ($object->entity != $conf->entity) + { + $propalperms = ! empty($user->rights->multicompany->propal->write); + } + } + elseif (in_array('ordercard', $currentcontext) && $object->element == 'commande') + { + if ($object->entity != $conf->entity) + { + $orderperms = ! empty($user->rights->multicompany->order->write); + } + } + elseif (in_array('invoicecard', $currentcontext) && $object->element == 'facture') + { + if ($object->entity != $conf->entity) + { + $invoiceperms = ! empty($user->rights->multicompany->invoice->write); + } + } + + $this->results = array('propal' => array('enabled'=>$conf->propal->enabled, 'perms'=>$propalperms, 'label'=>'LinkToProposal', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."propal as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('propal').')'), + 'order'=>array('enabled'=>$conf->commande->enabled, 'perms'=>$orderperms, 'label'=>'LinkToOrder', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."commande as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('commande').')'), + 'invoice'=>array('enabled'=>$conf->facture->enabled, 'perms'=>$invoiceperms, 'label'=>'LinkToInvoice', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_client, t.total as total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."facture as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('invoice').')'), + 'contrat'=>array('enabled'=>$conf->contrat->enabled , 'perms'=>$perms, 'label'=>'LinkToContract', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, '' as total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."contrat as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('contract').')'), + 'fichinter'=>array('enabled'=>$conf->ficheinter->enabled, 'perms'=>$perms, 'label'=>'LinkToIntervention', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."fichinter as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('intervention').')'), + 'supplier_proposal'=>array('enabled'=>$conf->supplier_proposal->enabled , 'perms'=>$perms, 'label'=>'LinkToSupplierProposal', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, '' as ref_supplier, t.total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."supplier_proposal as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('supplier_proposal').')'), + 'order_supplier'=>array('enabled'=>$conf->supplier_order->enabled , 'perms'=>$perms, 'label'=>'LinkToSupplierOrder', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, t.total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."commande_fournisseur as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('commande_fournisseur').')'), + 'invoice_supplier'=>array('enabled'=>$conf->supplier_invoice->enabled , 'perms'=>$perms, 'label'=>'LinkToSupplierInvoice', 'sql'=>"SELECT s.rowid as socid, s.nom as name, s.client, t.rowid, t.ref, t.ref_supplier, t.total_ht FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."facture_fourn as t WHERE t.fk_soc = s.rowid AND t.fk_soc IN (".$listofidcompanytoscan.') AND t.entity IN ('.getEntity('facture_fourn').')') + ); + + return 1; + } + + /** + * + */ + public function addMoreActionsButtons($parameters=false, &$object, &$action='') + { + global $conf, $user, $langs; + + if (empty($conf->multicompany->enabled)) return 0; + + if (is_array($parameters) && ! empty($parameters)) + { + foreach($parameters as $key=>$value) + { + $$key=$value; + } + } + + $currentcontext = explode(':', $parameters['context']); + + /*if (in_array('productcard', $currentcontext) && ($object->element == 'product' || $object->element == 'service')) + { + if ($object->entity != $conf->entity) + { + $user->rights->produit->creer = 0; + $user->rights->produit->supprimer = 0; + $user->rights->service->creer = 0; + $user->rights->service->supprimer = 0; + + //return 1; + } + }*/ + + return 0; + } + + /** + * + */ + public function printUserPasswordField($parameters=false, &$object, &$action='') + { + global $conf, $user, $langs; + + if (empty($conf->multicompany->enabled)) return 0; + + $langs->load('multicompany@multicompany'); + + if (is_array($parameters) && ! empty($parameters)) + { + foreach($parameters as $key=>$value) + { + $$key=$value; + } + } + + $currentcontext = explode(':', $parameters['context']); + + $this->resprints = "\n".''."\n"; + + if (in_array('usercard', $currentcontext) && $object->element == 'user' && ! empty($conf->global->MULTICOMPANY_HIDE_LOGIN_COMBOBOX) && checkMulticompanyAutentication()) + { + if ($action == 'create') + { + $this->resprints.= ''; + } + else if ($action == 'edit') + { + if ($caneditpassword) + { + $this->resprints.= ''; + } + else + { + $this->resprints.= preg_replace('/./i','*',$object->pass); + } + } + else + { + if ($object->pass) $this->resprints.= preg_replace('/./i','*',$object->pass); + else + { + if ($user->admin) $this->resprints.= ($valuetoshow?(' '.$langs->trans("or").' '):'').$langs->trans("Crypted").': '.$object->pass_indatabase_crypted; + else $this->resprints.= $langs->trans("Hidden"); + } + } + } + + $this->resprints.= ''."\n"; + + return 0; + } + + /** + * + */ + public function formConfirm($parameters=false, &$object, &$action='') + { + global $conf, $langs; + global $mc, $form; + + if (empty($conf->multicompany->enabled)) return 0; + + $langs->load('multicompany@multicompany'); + + if (is_array($parameters) && ! empty($parameters)) + { + foreach($parameters as $key=>$value) + { + $$key=$value; + } + } + + $return = 0; + $currentcontext = explode(':', $parameters['context']); + + $this->resprints = "\n".''."\n"; + + if (in_array('propalcard', $currentcontext) && $object->element == 'propal') + { + if ($action == 'clone' && ! empty($mc->entities['proposal'])) { + // Create an array for form + $formquestion = array( + // 'text' => $langs->trans("ConfirmClone"), + // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1), + // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1), + array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', '(s.client=1 OR s.client=2 OR s.client=3)')), + array('type' => 'other', 'name' => 'entity', 'label' => $langs->trans("SelectEntity"), 'value' => $mc->select_entities($conf->entity, 'entity', '', false, false, false, explode(',', $mc->entities['proposal']))) + ); + if (!empty($conf->global->PROPAL_CLONE_DATE_DELIVERY) && !empty($object->date_livraison)) { + $formquestion[] = array('type' => 'date', 'name' => 'date_delivery', 'label' => $langs->trans("DeliveryDate"), 'value' => $object->date_livraison); + } + // Incomplete payment. We ask if reason = discount or other + $this->resprints.= $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmClonePropal', $object->ref), 'confirm_clone', $formquestion, 'yes', 1); + $return++; + } + } + + $this->resprints.= ''."\n"; + + return $return; + } + + /** + * + */ + public function formObjectOptions($parameters=false, &$object, &$action='') + { + global $conf, $user, $langs; + global $form; + + if (empty($conf->multicompany->enabled)) return 0; + + $langs->load('multicompany@multicompany'); + + if (is_array($parameters) && ! empty($parameters)) + { + foreach($parameters as $key=>$value) + { + $$key=$value; + } + } + + $currentcontext = explode(':', $parameters['context']); + + $this->resprints = "\n".''."\n"; + + if (in_array('thirdpartycard', $currentcontext) && $object->element == 'societe' && ! empty($user->admin) && empty($user->entity)) + { + if ($action == 'create') + { + $this->resprints.= ''.fieldLabel('Entity','entity').''; + $s = $this->select_entities($conf->entity); + $this->resprints.= $form->textwithpicto($s,$langs->trans("ThirdpartyEntityDesc"),1); + $this->resprints.= ''."\n"; + } + } + else if (in_array('contactcard', $currentcontext) && $object->element == 'contact' && ! empty($user->admin) && empty($user->entity)) + { + if ($action == 'create' && empty($objsoc)) + { + $this->resprints.= ''.fieldLabel('Entity','entity').''; + $s = $this->select_entities($conf->entity); + $this->resprints.= $form->textwithpicto($s,$langs->trans("ContactEntityDesc"),1); + $this->resprints.= ''."\n"; + } + } + else if (in_array('usercard', $currentcontext) && $object->element == 'user') + { + if ($action == 'edit') + { + // TODO check if user not linked with the current entity before change entity (thirdparty, invoice, etc.) !! + if (empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE) && $conf->entity == 1 && ! empty($user->admin) && empty($user->entity)) + { + $this->resprints.= ''.$langs->trans("Entity").''; + $this->resprints.= ''.$this->select_entities($object->entity); + $this->resprints.= "\n"; + } + else + { + $this->resprints.= ''; + } + } + else if ($action == 'create') + { + if (empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE) && $conf->entity == 1 && ! empty($user->admin) && empty($user->entity)) + { + $this->resprints.= ''.$langs->trans("Entity").''; + $this->resprints.= ''.$this->select_entities($conf->entity); + $this->resprints.= "\n"; + } + else + { + $this->resprints.= ''; + } + } + else if ($action != 'adduserldap') + { + if (empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE) && $conf->entity == 1 && ! empty($user->admin) && empty($user->entity)) + { + $this->resprints.= ''.$langs->trans("Entity").''; + if (empty($object->entity)) + { + $this->resprints.= $langs->trans("AllEntities"); + } + else + { + $this->getInfo($object->entity); + $this->resprints.= $this->label; + } + $this->resprints.= "\n"; + } + } + } + else if ((in_array('propalcard', $currentcontext) && $object->element == 'propal') + || (in_array('ordercard', $currentcontext) && $object->element == 'commande') + || (in_array('invoicecard', $currentcontext) && $object->element == 'facture') + ) + { + if ($action == 'create') + { + $this->resprints.= ''.$langs->trans("Entity").''; + $this->resprints.= ''.$this->select_entities($conf->entity); + $this->resprints.= "\n"; + } + } + + $this->resprints.= ''."\n"; + + return 0; + } + + /** + * + */ + public function formCreateThirdpartyOptions($parameters=false, &$object, &$action='') + { + global $conf, $user, $langs; + global $form; + + if (empty($conf->multicompany->enabled)) return 0; + + $langs->load('multicompany@multicompany'); + + if (is_array($parameters) && ! empty($parameters)) + { + foreach($parameters as $key=>$value) + { + $$key=$value; + } + } + + //echo 'OK'; + + //$this->resprints = 'OK'; + + return 0; + } + + /** + * + */ + public function formAddUserToGroup($parameters=false, &$object, &$action='') + { + global $conf, $user, $langs; + global $form, $mc, $exclude; + + if (empty($conf->multicompany->enabled)) return 0; + + $langs->load('multicompany@multicompany'); + + if (is_array($parameters) && ! empty($parameters)) + { + foreach($parameters as $key=>$value) + { + $$key=$value; + } + } + + $currentcontext = explode(':', $parameters['context']); + + $this->resprints = ''; + + if (is_array($currentcontext)) + { + if (in_array('usercard', $currentcontext) && $object->element == 'user') + { + if ($action != 'edit' && $action != 'presend' && ! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) + { + $this->resprints = "\n".''."\n"; + + if (! empty($groupslist)) + { + $exclude=array(); + } + + if ($caneditgroup) + { + $this->resprints.= '
'."\n"; + $this->resprints.= ''; + $this->resprints.= ''; + } + $this->resprints.= ''."\n"; + + $this->resprints.= ''."\n"; + if (! empty($user->admin)) + { + $this->resprints.= ''; + } + $this->resprints.= ''."\n"; + + /* + * Groups assigned to user + */ + if (! empty($groupslist)) + { + foreach($groupslist as $group) + { + $this->resprints.= ''; + $this->resprints.= ''; + if (! empty($user->admin)) + { + $this->resprints.= ''."\n"; + } + } + else + { + $this->resprints.= ''; + } + + $this->resprints.= "
'.$langs->trans("Groups").''.$langs->trans("Entity").''; + if ($caneditgroup && empty($user->entity)) + { + // Users/Groups management only in master entity if transverse mode + if ($conf->entity == 1) + { + $this->resprints.= $form->select_dolgroups('', 'group', 1, $exclude, 0, '', '', $object->entity); + $this->resprints.= '   '; + if ($conf->entity == 1) + { + $entities = $this->getEntitiesList(); + $this->resprints.= $form->multiselectarray('entities', $entities, GETPOST('entities', 'array'), '', 0, '', 0, '20%'); + } + else + { + $this->resprints.= ''; + } + $this->resprints.= ''; + } + } + $this->resprints.= '
'; + if ($caneditgroup) + { + $this->resprints.= ''.img_object($langs->trans("ShowGroup"),"group").' '.$group->name.''; + } + else + { + $this->resprints.= img_object($langs->trans("ShowGroup"),"group").' '.$group->name; + } + $this->resprints.= ''; + if (! empty($group->usergroup_entity)) + { + $nb=0; + foreach($group->usergroup_entity as $group_entity) + { + $mc->getInfo($group_entity); + if (empty($conf->global->MULTICOMPANY_TEMPLATE_MANAGEMENT) && $mc->visible == 2) continue; + + $this->resprints.= ''; + if ($mc->visible == 2) { + $this->resprints.= ''; + } else { + $this->resprints.= ''; + } + $this->resprints.= $mc->label . (empty($mc->active) ? ' ('.$langs->trans('Disabled').')' : ($mc->visible == 2 ? ' ('.$langs->trans('Template').')' : (empty($mc->visible) ? ' ('.$langs->trans('Hidden').')' : '')) ); + if ($conf->entity == 1 && empty($user->entity)) { + $this->resprints.= ''; + $this->resprints.= img_picto($langs->trans("RemoveFromGroup"), 'unlink'); + $this->resprints.= ''; + } + $this->resprints.= ''; + } + } + } + $this->resprints.= ' 
'.$langs->trans("None").'
"; + + if ($caneditgroup) + { + $this->resprints.= '
'; + } + + $this->resprints.= ''."\n"; + + return 1; + } + } + else if (in_array('groupcard', $currentcontext) && $object->element == 'usergroup') + { + if ($action != 'edit' && ! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) + { + $this->resprints = "\n".''."\n"; + + if (! empty($object->members)) + { + $exclude=array(); + } + + if ($caneditperms && empty($user->entity)) + { + $this->resprints.= '
'."\n"; + $this->resprints.= ''; + $this->resprints.= ''; + $this->resprints.= ''."\n"; + $this->resprints.= ''."\n"; + $this->resprints.= ''."\n"; + $this->resprints.= '
'.$langs->trans("NonAffectedUsers").''; + $this->resprints.= $form->select_dolusers('', 'user', 1, $exclude, 0, '', '', $object->entity); + $this->resprints.= '   '; + if ($conf->entity == 1) + { + $entities = $this->getEntitiesList(false, false, false, (empty($conf->global->MULTICOMPANY_TEMPLATE_MANAGEMENT) ? false : true)); + $this->resprints.= $form->multiselectarray('entities', $entities, GETPOST('entities', 'array'), '', 0, '', 0, '20%'); + } + else + { + $this->resprints.= ''; + } + $this->resprints.= ''; + $this->resprints.= '
'."\n"; + $this->resprints.= '
'; + } + + /* + * Group members + */ + $this->resprints.= ''; + $this->resprints.= ''; + $this->resprints.= ''; + $this->resprints.= ''; + $this->resprints.= ''; + if ($conf->entity == 1) + { + $this->resprints.= ''; + } + $this->resprints.= ''; + $this->resprints.= ''; + $this->resprints.= "\n"; + + if (! empty($object->members)) + { + foreach($object->members as $useringroup) + { + $this->resprints.= ''; + $this->resprints.= ''; + $this->resprints.= ''; + $this->resprints.= ''; + if ($conf->entity == 1 && ! empty($user->admin)) + { + $this->resprints.= ''; + } + $this->resprints.= ''; + $this->resprints.= '\n"; + } + } + else + { + $this->resprints.= ''; + } + $this->resprints.= "
'.$langs->trans("Login").''.$langs->trans("Lastname").''.$langs->trans("Firstname").''.$langs->trans("Entity").''.$langs->trans("Status").' 
'; + $this->resprints.= $useringroup->getNomUrl(-1, '', 0, 0, 24, 0, 'login'); + if ($useringroup->admin && ! $useringroup->entity) $this->resprints.= img_picto($langs->trans("SuperAdministrator"),'redstar'); + else if ($useringroup->admin) $this->resprints.= img_picto($langs->trans("Administrator"),'star'); + $this->resprints.= ''.$useringroup->lastname.''.$useringroup->firstname.''; + if (! empty($useringroup->usergroup_entity)) + { + foreach($useringroup->usergroup_entity as $group_entity) + { + $mc->getInfo($group_entity); + if (empty($conf->global->MULTICOMPANY_TEMPLATE_MANAGEMENT) && $mc->visible == 2) continue; + + $this->resprints.= ''; + if ($mc->visible == 2) { + $this->resprints.= ''; + } else { + $this->resprints.= ''; + } + $this->resprints.= $mc->label . (empty($mc->active) ? ' ('.$langs->trans('Disabled').')' : ($mc->visible == 2 ? ' ('.$langs->trans('Template').')' : (empty($mc->visible) ? ' ('.$langs->trans('Hidden').')' : '')) ); + if (empty($user->entity)) { + $this->resprints.= ''; + $this->resprints.= img_picto($langs->trans("RemoveFromGroup"), 'unlink'); + $this->resprints.= ''; + } + $this->resprints.= ''; + } + } + $this->resprints.= ''.$useringroup->getLibStatut(3).''; + $this->resprints.= "-"; + $this->resprints.= "
'.$langs->trans("None").'
"; + + $this->resprints.= ''."\n"; + + return 1; + } + } + } + + return 0; + } + + /** + * + */ + public function moreHtmlRef($parameters=false, &$object, &$action='') + { + global $conf, $user, $langs; + global $mc; + + if (empty($conf->multicompany->enabled)) return 0; + + if (is_array($parameters) && ! empty($parameters)) + { + foreach($parameters as $key=>$value) + { + $$key=$value; + } + } + + $currentcontext = explode(':', $parameters['context']); + + $this->resprints = "\n".''."\n"; + + // if global sharings is enabled + if (! empty($conf->global->MULTICOMPANY_SHARINGS_ENABLED)) + { + $this->getInfo(! empty($object->entity) ? $object->entity : $conf->entity); + + // if third party sharing is enabled (is mandatory for some sharings) + if (! empty($conf->societe->enabled) && ! empty($conf->global->MULTICOMPANY_THIRDPARTY_SHARING_ENABLED) && ! empty($mc->sharings['thirdparty'])) + { + if ($object->element == 'societe') + { + if (in_array('thirdpartycard', $currentcontext)) + { + if ($action != 'create' && $action != 'edit') + { + if ($object->isObjectUsed($object->id) === 0 && ((! empty($user->admin) && ! $user->entity) || ! empty($user->rights->multicompany->thirdparty->write))) + { + $selectEntities = $this->getModifyEntityDialog('thirdparty', 'modifyEntity', $object); + + if (! empty($selectEntities)) { + $this->resprints.= '
'; + $this->resprints.= ''.$this->label.''; + $this->resprints.= '
'; + $this->resprints.= $selectEntities; + } else { + $this->resprints.= '
'; + $this->resprints.= ''.$this->label.''; + $this->resprints.= '
'; + } + } + else + { + $this->resprints.= '
'; + $this->resprints.= ''.$this->label.''; + $this->resprints.= '
'; + } + } + } + else + { + $this->resprints.= '
'; + $this->resprints.= ''.$this->label.''; + $this->resprints.= '
'; + } + } + else if ($object->element == 'contact') + { + if (in_array('contactcard', $currentcontext)) + { + if ($action != 'create' && $action != 'edit') + { + if (empty($object->socid) && ((! empty($user->admin) && ! $user->entity) || ! empty($user->rights->multicompany->contact->write))) + { + $selectEntities = $this->getModifyEntityDialog('contact', 'modifyEntity', $object); + + if (! empty($selectEntities)) { + $this->resprints.= '
'; + $this->resprints.= ''.$this->label.''; + $this->resprints.= '
'; + $this->resprints.= $selectEntities; + } else { + $this->resprints.= '
'; + $this->resprints.= ''.$this->label.''; + $this->resprints.= '
'; + } + } + else + { + $this->resprints.= '
'; + $this->resprints.= ''.$this->label.''; + $this->resprints.= '
'; + } + } + } + else + { + $this->resprints.= '
'; + $this->resprints.= ''.$this->label.''; + $this->resprints.= '
'; + } + } + } + + if (((! empty($conf->product->enabled) || ! empty($conf->service->enabled)) && $object->element == 'product' && ! empty($conf->global->MULTICOMPANY_PRODUCT_SHARING_ENABLED) && ! empty($mc->sharings['product'])) + || (! empty($conf->propal->enabled) && $object->element == 'propal' && in_array('propalcard', $currentcontext) && ! empty($conf->global->MULTICOMPANY_PROPOSAL_SHARING_ENABLED) && ! empty($mc->sharings['proposal'])) + || (! empty($conf->commande->enabled) && $object->element == 'commande' && in_array('ordercard', $currentcontext) && ! empty($conf->global->MULTICOMPANY_ORDER_SHARING_ENABLED) && ! empty($mc->sharings['order'])) + || (! empty($conf->facture->enabled) && $object->element == 'facture' && in_array('invoicecard', $currentcontext) && ! empty($conf->global->MULTICOMPANY_INVOICE_SHARING_ENABLED) && ! empty($mc->sharings['invoice'])) + || (! empty($conf->stock->enabled) && $object->element == 'stock' && in_array('warehousecard', $currentcontext) && ! empty($conf->global->MULTICOMPANY_STOCK_SHARING_ENABLED) && ! empty($mc->sharings['stock'])) + ) + { + $this->resprints.= '
'; + $this->resprints.= ''.$this->label.''; + $this->resprints.= '
'; + } + } + + if ($object->element == 'user' || $object->element == 'usergroup') + { + if (empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE) && $conf->entity == 1 && ! empty($user->admin) && empty($user->entity)) + { + $this->getInfo($object->entity); + $this->resprints.= '
'; + $this->resprints.= ''.$this->label.''; + $this->resprints.= '
'; + } + } + + $this->resprints.= ''."\n"; + + return 0; + } + + /** + * + */ + public function moreHtmlStatus($parameters=false, &$object, &$action='') + { + global $conf, $user; + + if (empty($conf->multicompany->enabled)) return 0; + + if (is_array($parameters) && ! empty($parameters)) + { + foreach($parameters as $key=>$value) + { + $$key=$value; + } + } + + //$this->resprints.= 'OK'; + + return 0; + } + + /** + * + */ + public function printUserListWhere($parameters=false) + { + global $conf, $user; + + if (empty($conf->multicompany->enabled)) return 0; + + if (is_array($parameters) && ! empty($parameters)) + { + foreach($parameters as $key=>$value) + { + $$key=$value; + } + } + + $this->resprints = ''; + + if (! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) { + if (! empty($user->admin) && empty($user->entity) && $conf->entity == 1) { + $this->resprints.= " WHERE u.entity IS NOT NULL"; // Show all users + } else { + $this->resprints.= ",".MAIN_DB_PREFIX."usergroup_user as ug"; + $this->resprints.= " WHERE ((ug.fk_user = u.rowid"; + $this->resprints.= " AND ug.entity IN (".getEntity('usergroup')."))"; + $this->resprints.= " OR u.entity = 0)"; // Show always superadmin + } + return 1; + } + + return 0; + } + + /** + * + * @return number + */ + public function addMoreMassActions($parameters=false) + { + global $conf, $user, $langs; + global $mc; + + if (empty($conf->multicompany->enabled)) return 0; + + if (is_array($parameters) && ! empty($parameters)) + { + foreach($parameters as $key=>$value) + { + $$key=$value; + } + } + + $currentcontext = explode(':', $parameters['context']); + + if (! empty($conf->global->MULTICOMPANY_SHARINGS_ENABLED)) + { + // name="massaction" + if (! empty($conf->global->MULTICOMPANY_THIRDPARTY_SHARING_ENABLED) && ! empty($mc->sharings['thirdparty'])) + { + if (in_array('thirdpartylist', $currentcontext) || in_array('contactlist', $currentcontext)) + { + $langs->load('multicompany@multicompany'); + $this->resprints = ''; + } + } + } + + return 0; + } + + /** + * + * @return number + */ + public function printFieldListSelect($parameters=false) + { + global $conf; + global $mc; + + if (empty($conf->multicompany->enabled)) return 0; + + if (is_array($parameters) && ! empty($parameters)) + { + foreach($parameters as $key=>$value) + { + $$key=$value; + } + } + + $currentcontext = explode(':', $parameters['context']); + + if (! empty($conf->global->MULTICOMPANY_SHARINGS_ENABLED)) + { + // Thirdparty sharing is mandatory to share document (propal, etc...) + if (! empty($conf->global->MULTICOMPANY_THIRDPARTY_SHARING_ENABLED) && ! empty($mc->sharings['thirdparty'])) + { + if (in_array('thirdpartylist', $currentcontext)) + { + //if (! empty($arrayfields['s.entity']['checked'])) + { + $this->resprints = ", s.entity"; + } + } + else if (in_array('contactlist', $currentcontext)) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $this->resprints = ", p.entity"; + } + } + else if (in_array('propallist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_PROPOSAL_SHARING_ENABLED) && ! empty($mc->sharings['proposal'])) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $this->resprints = ", p.entity"; + } + } + else if (in_array('orderlist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_ORDER_SHARING_ENABLED) && ! empty($mc->sharings['order'])) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $this->resprints = ", c.entity"; + } + } + else if (in_array('invoicelist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_INVOICE_SHARING_ENABLED) && ! empty($mc->sharings['invoice'])) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $this->resprints = ", f.entity"; + } + } + } + + if (in_array('productservicelist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_PRODUCT_SHARING_ENABLED) && ! empty($mc->sharings['product'])) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $this->resprints = ", p.entity"; + } + } + } + + return 0; + } + + /** + * + * @param boolean $parameters + * @return number + */ + public function printFieldListWhere($parameters=false) + { + global $conf; + global $mc; + + if (empty($conf->multicompany->enabled)) return 0; + + if (is_array($parameters) && ! empty($parameters)) + { + foreach($parameters as $key=>$value) + { + $$key=$value; + } + } + + $currentcontext = explode(':', $parameters['context']); + + if (! empty($conf->global->MULTICOMPANY_SHARINGS_ENABLED)) + { + if (! empty($conf->global->MULTICOMPANY_THIRDPARTY_SHARING_ENABLED) && ! empty($mc->sharings['thirdparty'])) + { + if (in_array('thirdpartylist', $currentcontext)) + { + //if (! empty($arrayfields['s.entity']['checked'])) + { + $search_entity = GETPOST('search_entity','int'); + + if (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha')) // All tests are required to be compatible with all browsers + { + $search_entity = ''; + } + + if ($search_entity > 0) + { + $this->resprints = " AND s.entity = " . $search_entity; + } + } + } + else if (in_array('contactlist', $currentcontext)) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $search_entity = GETPOST('search_entity','int'); + + if (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha')) // All tests are required to be compatible with all browsers + { + $search_entity = ''; + } + + if ($search_entity > 0) + { + $this->resprints = " AND p.entity = " . $search_entity; + } + } + } + else if (in_array('propallist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_PROPOSAL_SHARING_ENABLED) && ! empty($mc->sharings['proposal'])) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $search_entity = GETPOST('search_entity','int'); + + if (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha')) // All tests are required to be compatible with all browsers + { + $search_entity = ''; + } + + if ($search_entity > 0) + { + $this->resprints = " AND p.entity = " . $search_entity; + } + } + } + else if (in_array('orderlist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_ORDER_SHARING_ENABLED) && ! empty($mc->sharings['order'])) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $search_entity = GETPOST('search_entity','int'); + + if (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha')) // All tests are required to be compatible with all browsers + { + $search_entity = ''; + } + + if ($search_entity > 0) + { + $this->resprints = " AND c.entity = " . $search_entity; + } + } + } + else if (in_array('invoicelist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_INVOICE_SHARING_ENABLED) && ! empty($mc->sharings['invoice'])) + { + //if (! empty($arrayfields['f.entity']['checked'])) + { + $search_entity = GETPOST('search_entity','int'); + + if (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha')) // All tests are required to be compatible with all browsers + { + $search_entity = ''; + } + + if ($search_entity > 0) + { + $this->resprints = " AND f.entity = " . $search_entity; + } + } + } + } + + if (in_array('productservicelist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_PRODUCT_SHARING_ENABLED) && ! empty($mc->sharings['product'])) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $search_entity = GETPOST('search_entity','int'); + + if (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha')) // All tests are required to be compatible with all browsers + { + $search_entity = ''; + } + + if ($search_entity > 0) + { + $this->resprints = " AND p.entity = " . $search_entity; + } + } + } + if (in_array('stocklist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_STOCK_SHARING_ENABLED) && ! empty($mc->sharings['stock'])) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $search_entity = GETPOST('search_entity','int'); + + if (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha')) // All tests are required to be compatible with all browsers + { + $search_entity = ''; + } + + if ($search_entity > 0) + { + $this->resprints = " AND t.entity = " . $search_entity; + } + } + } + } + + return 0; + } + + /** + * + * @param boolean $parameters + * @return number + */ + public function printFieldListOption($parameters=false) + { + global $conf; + global $mc; + + if (empty($conf->multicompany->enabled)) return 0; + + if (is_array($parameters) && ! empty($parameters)) + { + foreach($parameters as $key=>$value) + { + $$key=$value; + } + } + + $currentcontext = explode(':', $parameters['context']); + + if (! empty($conf->global->MULTICOMPANY_SHARINGS_ENABLED)) + { + if (! empty($conf->global->MULTICOMPANY_THIRDPARTY_SHARING_ENABLED) && ! empty($mc->sharings['thirdparty'])) + { + if (in_array('thirdpartylist', $currentcontext) || in_array('contactlist', $currentcontext)) + { + //if (! empty($arrayfields['s.entity']['checked']) || ! empty($arrayfields['p.entity']['checked'])) + { + $search_entity = GETPOST('search_entity','int'); + + if (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha')) // All tests are required to be compatible with all browsers + { + $search_entity = ''; + } + + // Entity + $this->resprints = ''; + $this->resprints.= $this->select_entities($search_entity,'search_entity','',false,false,true,explode(",", $mc->entities['thirdparty']),'','minwidth100imp'); + $this->resprints.= ''; + } + } + else if (in_array('propallist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_PROPOSAL_SHARING_ENABLED) && ! empty($mc->sharings['proposal'])) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $search_entity = GETPOST('search_entity','int'); + + if (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha')) // All tests are required to be compatible with all browsers + { + $search_entity = ''; + } + + // Entity + $this->resprints = ''; + $this->resprints.= $this->select_entities($search_entity,'search_entity','',false,false,true,explode(",", $mc->entities['proposal']),'','minwidth100imp'); + $this->resprints.= ''; + } + } + else if (in_array('orderlist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_ORDER_SHARING_ENABLED) && ! empty($mc->sharings['order'])) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $search_entity = GETPOST('search_entity','int'); + + if (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha')) // All tests are required to be compatible with all browsers + { + $search_entity = ''; + } + + // Entity + $this->resprints = ''; + $this->resprints.= $this->select_entities($search_entity,'search_entity','',false,false,true,explode(",", $mc->entities['order']),'','minwidth100imp'); + $this->resprints.= ''; + } + } + else if (in_array('invoicelist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_INVOICE_SHARING_ENABLED) && ! empty($mc->sharings['invoice'])) + { + //if (! empty($arrayfields['f.entity']['checked'])) + { + $search_entity = GETPOST('search_entity','int'); + + if (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha')) // All tests are required to be compatible with all browsers + { + $search_entity = ''; + } + + // Entity + $this->resprints = ''; + $this->resprints.= $this->select_entities($search_entity,'search_entity','',false,false,true,explode(",", $mc->entities['invoice']),'','minwidth100imp'); + $this->resprints.= ''; + } + } + } + + if (in_array('productservicelist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_PRODUCT_SHARING_ENABLED) && ! empty($mc->sharings['product'])) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $search_entity = GETPOST('search_entity','int'); + + if (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha')) // All tests are required to be compatible with all browsers + { + $search_entity = ''; + } + + // Entity + $this->resprints = ''; + $this->resprints.= $this->select_entities($search_entity,'search_entity','',false,false,true,explode(",", $mc->entities['product']),'','minwidth100imp'); + $this->resprints.= ''; + } + } + if (in_array('stocklist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_STOCK_SHARING_ENABLED) && ! empty($mc->sharings['stock'])) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $search_entity = GETPOST('search_entity','int'); + + if (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha')) // All tests are required to be compatible with all browsers + { + $search_entity = ''; + } + + // Entity + $this->resprints = ''; + $this->resprints.= $this->select_entities($search_entity,'search_entity','',false,false,true,explode(",", $mc->entities['stock']),'','minwidth100imp'); + $this->resprints.= ''; + } + } + } + + return 0; + } + + /** + * + * @param boolean $parameters + * @return number + */ + public function printFieldListTitle($parameters=false) + { + global $conf; + global $mc; + + if (empty($conf->multicompany->enabled)) return 0; + + if (is_array($parameters) && ! empty($parameters)) + { + foreach($parameters as $key=>$value) + { + $$key=$value; + } + } + + $currentcontext = explode(':', $parameters['context']); + + if (! empty($conf->global->MULTICOMPANY_SHARINGS_ENABLED)) + { + if (! empty($conf->global->MULTICOMPANY_THIRDPARTY_SHARING_ENABLED) && ! empty($mc->sharings['thirdparty'])) + { + if (in_array('thirdpartylist', $currentcontext)) + { + //if (! empty($arrayfields['s.entity']['checked'])) + { + $this->resprints = getTitleFieldOfList('Entity',0,$_SERVER["PHP_SELF"],"s.entity","",$param,'align="center"',$sortfield,$sortorder); + } + } + else if (in_array('contactlist', $currentcontext)) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $this->resprints = getTitleFieldOfList('Entity',0,$_SERVER["PHP_SELF"],"p.entity","",$param,'align="center"',$sortfield,$sortorder); + } + } + else if (in_array('propallist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_PROPOSAL_SHARING_ENABLED) && ! empty($mc->sharings['proposal'])) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $this->resprints = getTitleFieldOfList('Entity',0,$_SERVER["PHP_SELF"],"p.entity","",$param,'align="center"',$sortfield,$sortorder); + } + } + else if (in_array('orderlist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_ORDER_SHARING_ENABLED) && ! empty($mc->sharings['order'])) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $this->resprints = getTitleFieldOfList('Entity',0,$_SERVER["PHP_SELF"],"c.entity","",$param,'align="center"',$sortfield,$sortorder); + } + } + else if (in_array('invoicelist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_INVOICE_SHARING_ENABLED) && ! empty($mc->sharings['invoice'])) + { + //if (! empty($arrayfields['f.entity']['checked'])) + { + $this->resprints = getTitleFieldOfList('Entity',0,$_SERVER["PHP_SELF"],"f.entity","",$param,'align="center"',$sortfield,$sortorder); + } + } + } + + if (in_array('productservicelist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_PRODUCT_SHARING_ENABLED) && ! empty($mc->sharings['product'])) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $this->resprints = getTitleFieldOfList('Entity',0,$_SERVER["PHP_SELF"],"p.entity","",$param,'align="center"',$sortfield,$sortorder); + } + } + + if (in_array('stocklist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_STOCK_SHARING_ENABLED) && ! empty($mc->sharings['stock'])) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $this->resprints = getTitleFieldOfList('Entity',0,$_SERVER["PHP_SELF"],"t.entity","",$param,'align="center"',$sortfield,$sortorder); + } + } + } + + return 0; + } + + /** + * + * @param boolean $parameters + * @return number + */ + public function printFieldListValue($parameters=false) + { + global $conf; + global $totalarray; + global $mc; + + if (empty($conf->multicompany->enabled)) return 0; + + if (is_array($parameters) && ! empty($parameters)) + { + foreach($parameters as $key=>$value) + { + $$key=$value; + } + } + + $currentcontext = explode(':', $parameters['context']); + + if (! empty($conf->global->MULTICOMPANY_SHARINGS_ENABLED)) + { + if (! empty($conf->global->MULTICOMPANY_THIRDPARTY_SHARING_ENABLED) && ! empty($mc->sharings['thirdparty'])) + { + if (in_array('thirdpartylist', $currentcontext) || in_array('contactlist', $currentcontext)) + { + //if (! empty($arrayfields['s.entity']['checked']) || ! empty($arrayfields['p.entity']['checked'])) + { + $this->getInfo($obj->entity); + $this->resprints = ''.$this->label."\n"; + } + } + else if (in_array('propallist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_PROPOSAL_SHARING_ENABLED) && ! empty($mc->sharings['proposal'])) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $this->getInfo($obj->entity); + $this->resprints = ''.$this->label."\n"; + if (! $i) $totalarray['nbfield']++; + } + } + else if (in_array('orderlist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_ORDER_SHARING_ENABLED) && ! empty($mc->sharings['order'])) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $this->getInfo($obj->entity); + $this->resprints = ''.$this->label."\n"; + if (! $i) $totalarray['nbfield']++; + } + } + else if (in_array('invoicelist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_INVOICE_SHARING_ENABLED) && ! empty($mc->sharings['invoice'])) + { + //if (! empty($arrayfields['f.entity']['checked'])) + { + $this->getInfo($obj->entity); + $this->resprints = ''.$this->label."\n"; + if (! $i) $totalarray['nbfield']++; + } + } + } + + if (in_array('productservicelist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_PRODUCT_SHARING_ENABLED) && ! empty($mc->sharings['product'])) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $this->getInfo($obj->entity); + $this->resprints = ''.$this->label."\n"; + } + } + + if (in_array('stocklist', $currentcontext) && ! empty($conf->global->MULTICOMPANY_STOCK_SHARING_ENABLED) && ! empty($mc->sharings['stock'])) + { + //if (! empty($arrayfields['p.entity']['checked'])) + { + $this->getInfo($obj->entity); + $this->resprints = ''.$this->label."\n"; + } + } + } + + return 0; + } + + /** + * + */ + public function insertExtraHeader($parameters=false, &$object, &$action='') + { + global $conf, $user, $langs; + + if (empty($conf->multicompany->enabled)) return 0; + + if (is_array($parameters) && ! empty($parameters)) + { + foreach($parameters as $key=>$value) + { + $$key=$value; + } + } + + $currentcontext = explode(':', $parameters['context']); + + if (! empty($user->admin) && empty($user->entity) && $conf->entity == 1 && ! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) + { + if (in_array('userperms', $currentcontext) || in_array('groupperms', $currentcontext)) + { + $this->getInstanceDao(); + + if ($object->element == 'user') + { + $aEntities=array_keys($permsgroupbyentity); + + // Check usergroup if user not in master entity + if (empty($aEntities) || ! array_key_exists(1, $permsgroupbyentity)) + { + require_once DOL_DOCUMENT_ROOT.'/user/class/usergroup.class.php'; + $aEntities=array(); + $group = new UserGroup($this->db); + $ret = $group->listGroupsForUser($object->id, false); + if (! empty($ret)) { + foreach($ret as $groupid => $data) + { + $aEntities = array_merge($aEntities, $data->usergroup_entity); + } + sort($aEntities); + } + } + + if (! empty($aEntities)) + { + $entity = (GETPOST('entity', 'int')?GETPOST('entity', 'int'):$aEntities[0]); + $head = entity_prepare_head($object, $aEntities); + $title = $langs->trans("Entities"); + dol_fiche_head($head, $entity, $title, 1, 'multicompany@multicompany'); + } + else + { + print get_htmloutput_mesg(img_warning('default') . ' ' . $langs->trans("ErrorLinkUserGroupEntity"), '', 'mc-upgrade-alert', 1); + } + } + else if ($object->element == 'usergroup') + { + $this->dao->getEntities(); + $aEntities=array(); + + foreach ($this->dao->entities as $objEntity) + { + $aEntities[] = $objEntity->id; + } + + $entity = (GETPOST('entity', 'int')?GETPOST('entity', 'int'):$aEntities[0]); + $head = entity_prepare_head($object, $aEntities); + $title = $langs->trans("Entities"); + dol_fiche_head($head, $entity, $title, 1, 'multicompany@multicompany'); + + if (! empty($conf->global->MULTICOMPANY_TEMPLATE_MANAGEMENT)) { + print ' +
+

'.img_info().' '.$langs->transnoentities('DuplicateRightsInfo').'

+

'.$langs->transnoentities('SelectRightsOfEntityToDuplicate').' '.$this->select_entities('', 'template', '', false, false, false, false, '', 'minwidth200imp', true, true).'

+

'.$langs->transnoentities('SelectEntitiesToOverride').'

+

+
+
+
'.$langs->transnoentities("EntitiesSelected").'
+ '.$this->multiselectEntitiesToOverride('overrideentities', true).' +
+
+ + + + + + +
+
+
'.$langs->transnoentities("EntitiesAvailable").'
+ '.$this->multiselectEntitiesToOverride('overrideentities', false).' +
+
+

+
+ + '; + } + } + + // Check if advanced perms is enabled for current object entity + $res = $this->dao->getEntityConfig($entity, 'MAIN_USE_ADVANCED_PERMS'); + if (empty($res['MAIN_USE_ADVANCED_PERMS'])) { + unset($conf->global->MAIN_USE_ADVANCED_PERMS); + } + } + } + + return 0; + } + + /** + * + */ + public function insertExtraFooter($parameters=false, &$object, &$action='') + { + global $conf, $user; + + if (empty($conf->multicompany->enabled)) return 0; + + if (is_array($parameters) && ! empty($parameters)) + { + foreach($parameters as $key=>$value) + { + $$key=$value; + } + } + + $currentcontext = explode(':', $parameters['context']); + + if (! empty($user->admin) && empty($user->entity) && $conf->entity == 1 && ! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) + { + if (in_array('userperms', $currentcontext) || in_array('groupperms', $currentcontext)) + { + // Restore advanced perms if enabled for current entity + $this->getInstanceDao(); + $res = $this->dao->getEntityConfig($conf->entity, 'MAIN_USE_ADVANCED_PERMS'); + if (! empty($res['MAIN_USE_ADVANCED_PERMS'])) { + $conf->global->MAIN_USE_ADVANCED_PERMS = $res['MAIN_USE_ADVANCED_PERMS']; + } + } + } + + return 0; + } + + /** + * Return combo list of entities. + * + * @param int $selected Preselected entity + * @param int $htmlname Name + * @param string $option Option + * @param boolean $login If use in login page or not + * @param boolean $exclude Exclude + * @param boolean $emptyvalue Emptyvalue + * @param boolean $only Only + * @param string $all Add 'All entities' value in combo list + * @param string $cssclass specific css class. eg 'minwidth150imp mycssclass' + * @param bool $ajax Enable ajax combobox + * @param bool $template Show template of entities + * @return string + */ + public function select_entities($selected = '', $htmlname = 'entity', $option = '', $login = false, $exclude = false, $emptyvalue = false, $only = false, $all = '', $cssclass = 'minwidth150imp', $ajax = true, $template = false) + { + global $conf, $user, $langs; + + $this->getInstanceDao(); + + $this->dao->getEntities($login, $exclude); + + $out = ''; + + if (is_array($this->dao->entities) && ! empty($this->dao->entities)) + { + $out.= ''; + + // Make select dynamic + if ($ajax) { + include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php'; + $out.= ajax_combobox($htmlname); + } + } + + return $out; + } + + /** + * Return multiselect list of entities. + * + * @param string $htmlname Name of select + * @param DaoMulticompany $current Current entity to manage + * @param bool $onlyselected true: show only selected, false: hide only selected + * @return string + */ + public function multiselect_entities($htmlname, $current, $onlyselected=false) + { + global $langs; + + $this->getInstanceDao(); + $this->dao->getEntities(); + + $selectname = ($onlyselected ? $htmlname.'_to[]' : 'from[]'); + $selectid = ($onlyselected ? 'multiselect_shared_'.$htmlname.'_to' : 'multiselect_shared_'.$htmlname); + + $return = ''; + + return $return; + } + + /** + * Return multiselect list of entities to override. + * + * @param string $htmlname Name of select + * @param bool $onlyselected true: show only selected, false: hide only selected + * @return string + */ + public function multiselectEntitiesToOverride($htmlname, $onlyselected=false) + { + global $langs; + + $this->getInstanceDao(); + $this->dao->getEntities(); + + $selectname = ($onlyselected ? $htmlname.'_to[]' : 'from[]'); + $selectid = ($onlyselected ? 'multiselect_'.$htmlname.'_to' : 'multiselect_'.$htmlname); + + $out = ''; + + return $out; + } + + /** + * Return multiselect list of entities. + * + * @param string $htmlname Name of select + * @param array $selected Entities already selected + * @param string $option Option + * @return string + */ + public function multiSelectEntities($htmlname, $selected=null, $option=null) + { + global $langs; + + $this->getInstanceDao(); + $this->dao->getEntities(); + + $return = ''; + + return $return; + } + + /** + * Switch to another entity. + * + * @param int $id User id + * @param int $entity Entity id + * @return int + */ + public function checkRight($id, $entity) + { + global $user; + + $this->getInstanceDao(); + + if ($this->dao->fetch($entity) > 0) + { + // Controle des droits sur le changement + if ($this->dao->verifyRight($entity, $id) || $user->admin) + { + return 1; + } + else + { + return -2; + } + } + else + { + return -1; + } + } + + /** + * Switch to another entity. + * @param int $id Id of the destination entity + * @param int $userid + * @return int + */ + public function switchEntity($id, $userid=null) + { + global $conf, $user; + + $this->getInstanceDao(); + + if (!empty($userid)) + { + $user=new User($this->db); + $user->fetch($userid); + } + + if ($this->dao->fetch($id) > 0 && ! empty($this->dao->active)) // check if the entity is still active + { + // Controle des droits sur le changement + if (!empty($conf->global->MULTICOMPANY_HIDE_LOGIN_COMBOBOX) + || (!empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE) && $this->dao->verifyRight($id, $user->id)) + || $user->admin) + { + $_SESSION['dol_entity'] = $id; + //$conf = new Conf(); FIXME some constants disappear + $conf->entity = $id; + $conf->setValues($this->db); + return 1; + } + else + { + //var_dump($conf->global->MULTICOMPANY_HIDE_LOGIN_COMBOBOX); + //var_dump($conf->global->MULTICOMPANY_TRANSVERSE_MODE); + //var_dump($this->dao->verifyRight($id, $user->id)); + return -2; + } + } + else + { + return -1; + } + } + + /** + * Get entity info + * @param int $id Object id + */ + public function getInfo($id) + { + $this->getInstanceDao(); + $this->dao->fetch($id); + + $this->id = $this->dao->id; + $this->label = $this->dao->label; + $this->country_id = $this->dao->country_id; + $this->country_code = $this->dao->country_code; + $this->currency_code = $this->dao->currency_code; + $this->language_code = $this->dao->language_code; + $this->description = $this->dao->description; + $this->options = $this->dao->options; + $this->active = $this->dao->active; + $this->visible = $this->dao->visible; + } + + /** + * Get action title + * @param string $action Type of action + * @return string + */ + public function getTitle($action='') + { + global $langs; + + if ($action == 'create') return $langs->trans("AddEntity"); + else if ($action == 'edit') return $langs->trans("EditEntity"); + else return $langs->trans("EntitiesManagement"); + } + + + /** + * Assigne les valeurs pour les templates + * @param string $action Type of action + */ + public function assign_values($action='view') + { + global $conf, $langs, $user; + global $form, $formcompany, $formadmin; + + require_once DOL_DOCUMENT_ROOT . '/core/class/extrafields.class.php'; + + $this->tpl['extrafields'] = new ExtraFields($this->db); + // fetch optionals attributes and labels + $this->tpl['extralabels'] = $this->tpl['extrafields']->fetch_name_optionals_label('entity'); + + $this->getInstanceDao(); + + $this->template_dir = dol_buildpath('/multicompany/admin/tpl/'); + $this->template = 'list.tpl.php'; + + if ($action == 'create' || $action == 'edit') + { + $this->template = 'card.tpl.php'; + + if ($action == 'edit' && GETPOSTISSET('id')) { + $ret = $this->dao->fetch(GETPOST('id', 'int')); + } + + if (! empty($conf->global->MULTICOMPANY_TEMPLATE_MANAGEMENT)) + { + $templatevalue = (GETPOSTISSET('template') ? GETPOST('template', 'int') : ($this->dao->visible === '2' ? 1 : 0)); + + if ($action == 'create') { + $this->tpl['template'] = $form->selectyesno('template', $templatevalue, 1); + $this->tpl['select_template'] = $this->select_entities('','usetemplate','',false,false,true,'','','minwidth200imp',true,'only'); + } elseif ($templatevalue === 1) { + $this->tpl['template'] = $templatevalue; + } + } + + // action + $this->tpl['action'] = $action; + + // id + $this->tpl['id'] = (GETPOSTISSET('id')?GETPOST('id', 'int'):null); + + // Label + $this->tpl['label'] = (GETPOSTISSET('label')?GETPOST('label', 'alpha'):$this->dao->label); + + // Description + $this->tpl['description'] = (GETPOSTISSET('description')?GETPOST('description', 'alpha'):$this->dao->description); + + // Company name + $this->tpl['name'] = (GETPOSTISSET('name')?GETPOST('name', 'alpha'):$this->dao->name); + + // Address + $this->tpl['address'] = (GETPOSTISSET('address')?GETPOST('address', 'alpha'):$this->dao->address); + + // Zip + $this->tpl['select_zip'] = $formcompany->select_ziptown((GETPOSTISSET('zipcode')?GETPOST('zipcode', 'alpha'):$this->dao->zip),'zipcode',array('town','selectcountry_id','departement_id'),6); + + // Town + $this->tpl['select_town'] = $formcompany->select_ziptown((GETPOSTISSET('town')?GETPOST('town', 'alpha'):$this->dao->town),'town',array('zipcode','selectcountry_id','departement_id'),40); + + if ($user->admin) $this->tpl['info_admin'] = info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1); + + + // We define country_id + if (GETPOSTISSET('country_id')) + { + $country_id = GETPOST('country_id', 'int'); + } + else if (! empty($this->dao->country_id)) + { + $country_id = $this->dao->country_id; + } + else if (! empty($conf->global->MAIN_INFO_SOCIETE_COUNTRY)) + { + $tmp = explode(':', $conf->global->MAIN_INFO_SOCIETE_COUNTRY); + $country_id = $tmp[0]; + } + else + { + $country_id = 0; + } + + $this->tpl['select_country'] = $form->select_country($country_id,'country_id'); + $this->tpl['select_state'] = $formcompany->select_state((GETPOSTISSET('departement_id')?GETPOST('departement_id', 'int'):$this->dao->state_id),$country_id,'departement_id'); + $this->tpl['select_currency'] = $form->selectCurrency((GETPOSTISSET('currency_code')?GETPOST('currency_code', 'alpha'):($this->dao->currency_code?$this->dao->currency_code:$conf->currency)),"currency_code"); + $this->tpl['select_language'] = $formadmin->select_language((GETPOSTISSET('main_lang_default')?GETPOST('main_lang_default', 'alpha'):($this->dao->language_code?$this->dao->language_code:$conf->global->MAIN_LANG_DEFAULT)),'main_lang_default',1); + + if (! empty($conf->global->MULTICOMPANY_SHARINGS_ENABLED)) { + foreach ($this->sharingelements as $element => $params) { + if ((($params['object'] || $params['objectnumber']) && ! isset($params['disable'])) && (empty($conf->societe->enabled) || empty($conf->global->MULTICOMPANY_THIRDPARTY_SHARING_ENABLED))) continue; + $uppername = strtoupper($element); + $constname = 'MULTICOMPANY_' . $uppername . '_SHARING_ENABLED'; + if (! empty($conf->global->$constname)) { + $this->tpl['multiselect_from_' . $element] = $this->multiselect_entities($element, $this->dao, false); + $this->tpl['multiselect_to_' . $element] = $this->multiselect_entities($element, $this->dao, true); + if ($element == 'proposalnumber' || $element == 'invoicenumber') { + $this->tpl['select_'.$element.'_entity'] = $this->select_entities($this->dao->options[$element.'_referent'], $element.'_referring_entity'); + } + $addtoallother = (GETPOSTISSET('addtoallother_' . $element) ? GETPOST('addtoallother_' . $element, 'int') : $this->dao->options['addtoallother'][$element]); + $this->tpl['addtoallother_' . $element] = $form->selectyesno('addtoallother_' . $element, $addtoallother, 1); + } + } + } + } + } + + /** + * Display the template + */ + public function display() + { + global $conf, $langs; + global $form, $object; + + include $this->template_dir.$this->template; + } + + /** + * Set values of global conf for multicompany + * + * @param Conf $conf Object conf + * @return void + */ + public function setValues(&$conf) + { + if (! empty($conf->global->MULTICOMPANY_SHARINGS_ENABLED)) + { + $this->getInstanceDao(); + $this->dao->fetch($conf->entity); + + $this->sharings = $this->dao->options['sharings']; + //$this->referent = $this->dao->options['referent']; + $this->proposalnumber_referent = (isset($this->dao->options['proposalnumber_referent'])?$this->dao->options['proposalnumber_referent']:''); + $this->invoicenumber_referent = (isset($this->dao->options['invoicenumber_referent'])?$this->dao->options['invoicenumber_referent']:''); + + // Load shared elements + $this->loadSharedElements(); + + // Define output dir for others entities + $this->setMultiOutputDir($conf); + } + + if (! empty($this->sharingdicts)) + { + foreach($this->sharingdicts as $dict => $data) + { + $constname = 'MULTICOMPANY_'.strtoupper($dict).'_SHARING_DISABLED'; + if (! empty($conf->global->$constname)) { + $this->dict[$dict] = true; + } + } + } + } + + /** + * Set status of an entity + * + * @param int $id Id of entity + * @param string $type Type of status (visible or active) + * @param string $value Value of status (0: disable, 1: enable) + * @return int + */ + public function setStatus($id, $type='active', $value) + { + global $user; + + if (! empty($user->admin) && ! $user->entity) { + $this->getInstanceDao(); + return $this->dao->setEntity($id, $type, $value); + } + else { + return -1; + } + } + + /** + * Delete an entity + * + * @param int $id Id of entity + * @return int + */ + public function deleteEntity($id) + { + global $user; + + if (! empty($user->admin) && ! $user->entity && $id != 1) { + $this->getInstanceDao(); + return $this->dao->delete($id); + } + else { + return -1; + } + } + + /** + * Get list of entity id to use. + * + * @param string $element Current element + * 'societe', 'socpeople', 'actioncomm', 'agenda', 'resource', + * 'product', 'productprice', 'stock', + * 'propal', 'supplier_proposal', 'invoice', 'facture_fourn', 'payment_various', + * 'categorie', 'bank_account', 'bank_account', 'adherent', 'user', + * 'commande', 'commande_fournisseur', 'expedition', 'intervention', 'survey', + * 'contract', 'tax', 'expensereport', 'holiday', 'multicurrency', 'project', + * 'email_template', 'event', 'donation' + * 'c_paiement', 'c_payment_term', ... + * @param int $shared 0=Return id of current entity only, + * 1=Return id of current entity + shared entities (default) + * @param object $currentobject Current object if needed + * @return mixed Entity id(s) to use ( eg. entity IN ('.getEntity(elementname).')' ) + */ + public function getEntity($element=false, $shared=1, $currentobject=null) + { + global $conf, $user; + + $element = str_replace(MAIN_DB_PREFIX, '', $element); + + if (in_array($element, $this->addzero)) + { + if ($element == 'user' && ! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) { + return '0,1'; // In transverse mode all users except superadmin and groups are in entity 1 + } else { + if ($element == 'usergroup' && $conf->entity == 1 && empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE) && !empty($user->admin) && empty($user->entity)) + { + return '0,'.implode(',', array_keys($this->getEntitiesList(true, false, true))); // Superadmin can always edit groups of another entities + } + + return '0,'.$conf->entity; + } + } + + // Sharing dictionnaries + if (array_key_exists($element, $this->sharingdicts)) + { + if (! empty($this->dict[$element])) { + return $conf->entity; + } else { + return 1; // Master entity + } + } + + // Check object entity when number sharing is disabled + if (is_object($currentobject) && + (($element == 'proposalnumber' && empty($conf->global->MULTICOMPANY_PROPOSALNUMBER_SHARING_ENABLED)) + || ($element == 'ordernumber' && empty($conf->global->MULTICOMPANY_ORDERNUMBER_SHARING_ENABLED)) + || ($element == 'invoicenumber' && empty($conf->global->MULTICOMPANY_INVOICENUMBER_SHARING_ENABLED)) + ) + ) + { + // Use object entity ID + $entity = ((isset($currentobject->entity) && is_numeric($currentobject->entity)) ? $currentobject->entity : $conf->entity); + return $entity; + } + + $elementkey = $element; + if ($element == 'societe' || $element == 'socpeople' || $element == 'contact') { + $elementkey = 'thirdparty'; + } + if ($element == 'adherent') $elementkey = 'member'; + if ($element == 'bank_account') $elementkey = 'bankaccount'; + if ($element == 'adherent_type') $elementkey = 'member_type'; + if ($element == 'categorie') $elementkey = 'category'; + if ($element == 'propal') $elementkey = 'proposal'; + if ($element == 'commande') $elementkey = 'order'; + if ($element == 'facture') $elementkey = 'invoice'; + + if (! empty($element) && ! empty($this->entities[$elementkey])) + { + if (! empty($shared)) + { + return $this->entities[$elementkey]; + } + else if (! empty($this->sharings['referent'])) + { + if ($element == 'societe') return $this->sharings['referent']; + } + } + + return $conf->entity; + } + + /** + * Set entity id to use when to create an object + * + * @param object $currentobject Current object + * @return int Entity id to use + */ + public function setEntity($currentobject) + { + global $conf; + + $entity = $conf->entity; + + if (is_object($currentobject) && ! empty($currentobject->element)) + { + $element = array_search($currentobject->element, $this->sharingmodulename); + $element = (! empty($element) ? $element : $currentobject->element); + $constname = 'MULTICOMPANY_'.strtoupper($element).'_SHARING_ENABLED'; + $newentity = $entity; + + if (isset($this->sharingelements[$element]) + && isset($this->sharingelements[$element]['active']) + && ! empty($conf->global->$constname) + ) + { + if (GETPOSTISSET('entity') && GETPOST('entity', 'int', 2)) + { + $newentity = GETPOST('entity', 'int', 2); + } + else if (isset($currentobject->entity) && is_numeric($currentobject->entity)) + { + $newentity = $currentobject->entity; + } + + if (isset($this->sharings[$element]) && in_array($newentity, $this->sharings[$element])) + { + $entity = $newentity; + } + } + else + { + $entity = (($currentobject->id > 0 && $currentobject->entity > 0) ? $currentobject->entity : $conf->entity); + } + } + + return $entity; + } + + /** + * Get entities list + * + * @param int $login If use in login page or not + * @param array $exclude Entity ids to exclude + * @param bool $onlyactive sort only active entities + * @param bool $showtemplate Show or not templates + * @return array Array of entities (id => label) + */ + public function getEntitiesList($login = false, $exclude = false, $onlyactive = false, $showtemplate = false) + { + global $langs; + + $this->getInstanceDao(); + $this->dao->getEntities($login, $exclude, $onlyactive); + + $entities=array(); + + foreach ($this->dao->entities as $entity) + { + if (empty($showtemplate) && $entity->visible == 2) continue; + $entities[$entity->id] = dol_html_entity_decode($entity->label, null) . (empty($entity->active) ? ' ('.$langs->transnoentities('Disabled').')' : ($entity->visible == 2 ? ' ('.$langs->transnoentities('Template').')' : (empty($entity->visible) ? ' ('.$langs->transnoentities('Hidden').')' : '')) ); + } + + return $entities; + } + + /** + * Set object documents directory to use + * + * @param Conf $conf Object Conf + * @return void + */ + public function setMultiOutputDir(&$conf) + { + if (! empty($this->entities)) + { + foreach($this->entities as $element => $shares) + { + if ($element == 'thirdparty') $element = 'societe'; + elseif ($element == 'member') $element = 'adherent'; + elseif ($element == 'proposal') $element = 'propal'; + elseif ($element == 'order') $element = 'commande'; + elseif ($element == 'invoice') $element = 'facture'; + elseif ($element == 'intervention') $element = 'ficheinter'; + + if (! empty($conf->$element->enabled) && isset($conf->$element->multidir_output) && isset($conf->$element->multidir_temp)) + { + $elementpath=$element; + if ($element == 'product') $elementpath='produit'; + elseif ($element == 'category') $elementpath='categorie'; + elseif ($element == 'propal') $elementpath='propale'; + + $entities = explode(",", $shares); + $dir_output = array(); + $dir_temp = array(); + foreach($entities as $entity) + { + if (! array_key_exists($entity, $conf->$element->multidir_output)) + { + $path = ($entity > 1 ? "/".$entity : ''); + + $dir_output[$entity] = DOL_DATA_ROOT.$path."/".$elementpath; + $dir_temp[$entity] = DOL_DATA_ROOT.$path."/".$elementpath."/temp"; + + $conf->$element->multidir_output += $dir_output; + $conf->$element->multidir_temp += $dir_temp; + } + + if (in_array($element, array('propal', 'commande', 'facture')) && isset($conf->mycompany->multidir_output)) + { + if (! array_key_exists($entity, $conf->mycompany->multidir_output)) + { + $path = ($entity > 1 ? "/".$entity : ''); + + $dir_output[$entity] = DOL_DATA_ROOT.$path."/mycompany"; + $dir_temp[$entity] = DOL_DATA_ROOT.$path."/mycompany/temp"; + + $conf->mycompany->multidir_output += $dir_output; + $conf->mycompany->multidir_temp += $dir_temp; + } + } + } + } + } + } + } + + /** + * @param bool $parameters + * @return int + */ + public function printTopRightMenu($parameters=false) + { + echo $this->getTopRightMenu(); + + return 0; + } + + /** + * + */ + public function printBugtrackInfo($parameters=false) + { + global $conf; + + if (! empty($conf->multicompany->enabled)) { + $this->resprints = urlencode("- **Multicompany**: " . $conf->global->MULTICOMPANY_MAIN_VERSION . "\n"); + } + + return 0; + } + + /** + * @param bool $parameters + * @return int + */ + /*public function afterLogin($parameters=false) + { + global $conf; + + return 0; + }*/ + + /** + * @param bool $parameters + * @return int + */ + public function updateSession($parameters=false) + { + global $conf; + + // Switch to another entity + if (! empty($conf->multicompany->enabled) && GETPOST('action','aZ') == 'switchentity') + { + if ($this->switchEntity(GETPOST('entity','int')) > 0) + { + header("Location: ".DOL_URL_ROOT.'/'); + exit; + } + } + + return 0; + } + + /** + * + */ + public function getLoginPageOptions($parameters=false) + { + global $conf, $langs; + + if (is_array($parameters) && ! empty($parameters)) + { + foreach($parameters as $key => $value) + { + $$key=$value; + } + } + + // Entity combobox + if (empty($conf->global->MULTICOMPANY_HIDE_LOGIN_COMBOBOX)) + { + if (empty($entity)) $entity=1; + $lastentity=(! empty($conf->global->MULTICOMPANY_FORCE_ENTITY)?$conf->global->MULTICOMPANY_FORCE_ENTITY:$entity); + $currentcontext = explode(':', $parameters['context']); + + if (in_array('cashdeskloginpage', $currentcontext)) + { + $select_entity = $this->select_entities($lastentity, 'entity', ' tabindex="3"', true, false, false, false, '', 'minwidth100imp'); + + $tableformat = ''; + $tableformat.= ''.$langs->trans("Entity").''; + $tableformat.= ''.$select_entity.''; + $tableformat.= ''; + + $this->resprints = $tableformat; + } + else + { + $select_entity = $this->select_entities($lastentity, 'entity', ' tabindex="3"', true, false, false, false, '', 'login-entity minwidth180'); + + $divformat = "\n".'
'."\n"; + $divformat.= '
'."\n"; + $divformat.= ''.$select_entity.''."\n"; + $divformat.= '
'; + + if (! empty($conf->global->MULTICOMPANY_LOGIN_LOGO_BY_ENTITY)) { + $divformat.= ' + '; + } + + $this->resprints = $divformat; + } + } + + return 0; + } + + /** + * + */ + public function getPasswordForgottenPageOptions($parameters=false) + { + return $this->getLoginPageOptions($parameters); + } + + /** + * Add all entities default dictionnaries in database + */ + public function addAllEntitiesDefaultDicts() + { + if (! empty($this->sharingdicts)) + { + $this->getInstanceDao(); + $this->dao->getEntities(); + + $dir = "/multicompany/sql/dict/"; + + foreach($this->sharingdicts as $dict => $data) + { + // Load sql init_new_entity_dict.sql file + $file = 'init_new_entity_'.$dict.'.sql'; + $fullpath = dol_buildpath($dir.$file); + + if (file_exists($fullpath)) + { + foreach ($this->dao->entities as $entity) + { + if ($entity->id == 1) continue; + + $result=run_sql($fullpath,1,$entity->id); + } + } + } + } + } + + /** + * Load shared elements + * + * @return void + */ + private function loadSharedElements() + { + global $conf; + + if (! empty($this->sharings)) + { + $this->getInstanceDao(); + + foreach($this->sharings as $element => $ids) + { + $modulesharingenabled = 'MULTICOMPANY_'.strtoupper($element).'_SHARING_ENABLED'; + + $module = ((isset($this->sharingmodulename[$element]) && !empty($this->sharingmodulename[$element])) ? $this->sharingmodulename[$element] : $element); + + if (! empty($conf->$module->enabled) && ! empty($conf->global->$modulesharingenabled)) + { + $entities=array(); + + if (! empty($this->referent)) + { + // Load configuration of referent entity + $this->config = $this->dao->getEntityConfig($this->referent); + $this->setConstant($conf, $element); + } + + if (! empty($ids)) + { + foreach ($ids as $id) + { + $ret=$this->dao->fetch($id); + if ($ret > 0 && $this->dao->active) + { + $entities[] = $id; + } + } + + $this->entities[$element] = (! empty($entities) ? implode(",", $entities) : 0); + $this->entities[$element].= ','.$conf->entity; + } + } + } + } + //var_dump($this->entities); + } + + /** + * Get modify entity dialog + */ + private function getModifyEntityDialog($htmlname, $action, $object) + { + global $langs; + + $langs->loadLangs(array('errors','multicompany@multicompany')); + + $selectEntities = $this->select_entities('', 'entity' . $htmlname, '', false, array($object->entity)); + + $out = ''; + + if (! empty($selectEntities)) { + + $out.= ''; + + $out.= ' + '; + + $out.= '
'."\n"; + $out.= '

' . img_warning() . ' ' . $langs->trans(ucfirst($htmlname) . 'ModifyEntityDescription') . '

'."\n"; + $out.= '
' . $langs->trans('SelectAnEntity'); + $out.= $selectEntities . '
'."\n"; + $out.= '
'."\n"; + + $out.= ''; + } + + return $out; + } + + /** + * Show entity info + */ + private function getTopRightMenu() + { + global $conf, $user, $langs; + + $langs->loadLangs(array('languages','admin','multicompany@multicompany')); + + $out=''; + + if (! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE) || ! empty($user->admin)) + { + if (($conf->global->MAIN_THEME === 'eldy' && empty($conf->global->MULTICOMPANY_DROPDOWN_MENU_DISABLED) && ! GETPOSTISSET('theme')) || (GETPOSTISSET('theme') && GETPOST('theme', 'aZ', 1) === 'eldy')) + { + $out.= $this->getDropdownMenu(); + } + else + { + $form=new Form($this->db); + + $this->getInfo($conf->entity); + + $selectEntities = $this->select_entities('', 'changeentity', '', false, array($conf->entity), false, false, '', 'minwidth200imp', true, true); + + $text =''; + if (($conf->global->MAIN_THEME === 'eldy' && empty($conf->global->MULTICOMPANY_NO_TOP_MENU_ENTITY_LABEL) && ! GETPOSTISSET('theme')) || (GETPOSTISSET('theme') && GETPOST('theme', 'aZ', 1) === 'eldy')) { + $text.= ''.$this->label.''; + } + $text.= ''; + + if ($cache = getCache('country_' . $this->country_id)) { + $country = $cache; + } else { + $country = getCountry($this->country_id); + setCache('country_' . $this->country_id, $country); + } + $imgCountry=picto_from_langcode($this->country_code, 'class="multicompany-flag-country"'); + $imgLang=picto_from_langcode($this->language_code, 'class="multicompany-flag-language"'); + + $htmltext =''.$langs->trans("Entity").''."\n"; + $htmltext.= '
'; + $htmltext.='
'.$langs->trans("Label").': '.$this->label."\n"; + $htmltext.='
'.$langs->trans("Country").': '. ($imgCountry?$imgCountry.' ':'') . $country."\n"; + $htmltext.='
'.$langs->trans("Currency").': '. currency_name($this->currency_code) . ' (' . $langs->getCurrencySymbol($this->currency_code) . ')'."\n"; + $htmltext.='
'.$langs->trans("Language").': '. ($imgLang?$imgLang.' ':'') . ($this->language_code=='auto'?$langs->trans("AutoDetectLang"):$langs->trans("Language_".$this->language_code)); + if (! empty($this->description)) $htmltext.='
'.$langs->trans("Description").': '.$this->description."\n"; + $htmltext.= '

'; + + $out.= $form->textwithtooltip('', $htmltext, 2, 1, $text, 'login_block_elem multicompany_block', 2); + + if (! empty($selectEntities)) { + $out.= ' + '; + + $out.= '
'."\n"; + $out.= '
'.$langs->trans('SelectAnEntity'); + $out.= $selectEntities; + $out.= '
'."\n"; + } else { + + } + } + } + + if (($level = checkMultiCompanyVersion()) === -2) + { + $msg = get_htmloutput_mesg(img_warning('default') . ' ' . $langs->trans("MultiCompanyUpgradeIsNeeded"), '', 'mc-upgrade-alert', 1); + $out.= ' + '; + } + + $this->resprints = $out; + } + + /** + * + * @return string + */ + private function getDropdownMenu() + { + global $conf, $user, $langs; + + $this->getInfo($conf->entity); + + if ($cache = getCache('country_' . $this->country_id)) { + $country = $cache; + } else { + $country = getCountry($this->country_id); + setCache('country_' . $this->country_id, $country); + } + $imgCountry=picto_from_langcode($this->country_code, 'class="multicompany-flag-country"'); + $imgLang=picto_from_langcode($this->language_code, 'class="multicompany-flag-language"'); + + $dropdownBody = ''; + $dropdownBody.= ' '.$langs->trans("ShowMoreInfos").''; + $dropdownBody.= '
'; + $dropdownBody.= '
'.$langs->trans("Entity").''."\n"; + $dropdownBody.= '
'.$langs->trans("Label").': '.$this->label."\n"; + $dropdownBody.= '
'.$langs->trans("Country").': '. ($imgCountry?$imgCountry.' ':'') . $country."\n"; + $dropdownBody.= '
'.$langs->trans("Currency").': '. currency_name($this->currency_code) . ' (' . $langs->getCurrencySymbol($this->currency_code) . ')'."\n"; + $dropdownBody.= '
'.$langs->trans("Language").': '. ($imgLang?$imgLang.' ':'') . ($this->language_code=='auto'?$langs->trans("AutoDetectLang"):$langs->trans("Language_".$this->language_code)); + if (! empty($this->description)) $dropdownBody.= '
'.$langs->trans("Description").': '.$this->description."\n"; + $dropdownBody.= '
'; + + $selectEntities = $this->select_entities('', 'changeentity', '', false, array($conf->entity), false, false, '', 'minwidth200imp', true, true); + + $entitySwitchLink ='
'.$langs->trans("SwitchEntity").'
'; + $entityConfigLink =' '.$langs->trans("Setup").''; + + $out = '
'; + $out.= '
'; + + $out.= ' + '; + + return $out; + } + + /** + * Set parameters with referent entity + * + * @param Conf $conf + * @param string $element + */ + public function setConstant(&$conf, $element) + { + if (! empty($this->config)) + { + $constants=array(); + + if ($element == 'thirdparty') + { + $constants = array( + 'SOCIETE_CODECLIENT_ADDON', + 'COMPANY_ELEPHANT_MASK_CUSTOMER', + 'COMPANY_ELEPHANT_MASK_SUPPLIER', + 'SOCIETE_IDPROF1_UNIQUE', + 'SOCIETE_IDPROF2_UNIQUE', + 'SOCIETE_IDPROF3_UNIQUE', + 'SOCIETE_IDPROF4_UNIQUE' + ); + } + + if (! empty($constants)) + { + foreach($constants as $name) + { + if (! empty($this->config[$name])) $conf->global->$name = $this->config[$name]; + } + } + } + } + + /** + * + * @param int $groupid + * @param int $template + * @param array $entities + * @return number + */ + public function duplicateUserGroupRights($groupid, $template, $entities) + { + require_once DOL_DOCUMENT_ROOT.'/user/class/usergroup.class.php'; + + $error=0; + + dol_syslog(get_class($this)."::duplicateUserGroupRights groupid=".$groupid." template=".$template." entities=".implode(",", $entities), LOG_DEBUG); + + $groupstatic = new UserGroup($this->db); + $ret = $groupstatic->fetch($groupid, '', false); + if ($ret > 0) + { + $this->getInstanceDao(); + $permsgroupbyentity = $this->dao->getGroupRightsByEntity($groupid, $template); + + if (! empty($entities)) + { + foreach($entities as $entity) + { + if ($error > 0) break; + + $ret = $groupstatic->delrights('', 'allmodules', '', $entity); + if ($ret < 0) { + $error++; + break; + } + + foreach($permsgroupbyentity as $rid) + { + $ret = $groupstatic->addrights($rid, '', '', $entity); + if ($ret < 0) { + $error++; + break; + } + } + } + + if (!$error) { + return 1; + } else { + return -1; + } + + } else { + return -2; + } + + } else { + return -3; + } + } + +} diff --git a/htdocs/custom/multicompany/class/api_multicompany.class.php b/htdocs/custom/multicompany/class/api_multicompany.class.php new file mode 100755 index 00000000000..46ba5284f75 --- /dev/null +++ b/htdocs/custom/multicompany/class/api_multicompany.class.php @@ -0,0 +1,334 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +use Luracast\Restler\RestException; + +dol_include_once('/multicompany/class/dao_multicompany.class.php', 'DaoMulticompany'); + +/** + * API class for multicompany + * + * @access protected + * @class DolibarrApiAccess {@requires user,external} + */ +class Multicompany extends DolibarrApi +{ + /** + * @var array $FIELDS Mandatory fields, checked when create and update object + */ + static $FIELDS = array( + 'label' + ); + + /** + * Constructor + */ + function __construct() + { + global $db, $conf; + $this->db = $db; + } + + /** + * Get properties of an entity + * + * Return an array with entity informations + * + * @param int $id ID of entity + * @return array|mixed data without useless information + * + * @throws RestException + */ + function get($id) + { + if (! DolibarrApiAccess::$user->rights->multicompany->read) { + throw new RestException(401); + } + + // The DaoMulticompany::fetch() method uses the global variable $user. + global $user; + $user = DolibarrApiAccess::$user; + + $multicompany = new DaoMulticompany($this->db); + $result = $multicompany->fetch($id); + if ( ! $result ) { + throw new RestException(404, 'entity not found'); + } + + return $this->_cleanObjectDatas($multicompany); + } + + /** + * List entities + * + * Get a list of entities + * + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.label:like:'SO-%') and (t.visible:=:'1')" + * @return array Array of entities objects + * + * @throws RestException + */ + function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 0, $page = 0, $sqlfilters = '') { + global $db, $conf; + + $obj_ret = array(); + + if(! DolibarrApiAccess::$user->rights->multicompany->read) { + throw new RestException(401); + } + + $sql = "SELECT t.rowid"; + $sql.= " FROM ".MAIN_DB_PREFIX."entity as t"; + $sql.= ' WHERE t.active = 1'; + + // Add sql filters + if ($sqlfilters) + { + if (! DolibarrApi::_checkFilters($sqlfilters)) + { + throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters); + } + $regexstring='\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)'; + $sql.=" AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; + } + + $sql.= $db->order($sortfield, $sortorder); + if ($limit) { + if ($page < 0) + { + $page = 0; + } + $offset = $limit * $page; + + $sql.= $db->plimit($limit + 1, $offset); + } + + $result = $db->query($sql); + if ($result) + { + // The DaoMulticompany::fetch() method uses the global variable $user. + global $user; + $user = DolibarrApiAccess::$user; + + $i=0; + $num = $db->num_rows($result); + $min = min($num, ($limit <= 0 ? $num : $limit)); + while ($i < $min) + { + $obj = $db->fetch_object($result); + $multicompany= new DaoMulticompany($this->db); + if ($multicompany->fetch($obj->rowid)) { + $obj_ret[] = $this->_cleanObjectDatas($multicompany); + } + $i++; + } + } + else { + throw new RestException(503, 'Error when retrieve entities list : '.$db->lasterror()); + } + if ( ! count($obj_ret)) { + throw new RestException(404, 'No entities found'); + } + + return $obj_ret; + } + + /** + * Create entity object + * + * @param array $request_data Request data + * @return int ID of entity + */ + /*function post($request_data = null) + { + if (! DolibarrApiAccess::$user->rights->adherent->configurer) { + throw new RestException(401); + } + // Check mandatory fields + $result = $this->_validate($request_data); + + $membertype = new AdherentType($this->db); + foreach($request_data as $field => $value) { + $membertype->$field = $value; + } + if ($membertype->create(DolibarrApiAccess::$user) < 0) { + throw new RestException(500, 'Error creating member type', array_merge(array($membertype->error), $membertype->errors)); + } + return $membertype->id; + }*/ + + /** + * Update entity + * + * @param int $id ID of entity to update + * @param array $request_data Datas + * @return int + */ + /*function put($id, $request_data = null) + { + if (! DolibarrApiAccess::$user->rights->adherent->configurer) { + throw new RestException(401); + } + + $membertype = new AdherentType($this->db); + $result = $membertype->fetch($id); + if( ! $result ) { + throw new RestException(404, 'member type not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('member',$membertype->id,'adherent_type')) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + foreach($request_data as $field => $value) { + if ($field == 'id') continue; + // Process the status separately because it must be updated using + // the validate() and resiliate() methods of the class AdherentType. + $membertype->$field = $value; + } + + // If there is no error, update() returns the number of affected rows + // so if the update is a no op, the return value is zero. + if ($membertype->update(DolibarrApiAccess::$user) >= 0) + return $this->get($id); + + return false; + }*/ + + /** + * Delete entity + * + * @param int $id entity ID + * @return array + */ + /*function delete($id) + { + if (! DolibarrApiAccess::$user->rights->adherent->configurer) { + throw new RestException(401); + } + $membertype = new AdherentType($this->db); + $result = $membertype->fetch($id); + if( ! $result ) { + throw new RestException(404, 'member type not found'); + } + + if ( ! DolibarrApi::_checkAccessToResource('member',$membertype->id,'adherent_type')) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + if (! $membertype->delete($membertype->id)) { + throw new RestException(401,'error when deleting member type'); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'member type deleted' + ) + ); + }*/ + + /** + * Validate fields before creating an object + * + * @param array|null $data Data to validate + * @return array + * + * @throws RestException + */ + function _validate($data) + { + $membertype = array(); + foreach (MembersTypes::$FIELDS as $field) { + if (!isset($data[$field])) + throw new RestException(400, "$field field missing"); + $membertype[$field] = $data[$field]; + } + return $membertype; + } + + /** + * Clean sensible object datas + * + * @param object $object Object to clean + * @return array Array of cleaned object properties + */ + function _cleanObjectDatas($object) { + + $object = parent::_cleanObjectDatas($object); + + // Remove constants + foreach($object as $key => $value) + { + if (preg_match('/^MAIN_/', $key)) + { + unset($object->$key); + } + } + + unset($object->language); + unset($object->fk_tables); + unset($object->import_key); + unset($object->array_options); + unset($object->linkedObjectsIds); + unset($object->context); + unset($object->canvas); + unset($object->fk_project); + unset($object->contact); + unset($object->contact_id); + unset($object->thirdparty); + unset($object->user); + unset($object->origin); + unset($object->origin_id); + unset($object->ref_ext); + unset($object->barcode_type); + unset($object->barcode_type_code); + unset($object->barcode_type_label); + unset($object->barcode_type_coder); + unset($object->mode_reglement_id); + unset($object->cond_reglement_id); + unset($object->cond_reglement); + unset($object->fk_delivery_address); + unset($object->shipping_method_id); + unset($object->modelpdf); + unset($object->fk_account); + unset($object->note_public); + unset($object->note_private); + unset($object->fk_incoterms); + unset($object->libelle_incoterms); + unset($object->location_incoterms); + unset($object->name); + unset($object->lastname); + unset($object->firstname); + unset($object->civility_id); + unset($object->total_ht); + unset($object->total_tva); + unset($object->total_localtax1); + unset($object->total_localtax2); + unset($object->total_ttc); + unset($object->ref); + unset($object->statut); + unset($object->note); + + return $object; + } + +} diff --git a/htdocs/custom/multicompany/class/dao_multicompany.class.php b/htdocs/custom/multicompany/class/dao_multicompany.class.php new file mode 100755 index 00000000000..1760b43094f --- /dev/null +++ b/htdocs/custom/multicompany/class/dao_multicompany.class.php @@ -0,0 +1,990 @@ + + * Copyright (C) 2011 Herve Prot + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/** + * \file htdocs/multicompany/dao_multicompany.class.php + * \ingroup multicompany + * \brief File Class multicompany + */ +require_once DOL_DOCUMENT_ROOT . '/core/class/commonobject.class.php'; +require_once DOL_DOCUMENT_ROOT . '/core/class/extrafields.class.php'; + +/** + * \class DaoMulticompany + * \brief Class of the module multicompany + */ +class DaoMulticompany extends CommonObject +{ + public $element = 'entity'; // !< Id that identify managed objects + public $table_element = 'entity'; // !< Name of table without prefix where object is stored + + public $id; + public $label; + public $description; + + public $options=array(); + public $options_json; + + public $entity=array(); + public $entities=array(); + + public $fk_tables=array(); + + public $visible; + public $active; + public $currency; + public $language; + + + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + public function __construct($db) + { + $this->db = $db; + + $this->fk_tables = array( + 'societe' => array( + 'key' => 'fk_soc', + 'childs' => array( + 'societe_address', + 'societe_commerciaux', + 'societe_log', + 'societe_prices', + 'societe_remise', + 'societe_remise_except', + 'societe_rib', + 'socpeople' + ) + ), + 'product' => array( + 'key' => 'fk_product', + 'childs' => array( + 'product_ca', + 'product_lang', + 'product_price', + 'product_stock', + 'product_fournisseur_price' => array( + 'key' => 'fk_product_fournisseur', + 'childs' => array('product_fournisseur_price_log') + ), + ) + ), + 'projet' => array( + 'key' => 'fk_projet', + 'childs' => array( + 'projet_task' => array( + 'key' => 'fk_task', + 'childs' => array('projet_task_time') + ) + ) + ) + ); + } + + /** + * Fetch entity + * + * @param int $id + * @return int + */ + public function fetch($id) + { + global $user; + + //clearCache($id); + if ($cache = getCache($id)) + { + foreach ($cache as $key => $value) + { + $this->$key = $value; + } + } + else + { + $sql = "SELECT rowid, label, description, options, visible, active"; + $sql.= " FROM ".MAIN_DB_PREFIX."entity"; + $sql.= " WHERE rowid = ".$id; + + $result = $this->db->query($sql); + if ($result) + { + if ($this->db->num_rows($result)) + { + $obj = $this->db->fetch_object($result); + + $this->id = $obj->rowid; + $this->label = $obj->label; + $this->description = $obj->description; + $this->options = json_decode($obj->options, true); + $this->visible = $obj->visible; + $this->active = $obj->active; + + if (is_array($this->options) && ! empty($this->options) && is_array($this->options['sharings'])) + { + // for backward compatibility + if (array_key_exists('referent', $this->options['sharings'])) + { + if (empty($this->options['referent'])) + { + $this->options['referent'] = $this->options['sharings']['referent']; + } + unset($this->options['sharings']['referent']); + } + + // for backward compatibility + if (array_key_exists('societe', $this->options['sharings'])) + { + if (empty($this->options['sharings']['thirdparty'])) + { + $this->options['sharings']['thirdparty'] = $this->options['sharings']['societe']; + } + unset($this->options['sharings']['societe']); + } + + // for backward compatibility + if (array_key_exists('bank_account', $this->options['sharings'])) + { + if (empty($this->options['sharings']['bankaccount'])) + { + $this->options['sharings']['bankaccount'] = $this->options['sharings']['bank_account']; + } + unset($this->options['sharings']['bank_account']); + } + } + + $this->fetch_optionals(); + + $cache = array( + 'id' => $this->id, + 'label' => $this->label, + 'description' => $this->description, + 'options' => $this->options, + 'visible' => $this->visible, + 'active' => $this->active, + 'array_options' => $this->array_options + ); + + setCache($this->id, $cache); + } + else + { + return -2; + } + } + else + { + return -3; + } + } + + if (! empty($user->login)) + { + $this->getConstants(); + } + + return 1; + } + + /** + * Create entity + * + * @param User $user Object of user that ask creation + * @param int $call_trigger false = no, true = yes + * @return int >= 0 if OK, < 0 if KO + */ + public function create(User $user, $call_trigger = true) + { + global $conf; + + $error=0; + + // Clean parameters + $this->label = trim($this->label); + $this->description = trim($this->description); + $this->options_json = json_encode($this->options); + + dol_syslog(get_class($this)."::create ".$this->label); + + $this->db->begin(); + + $now=dol_now(); + + $sql = "INSERT INTO ".MAIN_DB_PREFIX."entity ("; + $sql.= "label"; + $sql.= ", description"; + $sql.= ", datec"; + $sql.= ", fk_user_creat"; + $sql.= ", options"; + $sql.= ", visible"; + $sql.= ", active"; + $sql.= ") VALUES ("; + $sql.= "'".$this->db->escape($this->label)."'"; + $sql.= ", '".$this->db->escape($this->description)."'"; + $sql.= ", '".$this->db->idate($now)."'"; + $sql.= ", ".$user->id; + $sql.= ", '".$this->db->escape($this->options_json)."'"; + $sql.= ", ".(! empty($this->visible)?$this->db->escape($this->visible):0); + $sql.= ", ".(! empty($this->active)?$this->db->escape($this->active):0); + $sql.= ")"; + + dol_syslog(get_class($this)."::create sql=".$sql, LOG_DEBUG); + $result=$this->db->query($sql); + if ($result) + { + $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."entity"); + + if (! $error) { + + if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) { + $result = $this->insertExtraFields(); + if ($result < 0) { + $error ++; + } + } + } + + dol_syslog(get_class($this)."::Create success id=".$this->id); + } + + if (!$error && $call_trigger) + { + // Call trigger + $result = $this->call_trigger('MULTICOMPANY_CREATE', $user); + if ($result < 0) $error++; + // End call triggers + } + + if (empty($error)) { + $this->db->commit(); + return $this->id; + } + else + { + dol_syslog(get_class($this)."::Create echec ".$this->error); + $this->db->rollback(); + return -1; + } + } + + /** + * Update entity + * + * @param int $id Id of entity (deprecated, use 0 here and call update on an object loaded by a fetch) + * @param User $user User who requests the update + * @param int $call_trigger false = no, true = yes + * @return int <0 if KO, >=0 if OK + */ + public function update($id, User $user, $call_trigger = true) + { + global $conf; + + $error=0; + + if (empty($id)) $id = $this->id; + + // Clean parameters + $this->label = trim($this->label); + $this->description = trim($this->description); + $this->options_json = json_encode($this->options); + + dol_syslog(get_class($this)."::update id=".$id." label=".$this->label); + + $this->db->begin(); + + $sql = "UPDATE ".MAIN_DB_PREFIX."entity SET"; + $sql.= " label = '" . $this->db->escape($this->label) ."'"; + $sql.= ", description = '" . $this->db->escape($this->description) ."'"; + $sql.= ", options = '" . $this->db->escape($this->options_json) ."'"; + $sql.= " WHERE rowid = " . $id; + + dol_syslog(get_class($this)."::create sql=".$sql, LOG_DEBUG); + $result=$this->db->query($sql); + if ($result) + { + dol_syslog(get_class($this)."::Update success id=".$id); + + if (! $error) { + + if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) { + $result = $this->insertExtraFields(); + if ($result < 0) { + $error ++; + } + } + } + } + + if (!$error && $call_trigger) + { + // Call trigger + $result = $this->call_trigger('MULTICOMPANY_MODIFY', $user); + if ($result < 0) $error++; + // End call triggers + } + + if (empty($error)) { + $this->db->commit(); + clearCache($id); + clearCache('constants_' . $id); + return 1; + } + else + { + dol_syslog(get_class($this)."::Update echec ".$this->error, LOG_ERR); + $this->db->rollback(); + return -1; + } + } + + /** + * Delete entity + * + * @param int $id Id of entity to delete + * @param int $call_trigger false = no, true = yes + * @return int <0 if KO, >0 if OK + */ + public function delete($id, $call_trigger = true) + { + global $user; + + $error=0; + + $this->db->begin(); + + if (!$error && $call_trigger) + { + // Call trigger + $result = $this->call_trigger('MULTICOMPANY_DELETE', $user); + if ($result < 0) $error++; + // End call triggers + } + + if (! $error) + { + $sql = "DELETE FROM ".MAIN_DB_PREFIX."const"; + $sql.= " WHERE entity = " . $id; + dol_syslog(get_class($this)."::Delete sql=".$sql, LOG_DEBUG); + if ($this->db->query($sql)) + { + // TODO remove records of all tables + } + else + { + $error++; + $this->error .= $this->db->lasterror(); + dol_syslog(get_class($this)."::Delete erreur -1 ".$this->error, LOG_ERR); + } + } + + // Removed extrafields + if (!$error) + { + $result = $this->deleteExtraFields(); + if ($result < 0) + { + $error++; + dol_syslog(get_class($this)."::delete error -2 ".$this->error, LOG_ERR); + } + } + + if (! $error) + { + $sql = "DELETE FROM ".MAIN_DB_PREFIX."entity"; + $sql.= " WHERE rowid = " . $id; + dol_syslog(get_class($this)."::Delete sql=".$sql, LOG_DEBUG); + if (!$this->db->query($sql)) { + $error++; + $this->error .= $this->db->lasterror(); + dol_syslog(get_class($this)."::Delete erreur -1 ".$this->error, LOG_ERR); + } + } + + if (! $error) + { + dol_syslog(get_class($this)."::Delete success id=".$id); + $this->db->commit(); + clearCache($id); + clearCache('constants_' . $id); + return 1; + } + else + { + dol_syslog(get_class($this)."::Delete echec ".$this->error); + $this->db->rollback(); + return -1; + } + } + + /** + * + * + */ + public function getConstants() + { + $key = 'constants_' . $this->id; + //clearCache('constants_' . $this->id); + + if ($cache = getCache($key)) + { + foreach ($cache as $key => $value) + { + $this->$key = $value; + } + } + else + { + $cache=array(); + + $sql = "SELECT "; + $sql.= $this->db->decrypt('name')." as name"; + $sql.= ", ".$this->db->decrypt('value')." as value"; + $sql.= " FROM ".MAIN_DB_PREFIX."const"; + $sql.= " WHERE entity = ".$this->id; + $sql.= " AND ".$this->db->decrypt('name')." LIKE 'MAIN_%'"; + + $result = $this->db->query($sql); + if ($result) + { + $num=$this->db->num_rows($result); + $i=0; + + while ($i < $num) + { + $obj = $this->db->fetch_object($result); + + if ($obj->name === 'MAIN_INFO_SOCIETE_COUNTRY') + { + $tmp = explode(':', $obj->value); + $this->country_id = $tmp[0]; + $cache['country_id'] = $this->country_id; + $this->country_code = $tmp[1]; + $cache['country_code'] = $this->country_code; + } + else if ($obj->name === 'MAIN_MONNAIE') + { + $this->currency_code = $obj->value; + $cache['currency_code'] = $this->currency_code; + } + else if ($obj->name === 'MAIN_LANG_DEFAULT') + { + $this->language_code = $obj->value; + $cache['language_code'] = $this->language_code; + } + else if ($obj->name === 'MAIN_INFO_SOCIETE_NOM') + { + $this->name = $obj->value; + $cache['name'] = $this->name; + } + else if ($obj->name === 'MAIN_INFO_SOCIETE_ZIP') + { + $this->zip = $obj->value; + $cache['zip'] = $this->zip; + } + else if ($obj->name === 'MAIN_INFO_SOCIETE_ADDRESS') + { + $this->address = $obj->value; + $cache['address'] = $this->address; + } + else if ($obj->name === 'MAIN_INFO_SOCIETE_TOWN') + { + $this->town = $obj->value; + $cache['town'] = $this->town; + } + else if ($obj->name === 'MAIN_INFO_SOCIETE_STATE') + { + $this->state_id = $obj->value; + $cache['state_id'] = $this->state_id; + } + + $constname = $obj->name; + $this->$constname = $obj->value; + $cache[$constname] = $this->$constname; + + $i++; + } + + setCache($key, $cache); + } + else + { + return -1; + } + } + + return 1; + } + + /** + * Remove all records of an entity + * + * @param int $id Entity id + * @return int + */ + private function deleteEntityRecords($id) + { + $error=1; + + $this->db->begin(); + + $tables = $this->db->DDLListTables($this->db->database_name); + if (is_array($tables) && ! empty($tables)) + { + foreach($tables as $table) + { + $fields = $this->db->DDLInfoTable($table); + foreach ($fields as $field) + { + if (is_array($field) && in_array('entity', $field)) + { + $tablewithoutprefix = str_replace(MAIN_DB_PREFIX, '', $table); + $objIds = $this->getIdByForeignKey($tablewithoutprefix, $id); + if (! empty($objIds)) + { + if (array_key_exists($tablewithoutprefix, $this->fk_tables)) + { + // Level 0 + $foreignKey = $this->fk_tables[$tablewithoutprefix]['key']; + foreach($this->fk_tables[$tablewithoutprefix]['childs'] as $childTable => $child) + { + // Level 1 + if (! is_int($childTable) && is_array($child)) + { + echo 'childTableLevel1='.$childTable.'
'; + $objLevel1Ids = array(); + foreach($objIds as $rowid) + { + $ret = $this->getIdByForeignKey($childTable, $rowid, $foreignKey); + if (!empty($ret)) + $objLevel1Ids = array_merge($objLevel1Ids, $ret); + } + + sort($objLevel1Ids); + //var_dump($objLevel1Ids); + + // Level 2 + foreach($child['childs'] as $childLevel2) + { + echo 'childTableLevel2='.$childLevel2.'
'; + foreach($objLevel1Ids as $rowid) + { + $sql = "DELETE FROM " . MAIN_DB_PREFIX . $childLevel2; + $sql.= " WHERE " . $child['key'] . " = " . $rowid; + //echo $sql.'
'; + //dol_syslog(get_class($this)."::deleteEntityRecords sql=" . $sql, LOG_DEBUG); + /*if (!$this->db->query($sql)) { + $error++; + $this->error .= $this->db->lasterror(); + dol_syslog(get_class($this)."::deleteEntityRecords error -1 " . $this->error, LOG_ERR); + }*/ + } + } + + foreach($objIds as $rowid) + { + $sql = "DELETE FROM " . MAIN_DB_PREFIX . $childTable; + $sql.= " WHERE " . $foreignKey . " = " . $rowid; + //echo $sql.'
'; + //dol_syslog(get_class($this)."::deleteEntityRecords sql=" . $sql, LOG_DEBUG); + /*if (!$this->db->query($sql)) { + $error++; + $this->error .= $this->db->lasterror(); + dol_syslog(get_class($this)."::deleteEntityRecords error -1 " . $this->error, LOG_ERR); + }*/ + } + } + else + { + foreach($objIds as $rowid) + { + $sql = "DELETE FROM " . MAIN_DB_PREFIX . $child; + $sql.= " WHERE " . $foreignKey . " = " . $rowid; + //echo $sql.'
'; + //dol_syslog(get_class($this)."::deleteEntityRecords sql=" . $sql, LOG_DEBUG); + /*if (!$this->db->query($sql)) { + $error++; + $this->error .= $this->db->lasterror(); + dol_syslog(get_class($this)."::deleteEntityRecords error -1 " . $this->error, LOG_ERR); + }*/ + } + } + } + echo 'with childs = '.$table.'
'; + } + else + { + echo 'without childs = '.$table.'
'; + } + } + } + } + } + + if (! $error) + { + dol_syslog(get_class($this)."::deleteEntityRecords success entity=".$id); + $this->db->commit(); + return 1; + } + else + { + dol_syslog(get_class($this)."::deleteEntityRecords echec ".$this->error); + $this->db->rollback(); + return -1; + } + } + return 0; + } + + /** + * Get all rowid from a table by couple foreign key / id + * + * @param string $table + * @param int $id + * @param string $foreignkey + * @param string $fieldname + * @return int[] + */ + private function getIdByForeignKey($table, $id, $foreignkey = 'entity', $fieldname = 'rowid') + { + $objIds=array(); + $foreignkey = (! empty($foreignkey) ? $foreignkey : 'entity'); + $fieldname = (! empty($fieldname) ? $fieldname : 'rowid'); + + $sql = "SELECT " . $fieldname . " FROM " . MAIN_DB_PREFIX . $table; + $sql.= " WHERE " . $foreignkey . " = " . $id; + //echo $sql.'
'; + $resql = $this->db->query($sql); + if ($resql) + { + $i = 0; + $num = $this->db->num_rows($resql); + while ($i < $num) + { + $obj = $this->db->fetch_object($resql); + $objIds[] = $obj->$fieldname; + $i++; + } + } + + return $objIds; + } + + /** + * Set status of an entity + * + * @param int $id Id of entity + * @param string $type Type of status (visible or active) + * @param string $value Value of status (0: disable, 1: enable) + * @return int + */ + public function setEntity($id, $type='active', $value) + { + $this->db->begin(); + + $sql = "UPDATE ".MAIN_DB_PREFIX."entity"; + $sql.= " SET " . $this->db->escape($type) . " = " . (int) $value; + $sql.= " WHERE rowid = " . (int) $id; + + dol_syslog(get_class($this)."::setEntity sql=".$sql, LOG_DEBUG); + $result = $this->db->query($sql); + if ($result) + { + $this->db->commit(); + clearCache($id); + return 1; + } + else + { + $this->db->rollback(); + return -1; + } + } + + /** + * List of entities + * + * @param int $login If use in login page or not + * @param array $exclude Entity ids to exclude + * @param bool $onlyactive sort only active entities + * @return void + */ + public function getEntities($login = false, $exclude = false, $onlyactive = false) + { + global $conf, $user; + + $this->entities=array(); + + if ($login || empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE) || (! empty($user->admin) && empty($user->entity))) + { + $sql = "SELECT DISTINCT(rowid), rang"; // Distinct parce que si user dans plusieurs groupes d'une entité, la liste d'entités de la petite terre affiche plusieurs fois la même entité + $sql.= " FROM ".MAIN_DB_PREFIX."entity"; + if (! empty($user->admin) && empty($user->entity) && is_array($exclude) && ! empty($exclude)) + { + $exclude = implode(",", $exclude); + $sql.= " WHERE rowid NOT IN (" . $exclude .")"; + if (! empty($onlyactive)) $sql.= " AND active = 1"; + } + else if (! empty($onlyactive)) { + $sql.= " WHERE active = 1"; + } + if (!$login) { + $sql.= " ORDER BY rowid"; + } + else { + $sql.= " ORDER BY rang DESC, rowid ASC"; + } + } + else + { + $sql = "SELECT DISTINCT(entity) as rowid"; // Distinct parce que si user dans plusieurs groupes d'une entité, la liste d'entités de la petite terre affiche plusieurs fois la même entité + $sql.= " FROM ".MAIN_DB_PREFIX."usergroup_user"; + $sql.= " WHERE fk_user = ".$user->id; + $sql.= " ORDER BY entity"; + } + + $result = $this->db->query($sql); + if ($result) + { + $num = $this->db->num_rows($result); + $i = 0; + + while ($i < $num) + { + $obj = $this->db->fetch_object($result); + + $objectstatic = new self($this->db); + $ret = $objectstatic->fetch($obj->rowid); + + $this->entities[$i] = $objectstatic; + + $i++; + } + } + } + + /** + * Check user $userid belongs to at least one group created into entity $id + * + * @param int $entity + * @param int $userid + * @return int + */ + public function verifyRight($entity, $userid) + { + global $conf; + + $tmpuser=new User($this->db); + $tmpuser->fetch($userid); + //$tmpuser->fetch($userid, '', '',0, $entity); // TODO check compatibility with DAV authentication + + if ($tmpuser->id) + { + if (empty($tmpuser->entity)) return 1; // superadmin always allowed + if ($tmpuser->entity == $entity && $tmpuser->admin) return 1; // entity admin allowed + if (empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) + { + if ($tmpuser->entity == $entity) return 1; // user allowed if belong to entity + } + else + { + $sql = "SELECT count(rowid) as nb"; + $sql.= " FROM ".MAIN_DB_PREFIX."usergroup_user"; + $sql.= " WHERE fk_user=".$userid; + $sql.= " AND entity=".$entity; + //echo $sql; + + dol_syslog(get_class($this)."::verifyRight sql=".$sql, LOG_DEBUG); + $result = $this->db->query($sql); + if ($result) + { + $obj = $this->db->fetch_object($result); + return $obj->nb; // user allowed if at least in one group + } + } + } + + return 0; + } + + /** + * Get constants values of an entity + * + * @param int $entity Entity id + * @param string $constname Specific contant + * @return array Array of constants + */ + public function getEntityConfig($entity, $constname=null) + { + $const=array(); + + $sql = "SELECT ".$this->db->decrypt('value')." as value"; + $sql.= ", ".$this->db->decrypt('name')." as name"; + $sql.= " FROM ".MAIN_DB_PREFIX."const"; + $sql.= " WHERE entity = " . $entity; + if (! empty($constname)) { + if (preg_match('/\_\*$/', $constname)) + { + $constname = str_replace('*', '', $constname); + $sql.= " AND ".$this->db->decrypt('name')." LIKE '" . $this->db->escape($constname) ."%'"; + } + else + { + $sql.= " AND ".$this->db->decrypt('name')." = '" . $this->db->escape($constname) ."'"; + } + } + + dol_syslog(get_class($this)."::getEntityConfig sql=".$sql, LOG_DEBUG); + $resql = $this->db->query($sql); + if ($resql) + { + $i = 0; + $num = $this->db->num_rows($resql); + while ($i < $num) + { + $obj = $this->db->fetch_object($resql); + + $const[$obj->name] = $obj->value; + + $i++; + } + + } + return $const; + } + + /** + * Get group rights by entity + * + * @param int $group + * @param int $entity + * @return array[] + */ + public function getGroupRightsByEntity($group, $entity) + { + $permsgroupbyentity = array(); + + $sql = "SELECT DISTINCT r.id, r.libelle, r.module, gr.entity"; + $sql.= " FROM ".MAIN_DB_PREFIX."rights_def as r,"; + $sql.= " ".MAIN_DB_PREFIX."usergroup_rights as gr"; + $sql.= " WHERE gr.fk_id = r.id"; + $sql.= " AND gr.entity = " . (int) $entity; + $sql.= " AND gr.fk_usergroup = " . (int) $group; + + dol_syslog(get_class($this)."::getGroupRightsByEntity sql=".$sql, LOG_DEBUG); + $result=$this->db->query($sql); + if ($result) + { + $num = $this->db->num_rows($result); + $i = 0; + + while ($i < $num) + { + $obj = $this->db->fetch_object($result); + array_push($permsgroupbyentity, $obj->id); + $i++; + } + + $this->db->free($result); + + return $permsgroupbyentity; + } + else + { + dol_print_error($db); + } + } + + /** + * Get list of groups + * + * @return array + */ + public function getListOfGroups() + { + $ret=array(); + + $sql = "SELECT g.rowid"; + $sql.= " FROM ".MAIN_DB_PREFIX."usergroup as g"; + $sql.= " GROUP BY g.rowid"; + + $resql = $this->db->query($sql); + if ($resql) + { + while ($obj = $this->db->fetch_object($resql)) + { + $ret[] = $obj->rowid; + } + + $this->db->free($result); + + return $ret; + } + else + { + $this->error=$this->db->lasterror(); + return -1; + } + } + + /** + * + * @param unknown $groupid + * @param unknown $template + * @return User[]|number + */ + public function getListOfUsersInGroupByTemplate($groupid, $template) + { + $ret=array(); + + $sql = "SELECT u.rowid, ug.entity as usergroup_entity"; + $sql.= " FROM ".MAIN_DB_PREFIX."user as u"; + $sql.= ", ".MAIN_DB_PREFIX."usergroup_user as ug"; + $sql.= " WHERE ug.fk_user = u.rowid"; + $sql.= " AND ug.fk_usergroup = " . (int) $groupid; + $sql.= " AND ug.entity = " . (int) $template; + + dol_syslog(get_class($this)."::getListOfUsersInGroupByEntity groupid=".$groupid." template=".$template, LOG_DEBUG); + $resql = $this->db->query($sql); + if ($resql) + { + while ($obj = $this->db->fetch_object($resql)) + { + if (! array_key_exists($obj->rowid, $ret)) + { + $newuser=new User($this->db); + $newuser->fetch($obj->rowid); + $ret[$obj->rowid]=$newuser; + } + } + + $this->db->free($resql); + + return $ret; + } + else + { + $this->error=$this->db->lasterror(); + return -1; + } + } + +} diff --git a/htdocs/custom/multicompany/class/index.html b/htdocs/custom/multicompany/class/index.html new file mode 100755 index 00000000000..e69de29bb2d diff --git a/htdocs/custom/multicompany/class/ssp.class.php b/htdocs/custom/multicompany/class/ssp.class.php new file mode 100755 index 00000000000..d048ea745ca --- /dev/null +++ b/htdocs/custom/multicompany/class/ssp.class.php @@ -0,0 +1,412 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/** + * \file /multicompany/class/ssp.class.php + * \ingroup multicompany + * \brief File of class to manage DataTables server-side processing + */ + +/** + * \class SSP + * \brief DataTables server-side processing class + */ +class SSP +{ + /** + * Create the data output array for the DataTables rows + * + * @param array $columns Column information array + * @param array $data Data from the SQL get + * @return array Formatted data in a row based format + */ + static function data_output ( $columns, $data ) + { + $out = array(); + + for ( $i=0, $ien=count($data) ; $i<$ien ; $i++ ) { + $row = array(); + + for ( $j=0, $jen=count($columns) ; $j<$jen ; $j++ ) { + $column = $columns[$j]; + + // Is there a formatter? + if ( isset( $column['formatter'] ) ) { + $row[ $column['dt'] ] = $column['formatter']( $data[$i][ $column['db'] ], $data[$i] ); + } + else { + $row[ $column['dt'] ] = $data[$i][ $columns[$j]['db'] ]; + } + } + + $out[] = $row; + } + + return $out; + } + + + /** + * Paging + * + * Construct the LIMIT clause for server-side processing SQL query + * + * @param array $request Data sent to server by DataTables + * @param array $columns Column information array + * @return string SQL limit clause + */ + static function limit ( $request, $columns, $db ) + { + $limit = ''; + + if ( isset($request['start']) && $request['length'] != -1 ) { + $limit = $db->plimit(intval($request['length']), intval($request['start'])); + } + + return $limit; + } + + + /** + * Ordering + * + * Construct the ORDER BY clause for server-side processing SQL query + * + * @param array $request Data sent to server by DataTables + * @param array $columns Column information array + * @return string SQL order by clause + */ + static function order ( $request, $columns, $db ) + { + $order = ''; + $sortfield = array(); + $sortorder = array(); + + if ( isset($request['order']) && count($request['order']) ) { + $dtColumns = self::pluck( $columns, 'dt' ); + for ( $i=0, $ien=count($request['order']) ; $i<$ien ; $i++ ) { + // Convert the column index into the column data property + $columnIdx = intval($request['order'][$i]['column']); + $requestColumn = $request['columns'][$columnIdx]; + + $columnIdx = array_search( $requestColumn['data'], $dtColumns ); + $column = $columns[ $columnIdx ]; + + if ( $requestColumn['orderable'] == 'true' ) { + $dir = $request['order'][$i]['dir'] === 'asc' ? 'ASC' : 'DESC'; + $sortfield[] = $column['db']; + $sortorder[] = $dir; + } + } + + $order = $db->order(implode(', ', $sortfield), implode(', ', $sortorder)); + } + + return $order; + } + + + /** + * Searching / Filtering + * + * Construct the WHERE clause for server-side processing SQL query. + * + * NOTE this does not match the built-in DataTables filtering which does it + * word by word on any field. It's possible to do here performance on large + * databases would be very poor + * + * @param array $request Data sent to server by DataTables + * @param array $columns Column information array + * @param array $bindings Array of values for PDO bindings, used in the + * sql_exec() function + * @return string SQL where clause + */ + static function filter ( $request, $columns, $db ) + { + $globalSearch = array(); + $columnSearch = array(); + $dtColumns = self::pluck( $columns, 'dt' ); + + if ( isset($request['search']) && $request['search']['value'] != '' ) { + $str = $request['search']['value']; + + for ( $i=0, $ien=count($request['columns']) ; $i<$ien ; $i++ ) { + $requestColumn = $request['columns'][$i]; + $columnIdx = array_search( $requestColumn['data'], $dtColumns ); + $column = $columns[ $columnIdx ]; + + if ( $requestColumn['searchable'] == 'true' ) { + $globalSearch[] = $column['db']." LIKE '%" . $db->escape($str)."%'"; + } + } + } + + // Individual column filtering + if ( isset( $request['columns'] ) ) { + for ( $i=0, $ien=count($request['columns']) ; $i<$ien ; $i++ ) { + $requestColumn = $request['columns'][$i]; + $columnIdx = array_search( $requestColumn['data'], $dtColumns ); + $column = $columns[ $columnIdx ]; + + $str = $requestColumn['search']['value']; + + if ( $requestColumn['searchable'] == 'true' && + $str != '' ) { + $columnSearch[] = $column['db']." LIKE '%" . $db->escape($str)."%'"; + } + } + } + + // Combine the filters into a single string + $where = ''; + + if ( count( $globalSearch ) ) { + $where = '('.implode(' OR ', $globalSearch).')'; + } + + if ( count( $columnSearch ) ) { + $where = $where === '' ? + implode(' AND ', $columnSearch) : + $where .' AND '. implode(' AND ', $columnSearch); + } + + if ( $where !== '' ) { + $where = 'WHERE '.$where; + } + + return $where; + } + + + /** + * Perform the SQL queries needed for an server-side processing requested, + * utilising the helper functions of this class, limit(), order() and + * filter() among others. The returned array is ready to be encoded as JSON + * in response to an SSP request, or can be modified if needed before + * sending back to the client. + * + * @param array $request Data sent to server by DataTables + * @param string $table SQL table to query + * @param string $primaryKey Primary key of the table + * @param array $columns Column information array + * @return array Server-side processing response array + */ + static function simple ( $request, $db, $table, $primaryKey, $columns ) + { + // Build the SQL query string from the request + $limit = self::limit( $request, $columns, $db ); + $order = self::order( $request, $columns, $db ); + $where = self::filter( $request, $columns, $db ); + + // Main query to actually get the data + $sql = + "SELECT ".implode(", ", self::pluck($columns, 'db'))." + FROM $table + $where + $order + $limit"; + + $data = self::sql_exec($db, $sql); + //print_r($data); + + // Data set length after filtering + $resFilterLength = self::sql_exec($db, + "SELECT COUNT({$primaryKey}) + FROM $table + $where" + ); + $recordsFiltered = $resFilterLength[0][0]; + + // Total data set length + $resTotalLength = self::sql_exec($db, + "SELECT COUNT({$primaryKey}) + FROM $table" + ); + $recordsTotal = $resTotalLength[0][0]; + + /* + * Output + */ + return array( + "draw" => isset ( $request['draw'] ) ? + intval( $request['draw'] ) : + 0, + "recordsTotal" => intval( $recordsTotal ), + "recordsFiltered" => intval( $recordsFiltered ), + "data" => self::data_output( $columns, $data ) + ); + } + + + /** + * The difference between this method and the `simple` one, is that you can + * apply additional `where` conditions to the SQL queries. These can be in + * one of two forms: + * + * * 'Result condition' - This is applied to the result set, but not the + * overall paging information query - i.e. it will not effect the number + * of records that a user sees they can have access to. This should be + * used when you want apply a filtering condition that the user has sent. + * * 'All condition' - This is applied to all queries that are made and + * reduces the number of records that the user can access. This should be + * used in conditions where you don't want the user to ever have access to + * particular records (for example, restricting by a login id). + * + * @param array $request Data sent to server by DataTables + * @param string $table SQL table to query + * @param string $primaryKey Primary key of the table + * @param array $columns Column information array + * @param string $whereResult WHERE condition to apply to the result set + * @param string $whereAll WHERE condition to apply to all queries + * @return array Server-side processing response array + */ + static function complex ( $request, $db, $table, $primaryKey, $columns, $whereResult=null, $whereAll=null ) + { + $whereAllSql = ''; + + // Build the SQL query string from the request + $limit = self::limit( $request, $columns, $db ); + $order = self::order( $request, $columns, $db ); + $where = self::filter( $request, $columns, $db ); + + $whereResult = self::_flatten( $whereResult ); + $whereAll = self::_flatten( $whereAll ); + + if ( $whereResult ) { + $where = $where ? + $where .' AND '.$whereResult : + 'WHERE '.$whereResult; + } + + if ( $whereAll ) { + $where = $where ? + $where .' AND '.$whereAll : + 'WHERE '.$whereAll; + + $whereAllSql = 'WHERE '.$whereAll; + } + + // Main query to actually get the data + $data = self::sql_exec($db, + "SELECT ".implode(", ", self::pluck($columns, 'db'))." + FROM $table + $where + $order + $limit" + ); + + // Data set length after filtering + $resFilterLength = self::sql_exec($db, + "SELECT COUNT({$primaryKey}) + FROM $table + $where" + ); + $recordsFiltered = $resFilterLength[0][0]; + + // Total data set length + $resTotalLength = self::sql_exec($db, + "SELECT COUNT({$primaryKey}) + FROM $table ". + $whereAllSql + ); + $recordsTotal = $resTotalLength[0][0]; + + /* + * Output + */ + return array( + "draw" => isset ( $request['draw'] ) ? + intval( $request['draw'] ) : + 0, + "recordsTotal" => intval( $recordsTotal ), + "recordsFiltered" => intval( $recordsFiltered ), + "data" => self::data_output( $columns, $data ) + ); + } + + + /** + * Execute an SQL query on the database + * + * @param string $sql SQL query to execute. + * @return array Result from the query (all rows) + */ + static function sql_exec ( $db, $sql ) + { + $out=array(); + + $resql = $db->query($sql); + if ($resql) + { + $i = 0; + $num_rows=$db->num_rows($resql); + while ($i < $num_rows) + { + $array = $db->fetch_array($resql); + array_push($out, $array); + $i++; + } + } + + return $out; + } + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Internal methods + */ + + /** + * Pull a particular property from each assoc. array in a numeric array, + * returning and array of the property values from each item. + * + * @param array $a Array to get data from + * @param string $prop Property to read + * @return array Array of property values + */ + static function pluck ( $a, $prop ) + { + $out = array(); + + for ( $i=0, $len=count($a) ; $i<$len ; $i++ ) { + $out[] = $a[$i][$prop]; + } + + return $out; + } + + + /** + * Return a string from an array or a string + * + * @param array|string $a Array to join + * @param string $join Glue for the concatenation + * @return string Joined string + */ + static function _flatten ( $a, $join = ' AND ' ) + { + if ( ! $a ) { + return ''; + } + else if ( $a && is_array($a) ) { + return implode( $join, $a ); + } + return $a; + } +} + diff --git a/htdocs/custom/multicompany/core/ajax/functions.php b/htdocs/custom/multicompany/core/ajax/functions.php new file mode 100755 index 00000000000..335d84fc154 --- /dev/null +++ b/htdocs/custom/multicompany/core/ajax/functions.php @@ -0,0 +1,286 @@ + + * Copyright (C) 2011 Herve Prot + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/** + * \file multicompany/core/ajax/functions.php + * \brief File to return ajax result + */ + +if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL','1'); // Disables token renewal +if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1'); +if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1'); +if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1'); +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1'); +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); +if (! defined('NOREQUIREHOOK')) define('NOREQUIREHOOK',1); + +if (isset($_GET['action']) && $_GET['action'] === 'getEntityLogo') { + define("NOLOGIN",1); // This means this output page does not require to be logged. + $entity=(! empty($_GET['id']) ? (int) $_GET['id'] : 1); + if (is_numeric($entity)) define("DOLENTITY", $entity); +} + +$res=@include("../../../main.inc.php"); // For root directory +if (! $res && file_exists($_SERVER['DOCUMENT_ROOT']."/main.inc.php")) + $res=@include($_SERVER['DOCUMENT_ROOT']."/main.inc.php"); // Use on dev env only +if (! $res) $res=@include("../../../../main.inc.php"); // For "custom" directory + +dol_include_once('/multicompany/class/actions_multicompany.class.php', 'ActionsMulticompany'); +require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php"; + +$id = GETPOST('id', 'int'); // id of entity +$action = GETPOST('action', 'alpha'); // action method +$type = GETPOST('type', 'alpha'); // type of action +$element = GETPOST('element', 'alpha'); // type of element +$fk_element = GETPOST('fk_element', 'int'); // id of element + +$template = GETPOST('template', 'int'); +if (GETPOSTISSET('entities')) { + $entities = json_decode(GETPOST('entities', 'none'), true); +} + +/* + * View + */ + +// Ajout directives pour resoudre bug IE +//header('Cache-Control: Public, must-revalidate'); +//header('Pragma: public'); + +//top_htmlhead("", "", 1); // Replaced with top_httphead. An ajax page does not need html header. +top_httphead('application/json'); + +if (empty($conf->multicompany->enabled)) { + echo json_encode(array('status' => 'error')); + $db->close(); + exit(); +} + +//print ''."\n"; + +// Registering the location of boxes +if (! empty($action) && is_numeric($id)) +{ + if ($action == 'switchEntity' && ! empty($user->login)) + { + dol_syslog("multicompany action=".$action." entity=".$id, LOG_DEBUG); + + $object = new ActionsMulticompany($db); + echo $object->switchEntity($id); + } + else if ($action == 'setStatusEnable' && ! empty($user->admin) && ! $user->entity) + { + dol_syslog("multicompany action=".$action." type=".$type." entity=".$id, LOG_DEBUG); + + $object = new ActionsMulticompany($db); + $fieldname = ($type == 'activetemplate' ? 'active' : $type); + echo $object->setStatus($id, $fieldname, 1); + } + else if ($action == 'setStatusDisable' && ! empty($user->admin) && ! $user->entity) + { + dol_syslog("multicompany action=".$action." type=".$type." entity=".$id, LOG_DEBUG); + + $object = new ActionsMulticompany($db); + $fieldname = ($type == 'activetemplate' ? 'active' : $type); + $ret = $object->setStatus($id, $fieldname, 0); + if ($ret == 1 && $type == 'active') { + $ret = $object->setStatus($id, 'visible', 0); + } + echo $ret; + } + else if ($action == 'deleteEntity' && $id != 1 && ! empty($user->admin) && ! $user->entity) + { + dol_syslog("multicompany action=".$action." entity=".$id, LOG_DEBUG); + + $object = new ActionsMulticompany($db); + echo $object->deleteEntity($id); + } + else if ($action == 'setColOrder' && ! empty($user->admin) && ! $user->entity) + { + $id = (int) $id; + $direction = GETPOST('dir', 'aZ'); + $colOrder = array('id' => $id, 'direction' => $direction); + + if (dolibarr_set_const($db, 'MULTICOMPANY_COLORDER', json_encode($colOrder), 'chaine', 0, '', 0) > 0) { + $ret = json_encode(array('status' => 'success')); + } + else { + $ret = json_encode(array('status' => 'error')); + } + + echo $ret; + } + else if ($action == 'setColHidden' && ! empty($user->admin) && ! $user->entity) + { + $state = GETPOST('state', 'aZ'); + $colHidden = (! empty($conf->global->MULTICOMPANY_COLHIDDEN) ? json_decode($conf->global->MULTICOMPANY_COLHIDDEN, true) : array()); + + if ($state == 'visible') { + $colHidden = array_diff($colHidden, array(intval($id))); + } else if ($state == 'hidden') { + array_push($colHidden, intval($id)); + } + + sort($colHidden); + + if (dolibarr_set_const($db, 'MULTICOMPANY_COLHIDDEN', json_encode($colHidden), 'chaine', 0, '', 0) > 0) { + $ret = json_encode(array('status' => 'success')); + } + else { + $ret = json_encode(array('status' => 'error')); + } + + echo $ret; + } + else if ($action == 'modifyEntity' && ((! empty($user->admin) && ! $user->entity) || ! empty($user->rights->multicompany->thirdparty->write))) + { + if ($element == 'societe') + { + $object = new Societe($db); + $ret = $object->fetch($fk_element); + if ($ret > 0) { + + $object->oldcopy = clone $object; + + // To not set code if third party is not concerned. But if it had values, we keep them. + if (empty($object->client) && empty($object->oldcopy->code_client)) $object->code_client=''; + if (empty($object->fournisseur) && empty($object->oldcopy->code_fournisseur)) $object->code_fournisseur=''; + + $object->entity = $id; + + $ret = $object->update($object->id, $user, 0, $object->oldcopy->codeclient_modifiable(), $object->oldcopy->codefournisseur_modifiable(), 'update', 1); + if ($ret > 0) { + $ret = json_encode(array('status' => 'success')); + } + else { + $ret = json_encode(array('status' => 'error', 'error' => $object->errors)); + } + } + else { + $ret = json_encode(array('status' => 'error', 'error' => $object->errors)); + } + } + else if ($element == 'contact') + { + require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; + + $object = new Contact($db); + $ret = $object->fetch($fk_element); + if ($ret > 0) { + + $object->entity = $id; + + $ret = $object->update($object->id, $user, 1, 'update', 1); + if ($ret > 0) { + $ret = json_encode(array('status' => 'success')); + } + else { + $ret = json_encode(array('status' => 'error', 'error' => $object->errors)); + } + } + else { + $ret = json_encode(array('status' => 'error', 'error' => $object->errors)); + } + } + + echo $ret; + } + else if ($action === 'getEntityOptions' && ! empty($conf->global->MULTICOMPANY_TEMPLATE_MANAGEMENT) && ! empty($user->admin) && empty($user->entity)) + { + $object = new ActionsMulticompany($db); + $object->getInfo($id); + + $entities = $object->getEntitiesList(false, false, true, true); + + echo json_encode( + array( + 'status' => 'success', + 'options' => $object->options, + 'labels' => $entities + ) + ); + } + else if ($action === 'duplicateUserGroupRights' && ! empty($conf->global->MULTICOMPANY_TEMPLATE_MANAGEMENT) && ! empty($user->admin) && empty($user->entity) && ! empty($template) && ! empty($entities)) + { + $multicompany = new ActionsMulticompany($db); + $ret = $multicompany->duplicateUserGroupRights($id, $template, $entities); + if ($ret > 0) + { + echo json_encode(array('status' => 'success')); + } + else + { + echo json_encode(array( + 'status' => 'error', + 'id' => $id, + 'template' => $template, + 'entities' => $entities + ) + ); + } + } + else if ($action === 'getEntityLogo' && empty($conf->global->MULTICOMPANY_HIDE_LOGIN_COMBOBOX)) + { + $urllogo = DOL_URL_ROOT.'/theme/login_logo.png'; + + if (! empty($mysoc->logo_small) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$mysoc->logo_small)) + { + $urllogo = DOL_URL_ROOT.'/viewimage.php?cache=1&entity='.$id.'&modulepart=mycompany&file='.urlencode('logos/thumbs/'.$mysoc->logo_small); + } + elseif (! empty($mysoc->logo) && is_readable($conf->mycompany->dir_output.'/logos/'.$mysoc->logo)) + { + $urllogo = DOL_URL_ROOT.'/viewimage.php?cache=1&entity='.$id.'&modulepart=mycompany&file='.urlencode('logos/'.$mysoc->logo); + $width = 128; + } + elseif (is_readable(DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/img/dolibarr_logo.png')) + { + $urllogo = DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/dolibarr_logo.png'; + } + elseif (is_readable(DOL_DOCUMENT_ROOT.'/theme/dolibarr_logo.png')) + { + $urllogo = DOL_URL_ROOT.'/theme/dolibarr_logo.png'; + } + + $bgimg = null; + $unsplashimg = null; + + if (! empty($conf->global->MULTICOMPANY_LOGIN_BACKGROUND_BY_ENTITY)) + { + if (! empty($conf->global->ADD_UNSPLASH_LOGIN_BACKGROUND)) + { + $unsplashimg = $conf->global->ADD_UNSPLASH_LOGIN_BACKGROUND; + } + + if (! empty($conf->global->MAIN_LOGIN_BACKGROUND)) + { + $bgimg = DOL_URL_ROOT.'/viewimage.php?cache=1&noalt=1&entity='.$id.'&modulepart=mycompany&file=logos/'.urlencode($conf->global->MAIN_LOGIN_BACKGROUND); + } + } + + echo json_encode(array( + 'status' => 'success', + 'urllogo' => dol_html_entity_decode($urllogo, null), + 'bgimg' => dol_html_entity_decode($bgimg, null), + 'unsplashimg' => dol_html_entity_decode($unsplashimg, null) + ) + ); + } +} + +$db->close(); diff --git a/htdocs/custom/multicompany/core/ajax/index.html b/htdocs/custom/multicompany/core/ajax/index.html new file mode 100755 index 00000000000..e69de29bb2d diff --git a/htdocs/custom/multicompany/core/ajax/list.php b/htdocs/custom/multicompany/core/ajax/list.php new file mode 100755 index 00000000000..30b48cce8bc --- /dev/null +++ b/htdocs/custom/multicompany/core/ajax/list.php @@ -0,0 +1,248 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/** + * \file /multicompany/core/ajax/list.php + * \brief File to return datables output of entities list + */ + +if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL','1'); // Disables token renewal +if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK','1'); +if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1'); +if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1'); +if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1'); +if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1'); +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); +if (! defined('NOREQUIREHOOK')) define('NOREQUIREHOOK',1); + +$res=@include("../../../main.inc.php"); // For root directory +if (! $res && file_exists($_SERVER['DOCUMENT_ROOT']."/main.inc.php")) + $res=@include($_SERVER['DOCUMENT_ROOT']."/main.inc.php"); // Use on dev env only +if (! $res) $res=@include("../../../../main.inc.php"); // For "custom" directory + +require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/core/class/extrafields.class.php'; +dol_include_once('/multicompany/class/dao_multicompany.class.php', 'DaoMulticompany'); +dol_include_once('/multicompany/lib/multicompany.lib.php'); +dol_include_once('/multicompany/class/ssp.class.php'); + +$langs->loadLangs(array('languages','admin','multicompany@multicompany')); + +// Defini si peux lire/modifier permisssions +$canreadEntity=! empty($user->admin); +$caneditEntity=! empty($user->admin); +$candeleteEntity=! empty($user->admin); + +top_httphead('application/json'); + +//print ''."\n"; + +//print_r($_GET); + +if (empty($user->admin) || empty($conf->multicompany->enabled)) { + echo json_encode(array('status' => 'error')); + $db->close(); + exit(); +} + +$object = new DaoMulticompany($db); + +$extrafields = new ExtraFields($db); +// fetch optionals attributes and labels +$extralabels = $extrafields->fetch_name_optionals_label($object->element); + +$start = array('start' => GETPOST('start', 'int')); +$length = array('length' => GETPOST('length', 'int')); +$draw = array('draw' => GETPOST('draw', 'int')); +$order = array('order' => GETPOST('order', 'array')); +$columns = array('columns' => GETPOST('columns', 'array')); +$search = array('search' => GETPOST('search', 'array')); + +$request = $start + $length + $draw + $order + $columns + $search; +//print_r($request); + +// DB table to use +$table = MAIN_DB_PREFIX . "entity"; + +// Table's primary key +$primaryKey = 'rowid'; + +// Array of database columns which should be read and sent back to DataTables. +// The `db` parameter represents the column name in the database, while the `dt` +// parameter represents the DataTables column identifier. In this case simple +// indexes +$columns = array(); + +$columns[]= array( 'db' => 'rowid', 'dt' => 'entity_id' ); +$columns[]= array( 'db' => 'label', 'dt' => 'entity_label' ); +$columns[]= array( 'db' => 'description', 'dt' => 'entity_description' ); +$columns[]= array( + 'db' => 'rowid', + 'dt' => 'entity_name', + 'formatter' => function($value, $row) { + if (! empty($value)) { + global $object; + $object->fetch($value); + return $object->name; + } + } +); +$columns[]= array( + 'db' => 'rowid', + 'dt' => 'entity_zip', + 'formatter' => function($value, $row) { + if (! empty($value)) { + global $object; + $object->fetch($value); + return $object->zip; + } + } +); +$columns[]= array( + 'db' => 'rowid', + 'dt' => 'entity_town', + 'formatter' => function($value, $row) { + if (! empty($value)) { + global $object; + $object->fetch($value); + return $object->town; + } + } +); +$columns[]= array( + 'db' => 'rowid', + 'dt' => 'entity_country', + 'formatter' => function($value, $row) { + if (! empty($value)) { + global $object; + $object->fetch($value); + if ($cache = getCache('country_' . $object->country_id)) { + $country = $cache; + } else { + $country = getCountry($object->country_id); + setCache('country_' . $object->country_id, $country); + } + $img=picto_from_langcode($object->country_code, 'class="multicompany-flag-country"'); + return ($img?$img.' ':'') . $country; + } + } +); +$columns[]= array( + 'db' => 'rowid', + 'dt' => 'entity_currency', + 'formatter' => function($value, $row) { + if (! empty($value)) { + global $langs, $object; + $object->fetch($value); + return currency_name($object->currency_code) . ' (' . $langs->getCurrencySymbol($object->currency_code) . ')'; + } + } +); +$columns[]= array( + 'db' => 'rowid', + 'dt' => 'entity_language', + 'formatter' => function($value, $row) { + if (! empty($value)) { + global $langs, $object; + $object->fetch($value); + $img=picto_from_langcode($object->language_code, 'class="multicompany-flag-language"'); + return ($img?$img.' ':'') . ($object->language_code=='auto'?$langs->trans("AutoDetectLang"):$langs->trans("Language_".$object->language_code)); + } + } +); +if (! empty($extralabels)) { + foreach ($extralabels as $key => $name) + { + $columns[]= array( + 'db' => 'rowid', + 'dt' => 'entity_'.$key, + 'formatter' => function($value, $row) use ($key) { + global $object, $extrafields; + unset($object->array_options['options_'.$key]); // For avoid duplicate data in next row + $object->fetch_optionals(); + return $extrafields->showOutputField($key, $object->array_options['options_'.$key]); + } + ); + } +} +$columns[]= array( + 'db' => 'visible', + 'dt' => 'entity_visible', + 'formatter' => function($value, $row) { + global $langs; + if (! empty($value)) { + if ($value == 1) { + return img_picto($langs->trans("Enabled"),'on','id="visible_' . $row['rowid'] . '"',false,0,0,'','multicompany-button-visible-on'); + } else { + return ''; + } + } else if (! empty($row['active'])) { + return img_picto($langs->trans("Disabled"),'off','id="visible_' . $row['rowid'] . '"',false,0,0,'','multicompany-button-visible-off'); + } else { + return img_picto($langs->trans("Disabled"),'off','id="visible_' . $row['rowid'] . '"',false,0,0,'','multicompany-button-disabled'); + } + } +); +$columns[]= array( + 'db' => 'active', + 'dt' => 'entity_active', + 'formatter' => function($value, $row) { + global $conf, $langs; + if ($row['rowid'] == 1 || $conf->entity == $row['rowid']) { + return img_picto($langs->trans("Enabled"),'on','id="active_' . $row['rowid'] . '"',false,0,0,'','multicompany-button-disabled'); + } else if (! empty($value)) { + if ($row['visible'] == 2) { + return img_picto($langs->trans("Enabled"),'on','id="activetemplate_' . $row['rowid'] . '"',false,0,0,'','multicompany-button-active-on'); + } else { + return img_picto($langs->trans("Enabled"),'on','id="active_' . $row['rowid'] . '"',false,0,0,'','multicompany-button-active-on'); + } + } else { + if ($row['visible'] == 2) { + return img_picto($langs->trans("Disabled"),'off','id="activetemplate_' . $row['rowid'] . '"',false,0,0,'','multicompany-button-active-off'); + } else { + return img_picto($langs->trans("Disabled"),'off','id="active_' . $row['rowid'] . '"',false,0,0,'','multicompany-button-active-off'); + } + } + } +); +$columns[]= array( + 'db' => 'rowid', + 'dt' => 'entity_tools', + 'formatter' => function($value, $row) { + global $conf, $langs, $caneditEntity, $candeleteEntity; + $ret=''; + if ($caneditEntity) { + $ret.= img_edit($langs->transnoentities("Edit"),0, 'id="edit_' . $value . '" class="multicompany-button-setup"'); + } + if ($candeleteEntity) { + if ($value == 1 || $conf->entity == $value) { + $ret.= img_delete($langs->transnoentities("Delete"), 'id="delete_' . $value . '" class="multicompany-button-disabled"'); + } else { + $ret.= img_delete($langs->transnoentities("Delete"), 'id="delete_' . $value . '" class="multicompany-button-delete"'); + } + } + return $ret; + } +); + +//var_dump($columns); +echo json_encode( + SSP::simple( $request, $db, $table, $primaryKey, $columns ) +); + +$db->close(); diff --git a/htdocs/custom/multicompany/core/js/index.html b/htdocs/custom/multicompany/core/js/index.html new file mode 100755 index 00000000000..e69de29bb2d diff --git a/htdocs/custom/multicompany/core/js/lib_head.js b/htdocs/custom/multicompany/core/js/lib_head.js new file mode 100755 index 00000000000..668687e127e --- /dev/null +++ b/htdocs/custom/multicompany/core/js/lib_head.js @@ -0,0 +1,214 @@ +// Copyright (C) 2014-2019 Regis Houssin +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// or see http://www.gnu.org/ + +// +// \file /multicompany/core/js/lib_head.js +// \brief File that include javascript functions (included if option use_javascript activated) +// + +/* + * + */ +function setMulticompanyConstant(url, code, input, entity) { + $.get( url, { + action: "set", + name: code, + entity: entity + }, + function() { + $("#set_" + code).hide(); + $("#del_" + code).show(); + $.each(input, function(type, data) { + // Enable another element + if (type == "enabled") { + $.each(data, function(key, value) { + var newvalue=(value.search("^#") < 0 ? "#" : "") + value; + $(newvalue).removeAttr("disabled"); + }); + // Disable another element + } else if (type == "disabled") { + $.each(data, function(key, value) { + var newvalue=(value.search("^#") < 0 ? "#" : "") + value; + $(newvalue).attr("disabled", true); + }); + // enable and disable another element + } else if (type == "disabledenabled") { + $.each(data, function(key, value) { + var newvalue=(value.search("^#") < 0 ? "#" : "") + value; + $(newvalue).removeAttr("disabled"); + }); + // Show another element + } else if (type == "showhide" || type == "show") { + $.each(data, function(key, value) { + var newvalue=(value.search("^#") < 0 ? "#" : "") + value; + $(newvalue).show(); + }); + } else if (type == "hideshow") { + $.each(data, function(key, value) { + var newvalue=(value.search("^#") < 0 ? "#" : "") + value; + $(newvalue).hide(); + }); + // Set another constant + } else if (type == "set" || type == "del") { + $.each(data, function(key, value) { + if (type == "set") { + $("#set_" + value).hide(); + $("#del_" + value).show(); + $.get( url, { + action: type, + name: key, + value: value, + entity: entity + }); + } else if (type == "del") { + $("#del_" + value).hide(); + $("#set_" + value).show(); + $.get( url, { + action: type, + name: value, + entity: entity + }); + } + }); + // reload the current page + } else if (type == "reload") { + var url = window.location.pathname; + location.href=url; + } + }); + }); +} + +/* + * + */ +function delMulticompanyConstant(url, code, input, entity) { + $.get( url, { + action: "del", + name: code, + entity: entity + }, + function() { + $("#del_" + code).hide(); + $("#set_" + code).show(); + $.each(input, function(type, data) { + // Enable another element + if (type == "enabled") { + $.each(data, function(key, value) { + var newvalue=(value.search("^#") < 0 ? "#" : "") + value; + $(newvalue).removeAttr("disabled"); + }); + // Disable another element + } else if (type == "disabled") { + $.each(data, function(key, value) { + var newvalue=(value.search("^#") < 0 ? "#" : "") + value; + $(newvalue).attr("disabled", true); + }); + // enable and disable another element + } else if (type == "disabledenabled") { + $.each(data, function(key, value) { + var newvalue=(value.search("^#") < 0 ? "#" : "") + value; + $(newvalue).attr("disabled", true); + }); + } else if (type == "showhide" || type == "hide") { + $.each(data, function(key, value) { + var newvalue=(value.search("^#") < 0 ? "#" : "") + value; + $(newvalue).hide(); + }); + } else if (type == "hideshow") { + $.each(data, function(key, value) { + var newvalue=(value.search("^#") < 0 ? "#" : "") + value; + $(newvalue).show(); + }); + // Delete another constant + } else if (type == "set" || type == "del") { + $.each(data, function(key, value) { + if (type == "set") { + $("#set_" + value).hide(); + $("#del_" + value).show(); + $.get( url, { + action: type, + name: key, + value: value, + entity: entity + }); + } else if (type == "del") { + $("#del_" + value).hide(); + $("#set_" + value).show(); + $.get( url, { + action: type, + name: value, + entity: entity + }); + } + }); + // reload the current page + } else if (type == "reload") { + var url = window.location.pathname; + location.href=url; + } + }); + }); +} + +/* + * + */ +function confirmMulticompanyConstantAction(action, url, code, input, box, entity, yesButton, noButton) { + var boxConfirm = box; + $("#confirm_" + code) + .attr("title", boxConfirm.title) + .html(boxConfirm.content) + .dialog({ + resizable: false, + height: 180, + width: 500, + modal: true, + buttons: [ + { + id : 'yesButton_' + code, + text : yesButton, + click : function() { + if (action == "set") { + setMulticompanyConstant(url, code, input, entity); + } else if (action == "del") { + delMulticompanyConstant(url, code, input, entity); + } + // Close dialog + $(this).dialog("close"); + // Execute another method + if (boxConfirm.method) { + var fnName = boxConfirm.method; + if (window.hasOwnProperty(fnName)) { + window[fnName](); + } + } + } + }, + { + id : 'noButton_' + code, + text : noButton, + click : function() { + $(this).dialog("close"); + } + } + ] + }); + // For information dialog box only, hide the noButton + if (boxConfirm.info) { + $("#noButton_" + code).button().hide(); + } +} diff --git a/htdocs/custom/multicompany/core/login/functions_mc.php b/htdocs/custom/multicompany/core/login/functions_mc.php new file mode 100755 index 00000000000..69dc4d86659 --- /dev/null +++ b/htdocs/custom/multicompany/core/login/functions_mc.php @@ -0,0 +1,166 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file multicompany/core/login/functions_mc.php + * \ingroup multicompany + * \brief Authentication functions for Multicompany mode when combobox in login page is disabled + */ + + +/** + * Check validity of user/password/entity + * If test is ko, reason must be filled into $_SESSION["dol_loginmesg"] + * + * @param string $usertotest Login + * @param string $passwordtotest Password + * @param int $entitytotest Number of instance (always 1 if module multicompany not enabled) + * @return string Login if OK, '' if KO + */ +function check_user_password_mc($usertotest,$passwordtotest,$entitytotest=1) +{ + global $db,$conf,$langs; + global $mc; + + dol_syslog("functions_mc::check_user_password_mc usertotest=".$usertotest); + + $login=''; + + if (!empty($conf->multicompany->enabled)) + { + $langs->loadLangs(array('main','errors','multicompany@multicompany')); + + if (! empty($conf->global->MULTICOMPANY_HIDE_LOGIN_COMBOBOX)) + { + $entity=$entitytotest; + + if (!empty($usertotest)) + { + // If test username/password asked, we define $test=false and $login var if ok, set $_SESSION["dol_loginmesg"] if ko + $table = MAIN_DB_PREFIX."user"; + $usernamecol = 'login'; + $entitycol = 'entity'; + + $sql ='SELECT rowid, entity, pass, pass_crypted'; + $sql.=' FROM '.$table; + $sql.=' WHERE '.$usernamecol." = '".$db->escape($usertotest)."'"; + $sql.=' AND statut = 1'; + + dol_syslog("functions_mc::check_user_password_mc sql=" . $sql); + $resql=$db->query($sql); + if ($resql) + { + $obj=$db->fetch_object($resql); + if ($obj) + { + $passclear=$obj->pass; + $passcrypted=$obj->pass_crypted; + $passtyped=$passwordtotest; + + $passok=false; + + // Check crypted password + $cryptType=''; + if (! empty($conf->global->DATABASE_PWD_ENCRYPTED)) $cryptType=$conf->global->DATABASE_PWD_ENCRYPTED; + + // By default, we used MD5 + if (! in_array($cryptType,array('md5'))) $cryptType='md5'; + // Check crypted password according to crypt algorithm + if ($cryptType == 'md5') + { + if (dol_verifyHash($passtyped, $passcrypted)) + { + $passok=true; + dol_syslog("functions_mc::check_user_password_mc Authentification ok - " . $cryptType . " of pass is ok"); + } + } + + // For compatibility with old versions + if (! $passok) + { + if ((! $passcrypted || $passtyped) + && ($passclear && ($passtyped == $passclear))) + { + $passok=true; + dol_syslog("functions_mc::check_user_password_mc Authentification ok - found pass in database"); + } + } + + if ($passok && !empty($obj->entity)) + { + global $entitytotest; + + $entitytotest = $obj->entity; + + if (! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) + { + $sql = "SELECT uu.entity"; + $sql.= " FROM " . MAIN_DB_PREFIX . "usergroup_user as uu"; + $sql.= ", " . MAIN_DB_PREFIX . "entity as e"; + $sql.= " WHERE uu.entity = e.rowid AND e.visible < 2"; // Remove template of entity + $sql.= " AND fk_user = " . $obj->rowid; + + dol_syslog("functions_mc::check_user_password_mc sql=" . $sql, LOG_DEBUG); + $result = $db->query($sql); + if ($result) + { + while($array = $db->fetch_array($result)) // user allowed if at least in one group + { + $entitytotest = $array['entity']; + break; // stop in first entity + } + } + } + + $ret=$mc->switchEntity($entitytotest, $obj->rowid); + + if ($ret < 0) $passok=false; + } + + // Password ok ? + if ($passok) + { + $login=$usertotest; + } + else + { + dol_syslog("functions_mc::check_user_password_mc Authentification ko bad password pour '".$usertotest."'", LOG_ERR); + $_SESSION["dol_loginmesg"]=$langs->trans("ErrorBadLoginPassword"); + } + } + else + { + dol_syslog("functions_mc::check_user_password_mc Authentification ko user not found for '".$usertotest."'", LOG_ERR); + $_SESSION["dol_loginmesg"]=$langs->trans("ErrorBadLoginPassword"); + } + } + else + { + dol_syslog("functions_mc::check_user_password_mc Authentification ko db error for '".$usertotest."' error=".$db->lasterror(), LOG_ERR); + $_SESSION["dol_loginmesg"]=$db->lasterror(); + } + } + } + else + { + dol_syslog("functions_mc::check_user_password_mc Authentification ko, the drop-down list of entities on the login page must be hidden", LOG_ERR); + $_SESSION["dol_loginmesg"]=$langs->trans("ErrorDropDownListOfEntitiesMustBeHidden"); + } + } + + return $login; +} diff --git a/htdocs/custom/multicompany/core/login/index.html b/htdocs/custom/multicompany/core/login/index.html new file mode 100755 index 00000000000..e69de29bb2d diff --git a/htdocs/custom/multicompany/core/modules/index.html b/htdocs/custom/multicompany/core/modules/index.html new file mode 100755 index 00000000000..e69de29bb2d diff --git a/htdocs/custom/multicompany/core/modules/modMultiCompany.class.php b/htdocs/custom/multicompany/core/modules/modMultiCompany.class.php new file mode 100755 index 00000000000..6f2bd0f908c --- /dev/null +++ b/htdocs/custom/multicompany/core/modules/modMultiCompany.class.php @@ -0,0 +1,587 @@ + + * Copyright (C) 2011 Herve Prot + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/** + * \defgroup multicompany Module multicompany + * \brief Descriptor file for module multicompany + * \file htdocs/core/modules/modMultiCompany.class.php + * \ingroup multicompany + * \brief Description and activation file for module MultiCompany + */ +include_once DOL_DOCUMENT_ROOT . '/core/modules/DolibarrModules.class.php'; + + +/** + * \class modMultiCompany + * \brief Description and activation class for module MultiCompany + */ +class modMultiCompany extends DolibarrModules +{ + /** + * Constructor. + * + * @param DoliDB $db Database handler + */ + function __construct($db) + { + global $langs; + + $this->db = $db; + + // Id for module (must be unique). + // Use here a free id (See in Home -> System information -> Dolibarr for list of used modules id). + $this->numero = 5000; + // Key text used to identify module (for permissions, menus, etc...) + $this->rights_class = 'multicompany'; + + // Family can be 'crm','financial','hr','projects','products','ecm','technic','other' + // It is used to group modules in module setup page + $this->family = "base"; + // Gives the possibility to the module, to provide his own family info and position of this family. + $this->familyinfo = array( + 'core' => array( + 'position' => '001', + 'label' => $langs->trans("iNodbox") + ) + ); + // Module position in the family + $this->module_position = 1; + // Module label (no space allowed), used if translation string 'ModuleXXXName' not found (where XXX is value of numeric property 'numero' of module) + $this->name = preg_replace('/^mod/i','',get_class($this)); + // Module description, used if translation string 'ModuleXXXDesc' not found (where XXX is value of numeric property 'numero' of module) + $this->description = "Multi-Company Management"; + //$this->descriptionlong = "A very lon description. Can be a full HTML content"; + $this->editor_name = 'Régis Houssin'; + $this->editor_url = 'https://www.inodbox.com'; + // Can be enabled / disabled only in the main company with superadmin account + $this->core_enabled = 1; + // Possible values for version are: 'development', 'experimental', 'dolibarr' or version + $this->version = '12.0.1'; + // Key used in llx_const table to save module status enabled/disabled (where MYMODULE is value of property name of module in uppercase) + $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); + // Name of png file (without png) used for this module. + // Png file must be in theme/yourtheme/img directory under name object_pictovalue.png. + $this->picto='multicompany@multicompany'; + + // Data directories to create when module is enabled. + $this->dirs = array(); + + // Config pages. Put here list of php page names stored in admmin directory used to setup module. + $this->config_page_url = array("multicompany.php@multicompany"); + + // Defined all module parts (triggers, login, substitutions, menus, css, etc...) + $this->module_parts = array( + 'login' => array( + 'data' => 1, + 'entity' => '0' + ), + 'triggers' => array( + 'data' => 1, + 'entity' => '0' + ), + 'hooks' => array( + 'data' => array( + 'login', + 'main', + 'mainloginpage', + 'cashdeskloginpage', + 'passwordforgottenpage', + 'toprightmenu', + 'adminmodules', + 'admincompany', + 'commonobject', + 'thirdpartycard', + 'thirdpartylist', + 'customerlist', + 'prospectlist', + 'supplierlist', + 'usercard', + 'userperms', + 'groupcard', + 'groupperms', + 'userlist', + 'userhome', + 'userdao', + 'contactlist', + 'contactprospectlist', + 'contactcustomerlist', + 'contactsupplierlist', + 'contactotherlist', + 'productcard', + 'pricesuppliercard', + 'propalcard', + 'propallist', + 'ordercard', + 'orderlist', + 'invoicecard', + 'invoicelist', + 'warehousecard', + 'stocklist' + ), + 'entity' => '0' + ), + 'css' => array( + 'data' => '/multicompany/css/multicompany.css.php', + 'entity' => '0' + ) + ); + + // Dependencies + $this->depends = array(); // List of modules id that must be enabled if this module is enabled + $this->requiredby = array(); // List of modules id to disable if this one is disabled + $this->phpmin = array(5,6); // Minimum version of PHP required by module + $this->need_dolibarr_version = array(12,0,0); // Minimum version of Dolibarr required by module + $this->langfiles = array("multicompany@multicompany"); + + // Constants + // List of particular constants to add when module is enabled + $this->const=array( + 1 => array('MULTICOMPANY_MAIN_VERSION', 'chaine', $this->version, '', 0, 'multicompany', 1), + 2 => array('MULTICOMPANY_EXTERNAL_MODULES_SHARING', 'chaine', '', '', 0, 'multicompany', 0), + 3 => array('MULTICOMPANY_NO_TOP_MENU_ENTITY_LABEL', 'chaine', 1, '', 0, 'multicompany', 0) + ); + + // Boxes + $this->boxes = array(); // List of boxes + $r=0; + + // Permissions + $this->rights = array(); + $r=0; + + $r++; + $this->rights[$r][0] = 5001; + $this->rights[$r][1] = 'Read entities (For superadmin users)'; + $this->rights[$r][2] = 'r'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'read'; + + $r++; + $this->rights[$r][0] = 5002; + $this->rights[$r][1] = 'Create/modify entities (For superadmin users)'; + $this->rights[$r][2] = 'w'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'write'; + + $r++; + $this->rights[$r][0] = 5003; + $this->rights[$r][1] = 'Delete entities (For superadmin users)'; + $this->rights[$r][2] = 'd'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'delete'; + + // Thirdparty sharing (501x) + + $r++; + $this->rights[$r][0] = 5011; + $this->rights[$r][1] = 'Read shared third parties'; + $this->rights[$r][2] = 'r'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'thirdparty'; + $this->rights[$r][5] = 'read'; + + $r++; + $this->rights[$r][0] = 5012; + $this->rights[$r][1] = 'Create/modify shared third parties'; + $this->rights[$r][2] = 'w'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'thirdparty'; + $this->rights[$r][5] = 'write'; + + $r++; + $this->rights[$r][0] = 5013; + $this->rights[$r][1] = 'Delete shared third parties'; + $this->rights[$r][2] = 'd'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'thirdparty'; + $this->rights[$r][5] = 'delete'; + + // Contact sharing (502x) + + $r++; + $this->rights[$r][0] = 5021; + $this->rights[$r][1] = 'Read shared contacts'; + $this->rights[$r][2] = 'r'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'contact'; + $this->rights[$r][5] = 'read'; + + $r++; + $this->rights[$r][0] = 5022; + $this->rights[$r][1] = 'Create/modify shared contacts'; + $this->rights[$r][2] = 'w'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'contact'; + $this->rights[$r][5] = 'write'; + + $r++; + $this->rights[$r][0] = 5023; + $this->rights[$r][1] = 'Delete shared contacts'; + $this->rights[$r][2] = 'd'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'contact'; + $this->rights[$r][5] = 'delete'; + + // Product/service sharing (503x) + + $r++; + $this->rights[$r][0] = 5031; + $this->rights[$r][1] = 'Read shared products/services'; + $this->rights[$r][2] = 'r'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'product'; + $this->rights[$r][5] = 'read'; + + $r++; + $this->rights[$r][0] = 5032; + $this->rights[$r][1] = 'Create/modify shared products/services'; + $this->rights[$r][2] = 'w'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'product'; + $this->rights[$r][5] = 'write'; + + $r++; + $this->rights[$r][0] = 5033; + $this->rights[$r][1] = 'Delete shared products/services'; + $this->rights[$r][2] = 'd'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'product'; + $this->rights[$r][5] = 'delete'; + + // Proposal sharing (504x) + + $r++; + $this->rights[$r][0] = 5041; + $this->rights[$r][1] = 'Read shared customer proposals'; + $this->rights[$r][2] = 'r'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'propal'; + $this->rights[$r][5] = 'read'; + + $r++; + $this->rights[$r][0] = 5042; + $this->rights[$r][1] = 'Create/modify shared customer proposals'; + $this->rights[$r][2] = 'w'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'propal'; + $this->rights[$r][5] = 'write'; + + $r++; + $this->rights[$r][0] = 5043; + $this->rights[$r][1] = 'Validate shared customer proposals'; + $this->rights[$r][2] = 'd'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'propal_advance'; + $this->rights[$r][5] = 'validate'; + + $r++; + $this->rights[$r][0] = 5044; + $this->rights[$r][1] = 'Send shared customer proposals'; + $this->rights[$r][2] = 'd'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'propal_advance'; + $this->rights[$r][5] = 'send'; + + $r++; + $this->rights[$r][0] = 5045; + $this->rights[$r][1] = 'Close shared customer proposals'; + $this->rights[$r][2] = 'd'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'propal'; + $this->rights[$r][5] = 'close'; + + $r++; + $this->rights[$r][0] = 5046; + $this->rights[$r][1] = 'Delete shared customer proposals'; + $this->rights[$r][2] = 'd'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'propal'; + $this->rights[$r][5] = 'delete'; + + // Order sharing (505x) + + $r++; + $this->rights[$r][0] = 5051; + $this->rights[$r][1] = 'Read shared customer orders'; + $this->rights[$r][2] = 'r'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'order'; + $this->rights[$r][5] = 'read'; + + $r++; + $this->rights[$r][0] = 5052; + $this->rights[$r][1] = 'Close shared customer orders'; + $this->rights[$r][2] = 'w'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'order'; + $this->rights[$r][5] = 'write'; + + $r++; + $this->rights[$r][0] = 5054; + $this->rights[$r][1] = 'Validate shared customer orders'; + $this->rights[$r][2] = 'd'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'order_advance'; + $this->rights[$r][5] = 'validate'; + + $r++; + $this->rights[$r][0] = 5056; + $this->rights[$r][1] = 'Send shared customer orders'; + $this->rights[$r][2] = 'd'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'order_advance'; + $this->rights[$r][5] = 'send'; + + $r++; + $this->rights[$r][0] = 5057; + $this->rights[$r][1] = 'Close shared customer orders'; + $this->rights[$r][2] = 'd'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'order'; + $this->rights[$r][5] = 'close'; + + $r++; + $this->rights[$r][0] = 5058; + $this->rights[$r][1] = 'Cancel shared customer orders'; + $this->rights[$r][2] = 'd'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'order_advance'; + $this->rights[$r][5] = 'cancel'; + + $r++; + $this->rights[$r][0] = 5059; + $this->rights[$r][1] = 'Delete shared customer orders'; + $this->rights[$r][2] = 'd'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'order'; + $this->rights[$r][5] = 'delete'; + + // Invoice sharing (506x) + + $r++; + $this->rights[$r][0] = 5061; + $this->rights[$r][1] = 'Read shared customer invoices'; + $this->rights[$r][2] = 'a'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'invoice'; + $this->rights[$r][5] = 'read'; + + $r++; + $this->rights[$r][0] = 5062; + $this->rights[$r][1] = 'Create/modify shared customer invoices'; + $this->rights[$r][2] = 'a'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'invoice'; + $this->rights[$r][5] = 'write'; + + // There is a particular permission for unvalidate because this may be not forbidden by some laws + $r++; + $this->rights[$r][0] = 5063; + $this->rights[$r][1] = 'Devalidate shared customer invoices'; + $this->rights[$r][2] = 'a'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'invoice_advance'; + $this->rights[$r][5] = 'unvalidate'; + + $r++; + $this->rights[$r][0] = 5064; + $this->rights[$r][1] = 'Validate shared customer invoices'; + $this->rights[$r][2] = 'a'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'invoice_advance'; + $this->rights[$r][5] = 'validate'; + + $r++; + $this->rights[$r][0] = 5065; + $this->rights[$r][1] = 'Send shared customer invoices'; + $this->rights[$r][2] = 'a'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'invoice_advance'; + $this->rights[$r][5] = 'send'; + + $r++; + $this->rights[$r][0] = 5066; + $this->rights[$r][1] = 'Issue payments on shared customer invoices'; + $this->rights[$r][2] = 'a'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'invoice'; + $this->rights[$r][5] = 'payment'; + + $r++; + $this->rights[$r][0] = 5067; + $this->rights[$r][1] = 'Re-open a fully paid shared customer invoices'; + $this->rights[$r][2] = 'r'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'invoice_advance'; + $this->rights[$r][5] = 'reopen'; + + $r++; + $this->rights[$r][0] = 5069; + $this->rights[$r][1] = 'Delete shared customer invoices'; + $this->rights[$r][2] = 'a'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'invoice'; + $this->rights[$r][5] = 'delete'; + + // Main menu entries + $this->menus = array(); // List of menus to add + $r=0; + + } + + /** + * Function called when module is enabled. + * The init function add constants, boxes, permissions and menus (defined in constructor) into Dolibarr database. + * It also creates data directories. + * + * @param string $options Options when enabling module ('', 'newboxdefonly', 'noboxes') + * 'noboxes' = Do not insert boxes + * 'newboxdefonly' = For boxes, insert def of boxes only and not boxes activation + * @return int 1 if OK, 0 if KO + */ + function init($options = '') + { + $sql = array(); + + $result=$this->load_tables(); + + $result=$this->setSuperAdmin(); + + $result=$this->setFirstEntity(); + + return $this->_init($sql, $options); + } + + /** + * Function called when module is disabled. + * Remove from database constants, boxes and permissions from Dolibarr database. + * Data directories are not deleted. + * + * @param string $options Options when enabling module ('', 'noboxes') + * @return int 1 if OK, 0 if KO + */ + function remove($options = '') + { + $sql = array( + "DELETE FROM ".MAIN_DB_PREFIX."const WHERE name = ".$this->db->encrypt('MAIN_MODULE_MULTICOMPANY_CSS', 1), + "DELETE FROM ".MAIN_DB_PREFIX."const WHERE name = ".$this->db->encrypt('MAIN_MODULE_MULTICOMPANY_LOGIN', 1) + ); + + return $this->_remove($sql, $options); + } + + /** + * Create tables and keys required by module + * This function is called by this->init. + * @return int <=0 if KO, >0 if OK + */ + function load_tables() + { + return $this->_load_tables('/multicompany/sql/'); + } + + /** + * Set the first entity + * + * @return int + */ + function setSuperAdmin() + { + global $user; + + $sql = 'SELECT count(rowid) FROM '.MAIN_DB_PREFIX.'user'; + $sql.= ' WHERE admin = 1 AND entity = 0'; + $res = $this->db->query($sql); + if ($res) $num = $this->db->fetch_array($res); + else dol_print_error($this->db); + + if (empty($num[0])) + { + $this->db->begin(); + + $sql = 'UPDATE '.MAIN_DB_PREFIX.'user SET entity = 0'; + $sql.= ' WHERE admin = 1 AND rowid IN (1,'.$user->id.')'; + if ($this->db->query($sql)) + { + $this->db->commit(); + return 1; + } + else + { + $this->db->rollback(); + return -1; + } + } + else + { + return 0; + } + } + + /** + * Set the first entity + * + * @return int + */ + function setFirstEntity() + { + global $user, $langs; + + $langs->load('multicompany@multicompany'); + + $sql = 'SELECT count(rowid) FROM '.MAIN_DB_PREFIX.'entity'; + $res = $this->db->query($sql); + if ($res) $num = $this->db->fetch_array($res); + else dol_print_error($this->db); + + if (empty($num[0])) + { + $this->db->begin(); + + $now = dol_now(); + + $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'entity ('; + $sql.= 'label'; + $sql.= ', description'; + $sql.= ', datec'; + $sql.= ', fk_user_creat'; + $sql.= ') VALUES ('; + $sql.= '\''.$langs->trans("MasterEntity").'\''; + $sql.= ', \''.$langs->trans("MasterEntityDesc").'\''; + $sql.= ', \''.$this->db->idate($now).'\''; + $sql.= ', '.$user->id; + $sql.= ')'; + + if ($this->db->query($sql)) + { + $this->db->commit(); + return 1; + } + else + { + $this->db->rollback(); + return -1; + } + } + else + { + return 0; + } + } +} diff --git a/htdocs/custom/multicompany/core/triggers/index.html b/htdocs/custom/multicompany/core/triggers/index.html new file mode 100755 index 00000000000..e69de29bb2d diff --git a/htdocs/custom/multicompany/core/triggers/interface_25_modMulticompany_MulticompanyWorkflow.class.php b/htdocs/custom/multicompany/core/triggers/interface_25_modMulticompany_MulticompanyWorkflow.class.php new file mode 100755 index 00000000000..a8b444a7417 --- /dev/null +++ b/htdocs/custom/multicompany/core/triggers/interface_25_modMulticompany_MulticompanyWorkflow.class.php @@ -0,0 +1,86 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/** + * \file /multicompany/core/triggers/interface_25_modMulticompany_MulticompanyWorkflow.class.php + * \ingroup multicompany + * \brief Trigger file for create multicompany data + */ + +require_once DOL_DOCUMENT_ROOT.'/core/triggers/dolibarrtriggers.class.php'; + +/** + * \class InterfaceMulticompanyWorkflow + * \brief Classe des fonctions triggers des actions personnalisees du module multicompany + */ + +class InterfaceMulticompanyWorkflow extends DolibarrTriggers +{ + public $family = 'multicompany'; + + public $description = "Triggers of this module allows to create multicompany data"; + + /** + * Version of the trigger + * + * @var string + */ + public $version = self::VERSION_DOLIBARR; + + /** + * + * @var string Image of the trigger + */ + public $picto = 'multicompany@multicompany'; + + /** + * Function called when a Dolibarrr business event is done. + * All functions "runTrigger" are triggered if file is inside directory htdocs/core/triggers or htdocs/module/core/triggers (and declared) + * + * Following properties may be set before calling trigger. The may be completed by this trigger to be used for writing the event into database: + * $object->id (id of entity) + * $object->element (element type of object) + * + * @param string $action Event action code + * @param Object $object Object + * @param User $user Object user + * @param Translate $langs Object langs + * @param conf $conf Object conf + * @return int <0 if KO, 0 if no triggered ran, >0 if OK + */ + public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf) + { + // Mettre ici le code a executer en reaction de l'action + // Les donnees de l'action sont stockees dans $object + + /*if ($action == 'COMPANY_CREATE') + { + $entity = GETPOST('new_entity', 'int', 2); // limit to POST + + if ($entity > 0) + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ". __FILE__ .". id=".$object->rowid); + + return $ret; + } + }*/ + + return 0; + } + +} diff --git a/htdocs/custom/multicompany/css/dropdown.inc.php b/htdocs/custom/multicompany/css/dropdown.inc.php new file mode 100755 index 00000000000..ef91f9078cb --- /dev/null +++ b/htdocs/custom/multicompany/css/dropdown.inc.php @@ -0,0 +1,199 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +if (! defined('ISLOADEDBYSTEELSHEET')) die('Must be call by steelsheet'); +$colorbackhmenu1='60,70,100'; // topmenu +?> +/* + + + '> + + + + + From 7c2e3c49309c875aab7890ebf075975d5c0a78e1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 26 Mar 2021 14:47:10 +0100 Subject: [PATCH 76/79] Removed old deprecated API browser --- htdocs/api/admin/explorer.php | 216 ---------------------------------- 1 file changed, 216 deletions(-) delete mode 100644 htdocs/api/admin/explorer.php diff --git a/htdocs/api/admin/explorer.php b/htdocs/api/admin/explorer.php deleted file mode 100644 index 53b9233c130..00000000000 --- a/htdocs/api/admin/explorer.php +++ /dev/null @@ -1,216 +0,0 @@ - - * Copyright (C) 2016 Laurent Destailleur - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * @deprecated Old explorer. Not using Swagger. See instead explorer in htdocs/api/index.php. - */ - -/** - * \defgroup api Module DolibarrApi - * \brief API loader - * Search files htdocs//class/api_.class.php - * \file htdocs/api/admin/explorer.php - */ - -use Luracast\Restler\Routes; - -require_once '../../main.inc.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/api/class/api.class.php'; -require_once DOL_DOCUMENT_ROOT.'/api/class/api_access.class.php'; - -// Load translation files required by the page -$langs->load("admin"); - - -/* - * View - */ - -// Enable and test if module Api is enabled -if (empty($conf->global->MAIN_MODULE_API)) { - dol_syslog("Call Dolibarr API interfaces with module REST disabled"); - print $langs->trans("WarningModuleNotActive", 'Api').'.

'; - print $langs->trans("ToActivateModule"); - exit; -} - - -$api = new DolibarrApi($db); - -$api->r->addAPIClass('Luracast\\Restler\\Resources'); //this creates resources.json at API Root -$api->r->setSupportedFormats('JsonFormat', 'XmlFormat'); -$api->r->addAuthenticationClass('DolibarrApiAccess', ''); - -$listofapis = array(); - -$modulesdir = dolGetModulesDirs(); -foreach ($modulesdir as $dir) { - /* - * Search available module - */ - //dol_syslog("Scan directory ".$dir." for API modules"); - - $handle = @opendir(dol_osencode($dir)); - if (is_resource($handle)) { - while (($file = readdir($handle)) !== false) { - if (is_readable($dir.$file) && preg_match("/^(mod.*)\.class\.php$/i", $file, $reg)) { - $modulename = $reg[1]; - - // Defined if module is enabled - $enabled = true; - $module = $part = $obj = strtolower(preg_replace('/^mod/i', '', $modulename)); - //if ($part == 'propale') $part='propal'; - if ($module == 'societe') { - $obj = 'thirdparty'; - } - if ($module == 'categorie') { - $part = 'categories'; - $obj = 'category'; - } - if ($module == 'facture') { - $part = 'compta/facture'; - $obj = 'facture'; - } - if ($module == 'ficheinter') { - $obj = 'fichinter'; - $part = 'fichinter'; - $module = 'fichinter'; - } - - if (empty($conf->$module->enabled)) { - $enabled = false; - } - - if ($enabled) { - /* - * If exists, load the API class for enable module - * - * Search files named api_.class.php into /htdocs//class directory - * - * @todo : take care of externals module! - * @todo : use getElementProperties() function ? - */ - $dir_part = DOL_DOCUMENT_ROOT.'/'.$part.'/class/'; - - $handle_part = @opendir(dol_osencode($dir_part)); - if (is_resource($handle_part)) { - while (($file_searched = readdir($handle_part)) !== false) { - if (is_readable($dir_part.$file_searched) && preg_match("/^api_(.*)\.class\.php$/i", $file_searched, $reg)) { - $classname = ucwords($reg[1]); - require_once $dir_part.$file_searched; - if (class_exists($classname)) { - dol_syslog("Found API classname=".$classname." into ".$dir); - $listofapis[] = $classname; - } - } - - /* - if (is_readable($dir_part.$file_searched) && preg_match("/^(api_.*)\.class\.php$/i",$file_searched,$reg)) - { - $classname=$reg[1]; - $classname = str_replace('Api_','',ucwords($reg[1])).'Api'; - //$classname = str_replace('Api_','',ucwords($reg[1])); - $classname = ucfirst($classname); - require_once $dir_part.$file_searched; - - // if (class_exists($classname)) - // { - // dol_syslog("Found API classname=".$classname); - // $api->r->addAPIClass($classname,''); - - // require_once DOL_DOCUMENT_ROOT.'/includes/restler/framework/Luracast/Restler/Routes.php'; - // $tmpclass = new ReflectionClass($classname); - // try { - // $classMetadata = CommentParser::parse($tmpclass->getDocComment()); - // } catch (Exception $e) { - // throw new RestException(500, "Error while parsing comments of `$classname` class. " . $e->getMessage()); - // } - - // //$listofapis[]=array('classname'=>$classname, 'fullpath'=>$file_searched); - // } - }*/ - } - } - } - } - } - } -} - -//var_dump($listofapis); -$listofapis = Routes::toArray(); // @todo api for "status" is lost here -//var_dump($listofapis); - - -llxHeader(); - -$linkback = ''.$langs->trans("BackToModuleList").''; -print load_fiche_titre($langs->trans("ApiSetup"), $linkback, 'title_setup'); - -// Define $urlwithroot -$urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root)); -$urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file -//$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current - -// Show message -print '
'; -$message = ''; -$url = ''.$urlwithroot.'/api/index.php/login?login='.urlencode($user->login).'&password=yourpassword[&reset=1]'; -$message .= $langs->trans("UrlToGetKeyToUseAPIs").':
'; -$message .= img_picto('', 'globe').' '.$url; -print $message; -print '
'; -print '
'; - -$oldclass = ''; - -print $langs->trans("ListOfAvailableAPIs").':
'; -foreach ($listofapis['v1'] as $key => $val) { - if ($key == 'login') { - continue; - } - if ($key == 'index') { - continue; - } - - if ($key) { - foreach ($val as $method => $val2) { - $newclass = $val2['className']; - - if (preg_match('/restler/i', $newclass)) { - continue; - } - - if ($oldclass != $newclass) { - print "\n
\n".$langs->trans("Class").': '.$newclass.'
'."\n"; - $oldclass = $newclass; - } - //print $key.' - '.$val['classname'].' - '.$val['fullpath']." - ".DOL_MAIN_URL_ROOT.'/api/index.php/'.strtolower(preg_replace('/Api$/','',$val['classname']))."/xxx
\n"; - $url = $urlwithroot.'/api/index.php/'.$key; - $url .= '?api_key=token'; - print img_picto('', 'globe').' '.$method.' '.$url."
\n"; - } - } -} - -print '
'; -print '
'; -print $langs->trans("OnlyActiveElementsAreExposed", DOL_URL_ROOT.'/admin/modules.php'); - - -llxFooter(); -$db->close(); From a4ca16db32afccd28176194f982b779dfa0fbf6c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 26 Mar 2021 14:48:14 +0100 Subject: [PATCH 77/79] Doc --- htdocs/api/admin/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/api/admin/index.php b/htdocs/api/admin/index.php index 45fa87a2e77..3299435a10d 100644 --- a/htdocs/api/admin/index.php +++ b/htdocs/api/admin/index.php @@ -152,7 +152,7 @@ if (dol_is_dir(DOL_DOCUMENT_ROOT.'/includes/restler/framework/Luracast/Restler/e $url = DOL_MAIN_URL_ROOT.'/api/index.php/explorer'; print img_picto('', 'globe').' '.$url."
\n"; print '

'.$langs->trans("SwaggerDescriptionFile").':
'; - $urlswagger = DOL_MAIN_URL_ROOT.'/api/index.php/explorer/swagger.json?DOLAPIKEY=useauserapikey'; + $urlswagger = DOL_MAIN_URL_ROOT.'/api/index.php/explorer/swagger.json?DOLAPIKEY=youruserapikey'; print img_picto('', 'globe').' '.$urlswagger."
\n"; print '
'; } else { From 3a5f130ed578b9f080e4afb747bae7f4956ac76c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 26 Mar 2021 14:54:12 +0100 Subject: [PATCH 78/79] Add protections --- htdocs/api/admin/explorer_withredoc.php | 32 +++++++++++++++++++++++++ htdocs/api/index.php | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/htdocs/api/admin/explorer_withredoc.php b/htdocs/api/admin/explorer_withredoc.php index 08711abede2..45dd31d57c9 100644 --- a/htdocs/api/admin/explorer_withredoc.php +++ b/htdocs/api/admin/explorer_withredoc.php @@ -26,6 +26,38 @@ require_once '../../main.inc.php'; +// Enable and test if module Api is enabled +if (empty($conf->global->MAIN_MODULE_API)) { + $langs->load("admin"); + dol_syslog("Call of Dolibarr API interfaces with module API REST are disabled"); + print $langs->trans("WarningModuleNotActive", 'Api').'.

'; + print $langs->trans("ToActivateModule"); + //session_destroy(); + exit(0); +} + +// Test if explorer is not disabled +if (!empty($conf->global->API_EXPLORER_DISABLED)) { + $langs->load("admin"); + dol_syslog("Call Dolibarr API interfaces with module REST disabled"); + print $langs->trans("WarningAPIExplorerDisabled").'.

'; + //session_destroy(); + exit(0); +} + +// Restrict API to some IPs +if (!empty($conf->global->API_RESTRICT_ON_IP)) { + $allowedip = explode(' ', $conf->global->API_RESTRICT_ON_IP); + $ipremote = getUserRemoteIP(); + if (!in_array($ipremote, $allowedip)) { + dol_syslog('Remote ip is '.$ipremote.', not into list '.$conf->global->API_RESTRICT_ON_IP); + print 'APIs are not allowed from the IP '.$ipremote; + header('HTTP/1.1 503 API not allowed from your IP '.$ipremote); + //session_destroy(); + exit(0); + } +} + ?> diff --git a/htdocs/api/index.php b/htdocs/api/index.php index 880d3263aaa..89b5a696462 100644 --- a/htdocs/api/index.php +++ b/htdocs/api/index.php @@ -95,7 +95,7 @@ if (!empty($conf->global->MAIN_NGINX_FIX)) { // Enable and test if module Api is enabled if (empty($conf->global->MAIN_MODULE_API)) { $langs->load("admin"); - dol_syslog("Call Dolibarr API interfaces with module REST disabled"); + dol_syslog("Call of Dolibarr API interfaces with module API REST are disabled"); print $langs->trans("WarningModuleNotActive", 'Api').'.

'; print $langs->trans("ToActivateModule"); //session_destroy(); From 4a22c8e87e4aea7973711056e779abfa674fa2bb Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 26 Mar 2021 15:12:39 +0100 Subject: [PATCH 79/79] CSS --- htdocs/api/admin/index.php | 6 +++--- htdocs/theme/eldy/global.inc.php | 13 +++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/htdocs/api/admin/index.php b/htdocs/api/admin/index.php index 3299435a10d..05f372a3486 100644 --- a/htdocs/api/admin/index.php +++ b/htdocs/api/admin/index.php @@ -141,7 +141,7 @@ $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domai $message = ''; $url = $urlwithroot.'/api/index.php/login?login=auserlogin&password=thepassword[&reset=1]'; $message .= ''.$langs->trans("UrlToGetKeyToUseAPIs").':
'; -$message .= img_picto('', 'globe').' '.$url; +$message .= ''; print $message; print '
'; print '
'; @@ -150,10 +150,10 @@ print '
'; print ''.$langs->trans("ApiExporerIs").':
'; if (dol_is_dir(DOL_DOCUMENT_ROOT.'/includes/restler/framework/Luracast/Restler/explorer')) { $url = DOL_MAIN_URL_ROOT.'/api/index.php/explorer'; - print img_picto('', 'globe').' '.$url."
\n"; + print '
\n"; print '

'.$langs->trans("SwaggerDescriptionFile").':
'; $urlswagger = DOL_MAIN_URL_ROOT.'/api/index.php/explorer/swagger.json?DOLAPIKEY=youruserapikey'; - print img_picto('', 'globe').' '.$urlswagger."
\n"; + print '
\n"; print '
'; } else { $langs->load("errors"); diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index f14c7bba87f..62d040f2aff 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -767,6 +767,19 @@ textarea.centpercent { max-width: 100%; overflow-y: auto; } +div.urllink { + padding: 10px; + margin-top: 5px; + margin-bottom: 5px; + //border: 1px solid #ccc; + border-radius: 5px; + width: fit-content; + background-color: #eee; + opacity: 0.8; +} +div.urllink, div.urllink a { + color: #339 !important; +} i.fa-mars::before, i.fa-venus::before, i.fa-genderless::before { color: #888 !important;