diff --git a/ChangeLog b/ChangeLog index 9cd6f11d1b8..3cfc257bbb2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,12 +2,134 @@ English Dolibarr ChangeLog -------------------------------------------------------------- + +***** ChangeLog for 7.0.0 compared to 6.0.* ***** + + + ***** ChangeLog for 6.0.0 compared to 5.0.* ***** +NEW: Add experimental BlockeLog module (to log business events in a non reversible log file). +NEW: Add a payment module for Stripe. +NEW: Add module "Product variant" (like red, blue for the product shoes) +NEW: Accountancy - Activate multi-journal & Add journal_label to database (FEC) +NEW: Add a tracking id into mass emailing. +NEW: Tax system more compatible with the new tax roollout in India (IGST / CGST / SGST). +NEW: Add calculation function for Loan schedule +NEW: Add "depends on" and "required by" into module informations +NEW: Add hidden option THIRDPARTY_INCLUDE_PARENT_IN_LINKTO +NEW: Add key __USERID__ and __ENTITYID__ as key for dynamic filters. +NEW: Add last activation author and ip of modules +NEW: Add mass actions (pdf merge and delete) for interventions +NEW: Add module resources import/export +NEW: Add option PROJECT_THIRDPARTY_REQUIRED +NEW: Add page statistics for project tasks +NEW: add property to show warnings when activating modules +NEW: add rapport file for supplier paiement +NEW: Add statistics on supplier tab. +NEW: Add tooltip help on shipment weight and volume calculation +NEW: An external module can hook and add mass actions +NEW: Better reponsive design +NEW: Bookmarks are into a combo list. +NEW: Bulk actions available on supplier orders +NEW: Can add a background image on login page +NEW: Can change customer from POS +NEW: Can clone expense report on another user +NEW: Can control constants values into file integrity checker +NEW: Can define default values for create forms. +NEW: Can define default filters for list pages. +NEW: Can define default sort order for list pages. +NEW: Can deploy an external module from the module setup area. +NEW: Can disable all overwrote translations in one click. +NEW: Can edit background color for odd and even lines in tables +NEW: Can filter on code in dictionnaries +NEW: Can filter on year and product tags on the product statistic page +NEW: Can import users +NEW: Can read time spent of others (hierarchy only or all if granted) +NEW: Can send an email to a user from its card. +NEW: Can send email to multiple destinaries from the mailform combo list. +NEW: Can set margins of PDFs +NEW: Can set number of dump to keep with job "local database backup" +NEW: Can sort customer balance summary on date. +NEW: Can sort thumbs visible on product card. +NEW: Can use a credit note into a "down payment/deposit". +NEW: Can use dol_fiche_end without showing bottom border. +NEW: Can use translations into all substitutions (watermark, freetext...) +NEW: Change to allow a specific numbering rule for invoice with POS module. +NEW: convert exceiss received to reduc +NEW: custom dir is enabled dy default on first install. +NEW: Description of feature of a module visible into a dedicated popup. +NEW: Direct open of card after a search if one record only found. +NEW: download button +NEW: Enable bulk actions delete on supplier invoices. +NEW: Extrafields support formulas to be computed using PHP expressions. +NEW: Feature to crop/resize images available on user and expense reports. +NEW: Filechecker can include custom dir and report added files. +NEW: fix listview class and add a demo for product list +NEW: [FP17] Accountancy - Add select field in list of accounts +NEW: get amount base on hourly rate for ficheinter +NEW: hidden Easter egg to display commitstrip strip on login page +NEW: Include an hourglass icon when we click on online payment button +NEW: Index upload files into database. +NEW: Introduce mass action on product list ('delete' for the moment) +NEW: Introduce mass actions on contacts +NEW: Introduce option MAIN_HTTP_CONTENT_SECURITY_POLICY +NEW: It's easier to switch between sandbox and live for paypal +NEW: Mass action delete available on project and tasks +NEW: Move login information on home page into a widget +NEW: new demo entry page +NEW: No external check of version without explicit click in about page. +NEW: ODT docs for USER USERGROUP CONTRACT and PRODUCT class +NEW: odt usergroup +NEW: On invoices generated by template, we save if invoice come from a source template. +NEW: option to copy into attachement files of events, files send by mail (with auto event creation) +NEW: PDF with numbertoword +NEW: Permit multiple file upload in linked documents +NEW: PHP 7.1 compatibility +NEW: Reduce memory usage by removing deprecated constant loading. +NEW: Report page and menu for suppliers paiements +NEW: Show by default README.md file found into root dir of ext module. +NEW: Show company into combo list of projects +NEW: show files in the bank statement + download +NEW: Show local taxes in facture list +NEW: Show local taxes in supplier facture list +NEW: Small PDF template for products +NEW: Option SUPPLIER_ORDER_EDIT_BUYINGPRICE_DURING_RECEIPT +NEW: The substitution keys available for emailing edition are now visible into a popup. +NEW: Uniformize behaviour: Action to make order is an action button. +NEW: Use autocompletion on the "Add widget list". +NEW: Use html5 type "number" on select field for year and duration. +NEW: Can use pdktk to concat mass pdf because tcpdf generate avoid to split large file into multiple smaller file (all have same size) encounter issue with mailer provider virtual delivery service +NEW: Default theme of v6 is cleaner. +NEW: When down payment is entered, discount to reuse into final invoice is automatically created. This save one click into invoice workflow. +NEW: Add UI to configure MEMBER_NEWFORM_FORCETYPE +NEW: #2763 Go to document block after clicking in Generate document button +NEW: #6280: Generate PDF after creating an invoice from a customer order +NEW: #6915 Simplest change. +NEW: Uniformize the look and feel with v6 new look. + For developers: NEW: Add a lot of API REST: dictionaryevents, memberstypes, ... NEW: Big refactorization of multicompany transverse mode. NEW: getEntity function use true $shared value by default. +NEW: Add font-awesome css. +NEW: Add function ajax_autoselect +NEW: Add function dolMd2Html +NEW: Add hook doUpgrade2 +NEW: Add hook "formatNotificationMessage" +NEW: Add index and constraints keys on supplier proposal detail table +NEW: Add phpunit to check the engine is defined into sql create files. +NEW: Add project and Hook to Loan +NEW: Add REST API to push a file. +NEW: Allow extrafields list select to be dependands on other standard list and not only other extrafields list +NEW: Architecture to manage search criteria persistance (using save_lastsearch_values=1 on exit links and restore_lastsearch_values=1 in entry links) +NEW: data files are now also parsed by phpunit for sql syntax +NEW: Hook to allow inserting custom product head #6001 +NEW: Introduce fields that can be computed during export in export profiles. +NEW: Introduce function dol_compress_dir +NEW: Removed commande_pdf_create, contract_pdf_create,expedition_pdf_create, facture_pdf_create, delivery_order_pdf_create, task_pdf_create, project_pdf_create, propale_pdf_create, supplier_invoice_pdf_create, supplier_order_pdf_create, supplier_proposal_pdf_create deprecated functions +NEW: tooltip can be on hover or on click with textwithpicto function. +NEW: Upgrade jquery to 3.3.1 and jquery-ui to 1.12 WARNING: diff --git a/build/exe/doliwamp/doliwamp.iss b/build/exe/doliwamp/doliwamp.iss index 34757a5123a..2ef8ab32f22 100644 --- a/build/exe/doliwamp/doliwamp.iss +++ b/build/exe/doliwamp/doliwamp.iss @@ -353,10 +353,12 @@ begin begin // TODO Copy file or ask to install package ? //CustomMessage('YouWillInstallDoliWamp')+#13#13 - MsgBox('The package vcredist_x86.exe must have been installed first. It seems it is not. Please install it first from http://www.microsoft.com/en-us/download/details.aspx?id=30679 then restart DoliWamp installation/upgrade.',mbInformation,MB_OK); + MsgBox('The package vcredist_x86.exe must have been installed first. It seems it is not. Please install it first from http://www.microsoft.com/en-us/download/details.aspx?id=30679 then restart DoliWamp installation/upgrade.',mbInformation,MB_OK); end; - - + // Pb seems similar with msvcp110.dll + //vcredist_x64.exe + + // If we have a new database version, we should only copy old my.ini file into new directory // and change only all basedir= strings to use new version. Like this, data dir is still correct. // Install of service and stop/start scripts are already rebuild by installer. diff --git a/build/makepack-dolibarr.pl b/build/makepack-dolibarr.pl index c2d983653cb..1843f3c8cfd 100755 --- a/build/makepack-dolibarr.pl +++ b/build/makepack-dolibarr.pl @@ -592,6 +592,8 @@ if ($nboftargetok) { print "Remove subdir of custom dir\n"; print "find $BUILDROOT/$PROJECT/htdocs/custom/* -type d -exec rm -fr {} \\;\n"; $ret=`find $BUILDROOT/$PROJECT/htdocs/custom/* -type d -exec rm -fr {} \\; >/dev/null 2>&1`; # For custom we want to remove all subdirs but not files + print "find $BUILDROOT/$PROJECT/htdocs/custom/* -type l -exec rm -fr {} \\;\n"; + $ret=`find $BUILDROOT/$PROJECT/htdocs/custom/* -type l -exec rm -fr {} \\; >/dev/null 2>&1`; # For custom we want to remove all subdirs, even symbolic links, but not files } # Build package for each target @@ -972,9 +974,11 @@ if ($nboftargetok) { $ret=`$cmd`; $ret=`chmod 755 $BUILDROOT/$PROJECT.tmp/debian/rules`; $ret=`chmod -R 644 $BUILDROOT/$PROJECT.tmp/dev/translation/autotranslator.class.php`; + $ret=`chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/class/actions_mymodule.class.php`; + $ret=`chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/class/api_myobject.class.php`; $ret=`chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/class/myobject.class.php`; - $ret=`chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/class/myobject_api_class.class.php`; $ret=`chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/core/modules/modMyModule.class.php`; + $ret=`chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/mymoduleindex.php`; $ret=`chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/myobject_card.php`; $ret=`chmod -R 644 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/myobject_list.php`; $ret=`chmod -R 755 $BUILDROOT/$PROJECT.tmp/htdocs/modulebuilder/template/scripts/myobject.php`; diff --git a/build/rpm/dolibarr_fedora.spec b/build/rpm/dolibarr_fedora.spec index 33dc951309d..55898481691 100755 --- a/build/rpm/dolibarr_fedora.spec +++ b/build/rpm/dolibarr_fedora.spec @@ -162,6 +162,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/api %_datadir/dolibarr/htdocs/asterisk %_datadir/dolibarr/htdocs/barcode +%_datadir/dolibarr/htdocs/blockedlog %_datadir/dolibarr/htdocs/bookmarks %_datadir/dolibarr/htdocs/cashdesk %_datadir/dolibarr/htdocs/categories diff --git a/build/rpm/dolibarr_generic.spec b/build/rpm/dolibarr_generic.spec index 42a89675abf..e5b346278ab 100755 --- a/build/rpm/dolibarr_generic.spec +++ b/build/rpm/dolibarr_generic.spec @@ -242,6 +242,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/api %_datadir/dolibarr/htdocs/asterisk %_datadir/dolibarr/htdocs/barcode +%_datadir/dolibarr/htdocs/blockedlog %_datadir/dolibarr/htdocs/bookmarks %_datadir/dolibarr/htdocs/cashdesk %_datadir/dolibarr/htdocs/categories diff --git a/build/rpm/dolibarr_mandriva.spec b/build/rpm/dolibarr_mandriva.spec index 9dd2100b02c..04a3138d9f9 100755 --- a/build/rpm/dolibarr_mandriva.spec +++ b/build/rpm/dolibarr_mandriva.spec @@ -159,6 +159,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/api %_datadir/dolibarr/htdocs/asterisk %_datadir/dolibarr/htdocs/barcode +%_datadir/dolibarr/htdocs/blockedlog %_datadir/dolibarr/htdocs/bookmarks %_datadir/dolibarr/htdocs/cashdesk %_datadir/dolibarr/htdocs/categories diff --git a/build/rpm/dolibarr_opensuse.spec b/build/rpm/dolibarr_opensuse.spec index d780c47da99..c77661fe420 100755 --- a/build/rpm/dolibarr_opensuse.spec +++ b/build/rpm/dolibarr_opensuse.spec @@ -170,6 +170,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/api %_datadir/dolibarr/htdocs/asterisk %_datadir/dolibarr/htdocs/barcode +%_datadir/dolibarr/htdocs/blockedlog %_datadir/dolibarr/htdocs/bookmarks %_datadir/dolibarr/htdocs/cashdesk %_datadir/dolibarr/htdocs/categories diff --git a/dev/resources/iso-normes/world_tax_rates.txt b/dev/resources/iso-normes/world_tax_rates.txt index e5bb64a86f2..740062288dc 100644 --- a/dev/resources/iso-normes/world_tax_rates.txt +++ b/dev/resources/iso-normes/world_tax_rates.txt @@ -1 +1,4 @@ -http://www.taxrates.cc/index.html \ No newline at end of file +http://www.taxrates.cc/index.html + +For India: VAT=IGST/CGST=Localtax1/SGST=Localtax2: https://cleartax.in/s/what-is-sgst-cgst-igst + diff --git a/dev/translation/sanity_check_en_langfiles.php b/dev/translation/sanity_check_en_langfiles.php index 9136c192739..f65cefd7f94 100755 --- a/dev/translation/sanity_check_en_langfiles.php +++ b/dev/translation/sanity_check_en_langfiles.php @@ -25,7 +25,7 @@ $path=dirname(__FILE__).'/'; $web=0; // Test if batch mode -if (substr($sapi_type, 0, 3) == 'cgi') +if (substr($sapi_type, 0, 3) == 'cgi') { $web=1; } @@ -35,9 +35,9 @@ if ($web) { echo ""; echo ""; - + echo ""; - + echo ""; } @@ -142,9 +142,9 @@ foreach ($files AS $file) { } } -foreach ($langstrings_3d AS $filename => $file) +foreach ($langstrings_3d AS $filename => $file) { - foreach ($file AS $linenum => $value) + foreach ($file AS $linenum => $value) { $keys = array_keys($langstrings_full, $value); if (count($keys)>1) @@ -173,11 +173,11 @@ $sininstallandadmin=''; $sother=''; $count = 0; -foreach ($dups as $string => $pages) +foreach ($dups as $string => $pages) { $count++; $s=''; - + // Keyword $string if ($web) $s.=""; if ($web) $s.=""; @@ -188,32 +188,32 @@ foreach ($dups as $string => $pages) if ($web) $s.=""; if ($web) $s.=""; if (! $web) $s.= ' : '; - + // Loop on each files keyword was found $duplicateinsamefile=0; $inmain=0; $inadmin=0; - foreach ($pages AS $file => $lines) + foreach ($pages AS $file => $lines) { if ($file == 'main.lang') { $inmain=1; $inadmin=0; } if ($file == 'admin.lang' && ! $inmain) { $inadmin=1; } - + $s.=$file." "; - + // Loop on each line keword was found into file. $listoffilesforthisentry=array(); - foreach ($lines as $line => $translatedvalue) + foreach ($lines as $line => $translatedvalue) { if (! empty($listoffilesforthisentry[$file])) $duplicateinsamefile=1; $listoffilesforthisentry[$file]=1; - + $s.= "(".$line." - ".htmlentities($translatedvalue).") "; } if ($web) $s.="
"; } if ($web) $s.=""; $s.="\n"; - + if ($duplicateinsamefile) $sduplicateinsamefile .= $s; else if ($inmain) $sinmainandother .= $s; else if ($inadmin) $sininstallandadmin .= $s; @@ -252,7 +252,7 @@ if ($web) if ((! empty($_REQUEST['unused']) && $_REQUEST['unused'] == 'true') || (isset($argv[1]) && $argv[1]=='unused=true')) { print "***** Strings in en_US that are never used:\n"; - + $unused=array(); foreach ($langstrings_dist AS $value => $line) { @@ -288,7 +288,7 @@ if ((! empty($_REQUEST['unused']) && $_REQUEST['unused'] == 'true') || (isset($a if (preg_match('/^JuridicalStatus/', $value)) $qualifiedforclean=0; if (preg_match('/^CalcMode/', $value)) $qualifiedforclean=0; if (preg_match('/^newLT/', $value)) $qualifiedforclean=0; - if (preg_match('/^LT\d/', $value)) $qualifiedforclean=0; + if (preg_match('/^LT[0-9]/', $value)) $qualifiedforclean=0; if (preg_match('/^TypeContact_contrat_/', $value)) $qualifiedforclean=0; if (preg_match('/^ErrorPriceExpression/', $value)) $qualifiedforclean=0; if (preg_match('/^Language_/', $value)) $qualifiedforclean=0; @@ -315,7 +315,7 @@ if ((! empty($_REQUEST['unused']) && $_REQUEST['unused'] == 'true') || (isset($a // orders if (preg_match('/^OrderSource/', $value)) $qualifiedforclean=0; if (preg_match('/^TypeContact_/', $value)) $qualifiedforclean=0; - // other.lang + // other.lang if (preg_match('/^Notify_/', $value)) $qualifiedforclean=0; if (preg_match('/^PredefinedMail/', $value)) $qualifiedforclean=0; if (preg_match('/^DemoCompany/', $value)) $qualifiedforclean=0; @@ -336,17 +336,17 @@ if ((! empty($_REQUEST['unused']) && $_REQUEST['unused'] == 'true') || (isset($a if (preg_match('/OppStatus/', $value)) $qualifiedforclean=0; if (preg_match('/AvailabilityType/', $value)) $qualifiedforclean=0; if (preg_match('/CardProduct/', $value)) $qualifiedforclean=0; - + if (preg_match('/sms/i', $value)) $qualifiedforclean=0; if (preg_match('/TF_/i', $value)) $qualifiedforclean=0; if (preg_match('/WithBankUsing/i', $value)) $qualifiedforclean=0; if (preg_match('/descWORKFLOW_/i', $value)) $qualifiedforclean=0; - + if (! $qualifiedforclean) { - continue; + continue; } - + //$search = '\'trans("'.$value.'")\''; $search = '-e "\''.$value.'\'" -e \'"'.$value.'"\' -e "('.$value.')" -e "('.$value.',"'; $string = 'grep -R -m 1 -F --exclude=includes/* --include=*.php '.$search.' '.$htdocs.'* '.$scripts.'*'; @@ -356,7 +356,7 @@ if ((! empty($_REQUEST['unused']) && $_REQUEST['unused'] == 'true') || (isset($a $unused[$value] = $line; echo $line; // $trad contains the \n } - else + else { unset($output); //print 'X'.$output.'Y'; @@ -364,7 +364,7 @@ if ((! empty($_REQUEST['unused']) && $_REQUEST['unused'] == 'true') || (isset($a } if (empty($unused)) print "No string not used found.\n"; - else + else { $filetosave='/tmp/'.($argv[2]?$argv[2]:"").'notused.lang'; print "Strings in en_US that are never used are saved into file ".$filetosave.":\n"; diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index 1431df9f8a2..799ebf85a34 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -71,6 +71,7 @@ class BookKeeping extends CommonObject /** */ public $doc_date; + public $date_lim_reglement; public $doc_type; public $doc_ref; public $fk_doc; @@ -255,6 +256,7 @@ class BookKeeping extends CommonObject $sql = "INSERT INTO " . MAIN_DB_PREFIX . $this->table_element . " ("; $sql .= "doc_date"; + $sql .= ", date_lim_reglement"; $sql .= ", doc_type"; $sql .= ", doc_ref"; $sql .= ", fk_doc"; @@ -277,6 +279,7 @@ class BookKeeping extends CommonObject $sql .= ', entity'; $sql .= ") VALUES ("; $sql .= "'" . $this->db->idate($this->doc_date) . "'"; + $sql .= ",'" . $this->db->idate($this->date_lim_reglement) . "'"; $sql .= ",'" . $this->db->escape($this->doc_type) . "'"; $sql .= ",'" . $this->db->escape($this->doc_ref) . "'"; $sql .= "," . $this->fk_doc; @@ -444,6 +447,7 @@ class BookKeeping extends CommonObject // Insert request $sql = 'INSERT INTO ' . MAIN_DB_PREFIX . $this->table_element . $mode.'('; $sql .= 'doc_date,'; + $sql .= 'date_lim_reglement,'; $sql .= 'doc_type,'; $sql .= 'doc_ref,'; $sql .= 'fk_doc,'; @@ -466,6 +470,7 @@ class BookKeeping extends CommonObject $sql .= 'entity'; $sql .= ') VALUES ('; $sql .= ' ' . (! isset($this->doc_date) || dol_strlen($this->doc_date) == 0 ? 'NULL' : "'" . $this->db->idate($this->doc_date) . "'") . ','; + $sql .= ' ' . (! isset($this->date_lim_reglement) || dol_strlen($this->date_lim_reglement) == 0 ? 'NULL' : "'" . $this->db->idate($this->date_lim_reglement) . "'") . ','; $sql .= ' ' . (! isset($this->doc_type) ? 'NULL' : "'" . $this->db->escape($this->doc_type) . "'") . ','; $sql .= ' ' . (! isset($this->doc_ref) ? 'NULL' : "'" . $this->db->escape($this->doc_ref) . "'") . ','; $sql .= ' ' . (empty($this->fk_doc) ? '0' : $this->fk_doc) . ','; @@ -540,6 +545,7 @@ class BookKeeping extends CommonObject $sql = 'SELECT'; $sql .= ' t.rowid,'; $sql .= " t.doc_date,"; + $sql .= " t.date_lim_reglement,"; $sql .= " t.doc_type,"; $sql .= " t.doc_ref,"; $sql .= " t.fk_doc,"; @@ -577,6 +583,7 @@ class BookKeeping extends CommonObject $this->id = $obj->rowid; $this->doc_date = $this->db->jdate($obj->doc_date); + $this->date_lim_reglement = $this->db->jdate($obj->date_lim_reglement); $this->doc_type = $obj->doc_type; $this->doc_ref = $obj->doc_ref; $this->fk_doc = $obj->fk_doc; @@ -1260,7 +1267,7 @@ class BookKeeping extends CommonObject global $user; $error = 0; - $object = new Accountingbookkeeping($this->db); + $object = new BookKeeping($this->db); $this->db->begin(); diff --git a/htdocs/accountancy/journal/bankjournal.php b/htdocs/accountancy/journal/bankjournal.php index d5746eb63e5..587d36d227a 100644 --- a/htdocs/accountancy/journal/bankjournal.php +++ b/htdocs/accountancy/journal/bankjournal.php @@ -401,7 +401,7 @@ if (! $error && $action == 'writebookkeeping') { $bookkeeping->numero_compte = $k; $bookkeeping->label_operation = $val["label"]; $bookkeeping->label_compte = $langs->trans("Bank"); - $bookkeeping->montant = ($mt < 0 ? - $mt : $mt); + $bookkeeping->montant = $mt; $bookkeeping->sens = ($mt >= 0) ? 'D' : 'C'; $bookkeeping->debit = ($mt >= 0 ? $mt : 0); $bookkeeping->credit = ($mt < 0 ? - $mt : 0); @@ -462,7 +462,7 @@ if (! $error && $action == 'writebookkeeping') { $bookkeeping->fk_doc = $key; $bookkeeping->fk_docdet = $val["fk_bank"]; $bookkeeping->label_operation = $tabcompany[$key]['name']; - $bookkeeping->montant = ($mt < 0 ? - $mt : $mt); + $bookkeeping->montant = $mt; $bookkeeping->sens = ($mt < 0) ? 'D' : 'C'; $bookkeeping->debit = ($mt < 0 ? - $mt : 0); $bookkeeping->credit = ($mt >= 0) ? $mt : 0; diff --git a/htdocs/accountancy/journal/expensereportsjournal.php b/htdocs/accountancy/journal/expensereportsjournal.php index 1907cfe7dae..d253fb2820a 100644 --- a/htdocs/accountancy/journal/expensereportsjournal.php +++ b/htdocs/accountancy/journal/expensereportsjournal.php @@ -203,7 +203,7 @@ if ($action == 'writebookkeeping') { $bookkeeping->label_operation = $tabuser[$key]['name']; $bookkeeping->montant = $mt; $bookkeeping->sens = ($mt >= 0) ? 'C' : 'D'; - $bookkeeping->debit = ($mt <= 0) ? $mt : 0; + $bookkeeping->debit = ($mt <= 0) ? -$mt : 0; $bookkeeping->credit = ($mt > 0) ? $mt : 0; $bookkeeping->code_journal = $journal; $bookkeeping->journal_label = $journal_label; diff --git a/htdocs/accountancy/journal/purchasesjournal.php b/htdocs/accountancy/journal/purchasesjournal.php index 40b9033002c..b095e4650dc 100644 --- a/htdocs/accountancy/journal/purchasesjournal.php +++ b/htdocs/accountancy/journal/purchasesjournal.php @@ -85,7 +85,7 @@ if (empty($date_start) || empty($date_end)) // We define date_start and date_end $idpays = $mysoc->country_id; -$sql = "SELECT f.rowid, f.ref, f.type, f.datef as df, f.libelle,f.ref_supplier,"; +$sql = "SELECT f.rowid, f.ref, f.type, f.datef as df, f.libelle,f.ref_supplier, f.date_lim_reglement as dlf, "; $sql .= " fd.rowid as fdid, fd.description, fd.product_type, fd.total_ht, fd.tva as total_tva, fd.total_localtax1, fd.total_localtax2, fd.tva_tx, fd.total_ttc, fd.vat_src_code,"; $sql .= " s.rowid as socid, s.nom as name, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,"; $sql .= " p.accountancy_code_buy , aa.rowid as fk_compte, aa.account_number as compte, aa.label as label_compte"; @@ -155,6 +155,7 @@ if ($result) { } $tabfac[$obj->rowid]["date"] = $db->jdate($obj->df); + $tabfac[$obj->rowid]["datereg"] = $db->jdate($obj->dlr); $tabfac[$obj->rowid]["ref"] = $obj->ref_supplier . ' (' . $obj->ref . ')'; $tabfac[$obj->rowid]["refsologest"] = $obj->ref; $tabfac[$obj->rowid]["refsuppliersologest"] = $obj->ref_supplier; @@ -222,6 +223,7 @@ if ($action == 'writebookkeeping') { if ($mt) { $bookkeeping = new BookKeeping($db); $bookkeeping->doc_date = $val["date"]; + $bookkeeping->date_lim_reglement = $val["datereg"]; $bookkeeping->doc_ref = $val["ref"]; $bookkeeping->date_create = $now; $bookkeeping->doc_type = 'supplier_invoice'; @@ -269,6 +271,7 @@ if ($action == 'writebookkeeping') { if ($accountingaccount->fetch(null, $k, true)) { $bookkeeping = new BookKeeping($db); $bookkeeping->doc_date = $val["date"]; + $bookkeeping->date_lim_reglement = $val["datereg"]; $bookkeeping->doc_ref = $val["ref"]; $bookkeeping->date_create = $now; $bookkeeping->doc_type = 'supplier_invoice'; @@ -322,6 +325,7 @@ if ($action == 'writebookkeeping') { if ($mt) { $bookkeeping = new BookKeeping($db); $bookkeeping->doc_date = $val["date"]; + $bookkeeping->date_lim_reglement = $val["datereg"]; $bookkeeping->doc_ref = $val["ref"]; $bookkeeping->date_create = $now; $bookkeeping->doc_type = 'supplier_invoice'; diff --git a/htdocs/accountancy/journal/sellsjournal.php b/htdocs/accountancy/journal/sellsjournal.php index 4300b91eca6..c03c800f5d6 100644 --- a/htdocs/accountancy/journal/sellsjournal.php +++ b/htdocs/accountancy/journal/sellsjournal.php @@ -89,7 +89,7 @@ if (empty($date_start) || empty($date_end)) // We define date_start and date_end $idpays = $mysoc->country_id; -$sql = "SELECT f.rowid, f.facnumber, f.type, f.datef as df, f.ref_client,"; +$sql = "SELECT f.rowid, f.facnumber, f.type, f.datef as df, f.ref_client, f.date_lim_reglement as dlr,"; $sql .= " fd.rowid as fdid, fd.description, fd.product_type, fd.total_ht, fd.total_tva, fd.total_localtax1, fd.total_localtax2, fd.tva_tx, fd.total_ttc, fd.situation_percent, fd.vat_src_code,"; $sql .= " s.rowid as socid, s.nom as name, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,"; $sql .= " p.rowid as pid, p.ref as pref, p.accountancy_code_sell, aa.rowid as fk_compte, aa.account_number as compte, aa.label as label_compte"; @@ -178,6 +178,7 @@ if ($result) { // Invoice lines $tabfac[$obj->rowid]["date"] = $db->jdate($obj->df); + $tabfac[$obj->rowid]["datereg"] = $db->jdate($obj->dlr); $tabfac[$obj->rowid]["ref"] = $obj->facnumber; $tabfac[$obj->rowid]["type"] = $obj->type; $tabfac[$obj->rowid]["description"] = $obj->label_compte; @@ -240,6 +241,7 @@ if ($action == 'writebookkeeping') { if ($mt) { $bookkeeping = new BookKeeping($db); $bookkeeping->doc_date = $val["date"]; + $bookkeeping->date_lim_reglement = $val["datereg"]; $bookkeeping->doc_ref = $val["ref"]; $bookkeeping->date_create = $now; $bookkeeping->doc_type = 'customer_invoice'; @@ -287,6 +289,7 @@ if ($action == 'writebookkeeping') { if ($accountingaccount->fetch(null, $k, true)) { $bookkeeping = new BookKeeping($db); $bookkeeping->doc_date = $val["date"]; + $bookkeeping->date_lim_reglement = $val["datereg"]; $bookkeeping->doc_ref = $val["ref"]; $bookkeeping->date_create = $now; $bookkeeping->doc_type = 'customer_invoice'; @@ -340,6 +343,7 @@ if ($action == 'writebookkeeping') { if ($mt) { $bookkeeping = new BookKeeping($db); $bookkeeping->doc_date = $val["date"]; + $bookkeeping->date_lim_reglement = $val["datereg"]; $bookkeeping->doc_ref = $val["ref"]; $bookkeeping->date_create = $now; $bookkeeping->doc_type = 'customer_invoice'; diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index 72888a8deb3..ae26dce060d 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -249,7 +249,7 @@ $tabfield[6] = "code,libelle,type,color,position"; $tabfield[7] = "code,libelle,country,accountancy_code,deductible"; $tabfield[8] = "code,libelle,country_id,country".(! empty($conf->global->SOCIETE_SORT_ON_TYPEENT)?',position':''); $tabfield[9] = "code,label,unicode"; -$tabfield[10]= "country_id,country,code,taux,recuperableonly,localtax1_type,localtax1,localtax2_type,localtax2,accountancy_code_sell,accountancy_code_buy,note"; +$tabfield[10]= "country_id,country,code,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note"; $tabfield[11]= "element,source,code,libelle,position"; $tabfield[12]= "code,libelle,libelle_facture,nbjour,type_cdr,decalage,sortorder"; $tabfield[13]= "code,libelle,type,accountancy_code"; @@ -286,7 +286,7 @@ $tabfieldvalue[6] = "code,libelle,type,color,position"; $tabfieldvalue[7] = "code,libelle,country,accountancy_code,deductible"; $tabfieldvalue[8] = "code,libelle,country".(! empty($conf->global->SOCIETE_SORT_ON_TYPEENT)?',position':''); $tabfieldvalue[9] = "code,label,unicode"; -$tabfieldvalue[10]= "country,code,taux,recuperableonly,localtax1_type,localtax1,localtax2_type,localtax2,accountancy_code_sell,accountancy_code_buy,note"; +$tabfieldvalue[10]= "country,code,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note"; $tabfieldvalue[11]= "element,source,code,libelle,position"; $tabfieldvalue[12]= "code,libelle,libelle_facture,nbjour,type_cdr,decalage,sortorder"; $tabfieldvalue[13]= "code,libelle,type,accountancy_code"; @@ -323,7 +323,7 @@ $tabfieldinsert[6] = "code,libelle,type,color,position"; $tabfieldinsert[7] = "code,libelle,fk_pays,accountancy_code,deductible"; $tabfieldinsert[8] = "code,libelle,fk_country".(! empty($conf->global->SOCIETE_SORT_ON_TYPEENT)?',position':''); $tabfieldinsert[9] = "code_iso,label,unicode"; -$tabfieldinsert[10]= "fk_pays,code,taux,recuperableonly,localtax1_type,localtax1,localtax2_type,localtax2,accountancy_code_sell,accountancy_code_buy,note"; +$tabfieldinsert[10]= "fk_pays,code,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note"; $tabfieldinsert[11]= "element,source,code,libelle,position"; $tabfieldinsert[12]= "code,libelle,libelle_facture,nbjour,type_cdr,decalage,sortorder"; $tabfieldinsert[13]= "code,libelle,type,accountancy_code"; diff --git a/htdocs/admin/multicurrency.php b/htdocs/admin/multicurrency.php index 0229f4fc150..c6d00501015 100644 --- a/htdocs/admin/multicurrency.php +++ b/htdocs/admin/multicurrency.php @@ -100,7 +100,7 @@ elseif ($action == 'update_currency') if ($submit == $langs->trans('Modify')) { $fk_multicurrency = GETPOST('fk_multicurrency', 'int'); - $rate = GETPOST('rate', 'float'); + $rate = price2num(GETPOST('rate', 'alpha')); $currency = new MultiCurrency($db); if ($currency->fetch($fk_multicurrency) > 0) diff --git a/htdocs/admin/websites.php b/htdocs/admin/websites.php index ee75a811347..e25878b3aaa 100644 --- a/htdocs/admin/websites.php +++ b/htdocs/admin/websites.php @@ -114,7 +114,7 @@ $tabfieldcheck[1] = array(); $elementList = array(); $sourceList=array(); -// Actions add or modify an entry into a dictionary +// Actions add or modify a website if (GETPOST('actionadd','alpha') || GETPOST('actionmodify','alpha')) { $listfield=explode(',',$tabfield[$id]); @@ -133,7 +133,7 @@ if (GETPOST('actionadd','alpha') || GETPOST('actionmodify','alpha')) $fieldnamekey=$listfield[$f]; setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->transnoentities($fieldnamekey)), null, 'errors'); } - if ($value == 'ref' && (preg_match('/[a-zA-Z0-9]/', $_POST[$value]))) + if ($value == 'ref' && ! preg_match('/^[a-z0-9]+$/i', $_POST[$value])) { $ok=0; $fieldnamekey=$listfield[$f]; @@ -141,6 +141,12 @@ if (GETPOST('actionadd','alpha') || GETPOST('actionmodify','alpha')) } } + // Clean parameters + if (! empty($_POST['ref'])) + { + $websitekey=strtolower($_POST['ref']); + } + // Si verif ok et action add, on ajoute la ligne if ($ok && GETPOST('actionadd','alpha')) { @@ -160,6 +166,12 @@ if (GETPOST('actionadd','alpha') || GETPOST('actionmodify','alpha')) } } + /* $website=new Website($db); + $website->ref= + $website->description= + $website->virtualhost= + $website->create($user); */ + // Add new entry $sql = "INSERT INTO ".$tabname[$id]." ("; // List of fields @@ -178,6 +190,9 @@ if (GETPOST('actionadd','alpha') || GETPOST('actionmodify','alpha')) if ($value == 'entity') { $_POST[$listfieldvalue[$i]] = $conf->entity; } + if ($value == 'ref') { + $_POST[$listfieldvalue[$i]] = strtolower($_POST[$listfieldvalue[$i]]); + } if ($i) $sql.=","; if ($_POST[$listfieldvalue[$i]] == '') $sql.="null"; else $sql.="'".$db->escape($_POST[$listfieldvalue[$i]])."'"; @@ -189,6 +204,29 @@ if (GETPOST('actionadd','alpha') || GETPOST('actionmodify','alpha')) $result = $db->query($sql); if ($result) // Add is ok { + global $dolibarr_main_data_root; + $pathofwebsite=$dolibarr_main_data_root.'/websites/'.$websitekey; + $filehtmlheader=$pathofwebsite.'/htmlheader.html'; + $filecss=$pathofwebsite.'/styles.css.php'; + $filetpl=$pathofwebsite.'/page'.$pageid.'.tpl.php'; + $fileindex=$pathofwebsite.'/index.php'; + + // Css file + $csscontent = ''."\n"; + $csscontent.= ''."\n"; + $csscontent.= '"."\n"; + $csscontent.= ''."\n"; + $csscontent.= 'body { margin: 0; }'."\n"; + + dol_syslog("Save file css into ".$filecss); + + dol_mkdir($pathofwebsite); + $result = file_put_contents($filecss, $csscontent); + if (! empty($conf->global->MAIN_UMASK)) + @chmod($filecss, octdec($conf->global->MAIN_UMASK)); + setEventMessages($langs->transnoentities("RecordSaved"), null, 'mesgs'); unset($_POST); // Clean $_POST array, we keep only } @@ -400,7 +438,11 @@ if ($id) { print ''; if (! empty($tabhelp[$id][$value]) && preg_match('/^http(s*):/i',$tabhelp[$id][$value])) print ''.$valuetoshow.' '.img_help(1,$valuetoshow).''; - else if (! empty($tabhelp[$id][$value])) print $form->textwithpicto($valuetoshow,$tabhelp[$id][$value]); + elseif (! empty($tabhelp[$id][$value])) + { + if ($value == 'virtualhost') print $form->textwithpicto($valuetoshow, $tabhelp[$id][$value], 1, 'help', '', 0, 2, 'tooltipvirtual'); + else print $form->textwithpicto($valuetoshow, $tabhelp[$id][$value]); + } else print $valuetoshow; print ''; } diff --git a/htdocs/categories/class/categorie.class.php b/htdocs/categories/class/categorie.class.php index ecf95c5096d..d1b8975eaf4 100644 --- a/htdocs/categories/class/categorie.class.php +++ b/htdocs/categories/class/categorie.class.php @@ -42,24 +42,24 @@ require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; */ class Categorie extends CommonObject { - // Categories types - const TYPE_PRODUCT = 0; // TODO Replace with value 'product' - const TYPE_SUPPLIER = 1; // TODO Replace this value with 'supplier' - const TYPE_CUSTOMER = 2; // TODO Replace this value with 'customer' - const TYPE_MEMBER = 3; // TODO Replace this value with 'member' - const TYPE_CONTACT = 4; // TODO Replace this value with 'contact' - const TYPE_USER = 4; // categorie contact and user are same ! TODO Replace this value with 'user' - - const TYPE_ACCOUNT = 5; // TODO Replace this value with 'bank_account' - const TYPE_PROJECT = 6; // TODO Replace this value with 'project' + // Categories types (we use string because we want to accept any modules/types in a future) + const TYPE_PRODUCT = 'product'; + const TYPE_SUPPLIER = 'supplier'; + const TYPE_CUSTOMER = 'customer'; + const TYPE_MEMBER = 'member'; + const TYPE_CONTACT = 'contact'; + const TYPE_USER = 'user'; + const TYPE_PROJECT = 'project'; + const TYPE_ACCOUNT = 'bank_account'; const TYPE_BANK_LINE = 'bank_line'; + public $picto = 'category'; /** * @var array ID mapping from type string * - * @note This array should be remove in future, once previous constants are moved to the string value. + * @note This array should be remove in future, once previous constants are moved to the string value. Deprecated */ private $MAP_ID = array( 'product' => 0, @@ -67,10 +67,21 @@ class Categorie extends CommonObject 'customer' => 2, 'member' => 3, 'contact' => 4, - 'user' => 4, 'account' => 5, 'project' => 6, + 'user' => 7, ); + public static $MAP_ID_TO_CODE = array( + 0 => 'product', + 1 => 'supplier', + 2 => 'customer', + 3 => 'member', + 4 => 'contact', + 5 => 'account', + 6 => 'project', + 7 => 'user', + ); + /** * @var array Foreign keys mapping from type string * @@ -82,9 +93,9 @@ class Categorie extends CommonObject 'supplier' => 'soc', 'member' => 'member', 'contact' => 'socpeople', - 'user' => 'user', - 'account' => 'account', - 'project' => 'project', + 'user' => 'user', + 'account' => 'account', + 'project' => 'project', ); /** * @var array Category tables mapping from type string @@ -97,9 +108,9 @@ class Categorie extends CommonObject 'supplier' => 'fournisseur', 'member' => 'member', 'contact' => 'contact', - 'user' => 'user', - 'account' => 'account', - 'project' => 'project', + 'user' => 'user', + 'account' => 'account', + 'project' => 'project', ); /** * @var array Object class mapping from type string @@ -113,8 +124,8 @@ class Categorie extends CommonObject 'member' => 'Adherent', 'contact' => 'Contact', 'user' => 'User', - 'account' => 'Account', - 'project' => 'Project', + 'account' => 'Account', + 'project' => 'Project', ); /** * @var array Object table mapping from type string @@ -128,8 +139,8 @@ class Categorie extends CommonObject 'member' => 'adherent', 'contact' => 'socpeople', 'user' => 'user', - 'account' => 'bank_account', - 'project' => 'projet', + 'account' => 'bank_account', + 'project' => 'projet', ); public $element='category'; @@ -178,15 +189,16 @@ class Categorie extends CommonObject * * @param int $id Id of category * @param string $label Label of category - * @param string $type Type of category + * @param string $type Type of category ('product', '...') or (0, 1, ...) * @return int <0 if KO, >0 if OK */ - function fetch($id,$label='',$type='') + function fetch($id, $label='', $type=null) { global $conf; // Check parameters if (empty($id) && empty($label)) return -1; + if (! is_numeric($type)) $type=$this->MAP_ID[$type]; $sql = "SELECT rowid, fk_parent, entity, label, description, color, fk_soc, visible, type"; $sql.= " FROM ".MAIN_DB_PREFIX."categorie"; @@ -197,7 +209,7 @@ class Categorie extends CommonObject else { $sql.= " WHERE label = '".$this->db->escape($label)."' AND entity IN (".getEntity('category').")"; - if ($type) $sql.= " AND type = '".$this->db->escape($type)."'"; + if (! is_null($type)) $sql.= " AND type = ".$this->db->escape($type); } dol_syslog(get_class($this)."::fetch", LOG_DEBUG); @@ -254,6 +266,10 @@ class Categorie extends CommonObject global $conf,$langs,$hookmanager; $langs->load('categories'); + $type=$this->type; + + if (! is_numeric($type)) $type=$this->MAP_ID[$type]; + $error=0; dol_syslog(get_class($this).'::create', LOG_DEBUG); @@ -299,7 +315,7 @@ class Categorie extends CommonObject $sql.= ($this->socid != -1 ? $this->socid : 'null').","; } $sql.= "'".$this->visible."',"; - $sql.= $this->type.","; + $sql.= $type.","; $sql.= (! empty($this->import_key)?"'".$this->db->escape($this->import_key)."'":'null').","; $sql.= $conf->entity; $sql.= ")"; @@ -618,12 +634,11 @@ class Categorie extends CommonObject /** * Link an object to the category * - * @param CommonObject $obj Object to link to category - * @param string $type Type of category ('customer', 'supplier', 'contact', 'product', 'member') - * - * @return int 1 : OK, -1 : erreur SQL, -2 : id not defined, -3 : Already linked + * @param CommonObject $obj Object to link to category + * @param string $type Type of category ('product', ...) + * @return int 1 : OK, -1 : erreur SQL, -2 : id not defined, -3 : Already linked */ - function add_type($obj,$type) + function add_type($obj, $type) { global $user,$langs,$conf; @@ -840,13 +855,12 @@ class Categorie extends CommonObject /** * Check for the presence of an object in a category * - * @param string $type Type of category ('customer', 'supplier', 'contact', 'product', 'member') - * @param int $object_id id of the object to search - * - * @return int number of occurrences + * @param string $type Type of category ('customer', 'supplier', 'contact', 'product', 'member') + * @param int $object_id Id of the object to search + * @return int Number of occurrences * @see getObjectsInCateg */ - function containsObject($type, $object_id ) + function containsObject($type, $object_id) { $sql = "SELECT COUNT(*) as nb FROM " . MAIN_DB_PREFIX . "categorie_" . $this->MAP_CAT_TABLE[$type]; $sql .= " WHERE fk_categorie = " . $this->id . " AND fk_" . $this->MAP_CAT_FK[$type] . " = " . $object_id; @@ -933,24 +947,16 @@ class Categorie extends CommonObject * fulllabel = nom avec chemin complet de la categorie * fullpath = chemin complet compose des id * - * @param string $type Type of categories ('customer', 'supplier', 'contact', 'product', 'member'). - * Old mode (0, 1, 2, ...) is deprecated. - * @param int $markafterid Removed all categories including the leaf $markafterid in category tree. + * @param string $type Type of categories ('customer', 'supplier', 'contact', 'product', 'member') or (0, 1, 2, ...). + * @param int $markafterid Removed all categories including the leaf $markafterid in category tree. * - * @return array Array of categories. this->cats and this->motherof are set. + * @return array Array of categories. this->cats and this->motherof are set. */ function get_full_arbo($type, $markafterid=0) { global $conf, $langs; - // For backward compatibility - if (is_numeric($type)) - { - // We want to reverse lookup - $map_type = array_flip($this->MAP_ID); - $type = $map_type[$type]; - dol_syslog( get_class( $this ) . "::get_full_arbo(): numeric types are deprecated, please use string instead", LOG_WARNING); - } + if (! is_numeric($type)) $type = $this->MAP_ID[$type]; $this->cats = array(); @@ -964,7 +970,7 @@ class Categorie extends CommonObject $sql.= " FROM ".MAIN_DB_PREFIX."categorie as c"; if (! empty($conf->global->MAIN_MULTILANGS)) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."categorie_lang as t ON t.fk_category=c.rowid AND t.lang='".$current_lang."'"; $sql .= " WHERE c.entity IN (" . getEntity( 'category', 1 ) . ")"; - $sql .= " AND c.type = " . $this->MAP_ID[$type]; + $sql .= " AND c.type = " . $type; dol_syslog(get_class($this)."::get_full_arbo get category list", LOG_DEBUG); $resql = $this->db->query($sql); @@ -1088,7 +1094,7 @@ class Categorie extends CommonObject /** * Returns all categories * - * @param int $type Type of category + * @param int $type Type of category (0, 1, ...) * @param boolean $parent Just parent categories if true * @return array Table of Object Category */ @@ -1151,13 +1157,17 @@ class Categorie extends CommonObject */ function already_exists() { + $type=$this->type; + + if (! is_numeric($type)) $type=$this->MAP_ID[$type]; + /* We have to select any rowid from llx_categorie which category's mother and label * are equals to those of the calling category */ $sql = "SELECT c.rowid"; $sql.= " FROM ".MAIN_DB_PREFIX."categorie as c "; $sql.= " WHERE c.entity IN (".getEntity('category').")"; - $sql.= " AND c.type = ".$this->type; + $sql.= " AND c.type = ".$type; $sql.= " AND c.fk_parent = ".$this->fk_parent; $sql.= " AND c.label = '".$this->db->escape($this->label)."'"; @@ -1192,7 +1202,7 @@ class Categorie extends CommonObject /** * Returns the top level categories (which are not girls) * - * @param int $type Type of category + * @param int $type Type of category (0, 1, ...) * @return array */ function get_main_categories($type=null) @@ -1330,24 +1340,17 @@ class Categorie extends CommonObject * Return list of categories (object instances or labels) linked to element of id $id and type $type * Should be named getListOfCategForObject * - * @param int $id Id of element - * @param string $type Type of category ('customer', 'supplier', 'contact', 'product', 'member'). Old mode (0, 1, 2, ...) is deprecated. - * @param string $mode 'id'=Get array of category ids, 'object'=Get array of fetched category instances, 'label'=Get array of category - * labels, 'id'= Get array of category IDs - * @return mixed Array of category objects or < 0 if KO + * @param int $id Id of element + * @param int $type Type of category ('customer', 'supplier', 'contact', 'product', 'member') or (0, 1, 2, ...) + * @param string $mode 'id'=Get array of category ids, 'object'=Get array of fetched category instances, 'label'=Get array of category + * labels, 'id'= Get array of category IDs + * @return mixed Array of category objects or < 0 if KO */ function containing($id, $type, $mode='object') { $cats = array(); - // For backward compatibility - if (is_numeric($type)) - { - dol_syslog(__METHOD__ . ': using numeric value for parameter type is deprecated. Use string code instead.', LOG_WARNING); - // We want to reverse lookup - $map_type = array_flip($this->MAP_ID); - $type = $map_type[$type]; - } + if (is_numeric($type)) $type = Categorie::$MAP_ID_TO_CODE[$type]; if ($type == Categorie::TYPE_BANK_LINE) // TODO Remove this with standard category code { diff --git a/htdocs/categories/index.php b/htdocs/categories/index.php index ea4d60e9b5b..c751fad67a7 100644 --- a/htdocs/categories/index.php +++ b/htdocs/categories/index.php @@ -39,6 +39,8 @@ $id=GETPOST('id','int'); $type=(GETPOST('type','aZ09') ? GETPOST('type','aZ09') : Categorie::TYPE_PRODUCT); $catname=GETPOST('catname','alpha'); +if (is_numeric($type)) $type=Categorie::$MAP_ID_TO_CODE[$type]; // For backward compatibility + /* * View @@ -53,8 +55,8 @@ elseif ($type == Categorie::TYPE_CUSTOMER) { $title=$langs->trans("CustomersCat elseif ($type == Categorie::TYPE_MEMBER) { $title=$langs->trans("MembersCategoriesArea"); $typetext='member'; } elseif ($type == Categorie::TYPE_CONTACT) { $title=$langs->trans("ContactsCategoriesArea"); $typetext='contact'; } elseif ($type == Categorie::TYPE_ACCOUNT) { $title=$langs->trans("AccountsCategoriesArea"); $typetext='account'; } -elseif ($type == Categorie::TYPE_USER) { $title=$langs->trans("UsersCategoriesArea"); $typetext='user'; } elseif ($type == Categorie::TYPE_PROJECT) { $title=$langs->trans("ProjectsCategoriesArea"); $typetext='project'; } +elseif ($type == Categorie::TYPE_USER) { $title=$langs->trans("UsersCategoriesArea"); $typetext='user'; } else { $title=$langs->trans("CategoriesArea"); $typetext='unknown'; } $arrayofjs=array('/includes/jquery/plugins/jquerytreeview/jquery.treeview.js', '/includes/jquery/plugins/jquerytreeview/lib/jquery.cookie.js'); diff --git a/htdocs/categories/photos.php b/htdocs/categories/photos.php index e99e081e015..e6047ed2149 100644 --- a/htdocs/categories/photos.php +++ b/htdocs/categories/photos.php @@ -42,6 +42,8 @@ $type=GETPOST('type'); $action=GETPOST('action','aZ09'); $confirm=GETPOST('confirm'); +if (is_numeric($type)) $type=Categorie::$MAP_ID_TO_CODE[$type]; // For backward compatibility + if ($id == "") { dol_print_error('','Missing parameter id'); @@ -100,15 +102,16 @@ if ($object->id) elseif ($type == Categorie::TYPE_CONTACT) $title=$langs->trans("ContactCategoriesShort"); elseif ($type == Categorie::TYPE_ACCOUNT) $title=$langs->trans("AccountsCategoriesShort"); elseif ($type == Categorie::TYPE_PROJECT) $title=$langs->trans("ProjectsCategoriesShort"); - else $title=$langs->trans("Category"); + elseif ($type == Categorie::TYPE_USER) $title=$langs->trans("UsersCategoriesShort"); + else $title=$langs->trans("Category"); $head = categories_prepare_head($object,$type); dol_fiche_head($head, 'photos', $title, -1, 'category'); - + $linkback = ''.$langs->trans("BackToList").''; - + $object->ref = $object->label; $morehtmlref='
'.$langs->trans("Root").' >> '; $ways = $object->print_all_ways(" >> ", '', 1); @@ -117,9 +120,9 @@ if ($object->id) $morehtmlref.=$way."
\n"; } $morehtmlref.='
'; - + dol_banner_tab($object, 'ref', $linkback, ($user->societe_id?0:1), 'ref', 'ref', $morehtmlref, '', 0, '', '', 1); - + /* * Confirmation de la suppression de photo */ @@ -129,7 +132,7 @@ if ($object->id) } print '
'; - + print '
'; print '
'; print ''; @@ -148,7 +151,7 @@ if ($object->id) print "
\n"; print '
'; - + print dol_fiche_end(); @@ -258,7 +261,7 @@ if ($object->id) } print ''; - + if ($nbphoto < 1) { print '
'.$langs->trans("NoPhotoYet")."
"; diff --git a/htdocs/categories/traduction.php b/htdocs/categories/traduction.php index 7dbe6325e1d..40b40eab921 100644 --- a/htdocs/categories/traduction.php +++ b/htdocs/categories/traduction.php @@ -35,11 +35,13 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; $langs->load("categories"); $langs->load("languages"); -$id = GETPOST('id', 'int'); -$ref = GETPOST('ref', 'alpha'); -$action=GETPOST('action','alpha'); -$cancel=GETPOST('cancel','alpha'); -$type=GETPOST('type'); +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action','alpha'); +$cancel = GETPOST('cancel','alpha'); +$type = GETPOST('type','aZ09'); + +if (is_numeric($type)) $type=Categorie::$MAP_ID_TO_CODE[$type]; // For backward compatibility // Security check $fieldvalue = (! empty($id) ? $id : (! empty($ref) ? $ref : '')); @@ -153,6 +155,7 @@ elseif ($type == Categorie::TYPE_MEMBER) $title=$langs->trans("MembersCategor elseif ($type == Categorie::TYPE_CONTACT) $title=$langs->trans("ContactCategoriesShort"); elseif ($type == Categorie::TYPE_ACCOUNT) $title=$langs->trans("AccountsCategoriesShort"); elseif ($type == Categorie::TYPE_PROJECT) $title=$langs->trans("ProjectsCategoriesShort"); +elseif ($type == Categorie::TYPE_USER) $title=$langs->trans("UsersCategoriesShort"); else $title=$langs->trans("Category"); $head = categories_prepare_head($object,$type); @@ -256,9 +259,9 @@ if ($action == 'edit') print ''; } } - + print '
'; - + print '
'; print ''; print '     '; @@ -271,7 +274,7 @@ if ($action == 'edit') else if ($action != 'add') { if ($cnt_trans) print '
'; - + if (! empty($object->multilangs)) { foreach ($object->multilangs as $key => $value) diff --git a/htdocs/categories/viewcat.php b/htdocs/categories/viewcat.php index 1c6186d5df4..75a9215e18d 100644 --- a/htdocs/categories/viewcat.php +++ b/htdocs/categories/viewcat.php @@ -34,13 +34,13 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; $langs->load("categories"); -$id=GETPOST('id','int'); -$label=GETPOST('label'); -$type=GETPOST('type'); +$id = GETPOST('id','int'); +$label= GETPOST('label','alpha'); +$type = GETPOST('type','az09'); $action=GETPOST('action','aZ09'); -$confirm=GETPOST('confirm'); +$confirm = GETPOST('confirm','alpha'); $removeelem = GETPOST('removeelem','int'); -$elemid=GETPOST('elemid'); +$elemid = GETPOST('elemid','alpha'); if ($id == "" && $label == "") { @@ -61,6 +61,7 @@ if ($result <= 0) } $type=$object->type; +if (is_numeric($type)) $type=Categorie::$MAP_ID_TO_CODE[$type]; // For backward compatibility $extrafields = new ExtraFields($db); $extralabels = $extrafields->fetch_name_optionals_label($object->table_element); @@ -187,6 +188,7 @@ elseif ($type == Categorie::TYPE_MEMBER) $title=$langs->trans("MembersCategor elseif ($type == Categorie::TYPE_CONTACT) $title=$langs->trans("ContactCategoriesShort"); elseif ($type == Categorie::TYPE_ACCOUNT) $title=$langs->trans("AccountsCategoriesShort"); elseif ($type == Categorie::TYPE_PROJECT) $title=$langs->trans("ProjectsCategoriesShort"); +elseif ($type == Categorie::TYPE_USER) $title=$langs->trans("ProjectsCategoriesShort"); else $title=$langs->trans("Category"); $head = categories_prepare_head($object,$type); diff --git a/htdocs/comm/card.php b/htdocs/comm/card.php index dfdc9183886..cf7b5bf3dc0 100644 --- a/htdocs/comm/card.php +++ b/htdocs/comm/card.php @@ -603,11 +603,17 @@ if ($id > 0) if ($link) $boxstat.=''; } + $parameters = array(); + $reshook = $hookmanager->executeHooks('addMoreBoxStatsCustomer', $parameters, $object, $action); + if(empty($reshook)){ + $boxstat.= $hookmanager->resPrint; + } + $boxstat.=''; $boxstat.=''; $boxstat.='
'; - print $boxstat; + print $boxstat; $now=dol_now(); diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index b1d8aa03022..b603d1e6a17 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -1750,6 +1750,7 @@ if ($action == 'create') $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, $user->rights->propal->creer, 'string', '', null, null, '', 1); // Thirdparty $morehtmlref.='
'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1); + if (empty($conf->global->MAIN_DISABLE_OTHER_LINK) && $object->thirdparty->id > 0) $morehtmlref.=' ('.$langs->trans("OtherProposals").')'; // Project if (! empty($conf->projet->enabled)) { diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php index 70953e58fbf..6062f6033dc 100644 --- a/htdocs/comm/propal/list.php +++ b/htdocs/comm/propal/list.php @@ -355,6 +355,7 @@ if ($resql) $soc = new Societe($db); $soc->fetch($socid); $title = $langs->trans('ListOfProposals') . ' - '.$soc->name; + if (empty($search_societe)) $search_societe = $soc->name; } else { diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index a4888b44861..ddb44153e49 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1924,6 +1924,7 @@ if ($action == 'create' && $user->rights->commande->creer) $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, $user->rights->commande->creer, 'string', '', null, null, '', 1); // Thirdparty $morehtmlref.='
'.$langs->trans('ThirdParty') . ' : ' . $soc->getNomUrl(1); + if (empty($conf->global->MAIN_DISABLE_OTHER_LINK) && $object->thirdparty->id > 0) $morehtmlref.=' ('.$langs->trans("OtherOrders").')'; // Project if (! empty($conf->projet->enabled)) { diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 9e0b04ab6e9..565f39e62a2 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -578,6 +578,7 @@ if ($resql) $soc = new Societe($db); $soc->fetch($socid); $title = $langs->trans('ListOfOrders') . ' - '.$soc->name; + if (empty($search_company)) $search_company = $soc->name; } else { diff --git a/htdocs/compta/bank/class/api_bankaccounts.class.php b/htdocs/compta/bank/class/api_bankaccounts.class.php index 869b86238ff..c6fd3f72def 100644 --- a/htdocs/compta/bank/class/api_bankaccounts.class.php +++ b/htdocs/compta/bank/class/api_bankaccounts.class.php @@ -72,7 +72,7 @@ class BankAccounts extends DolibarrApi $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."bank_account as t"; $sql.= ' WHERE t.entity IN ('.getEntity('bank_account').')'; // Add sql filters - if ($sqlfilters) + if ($sqlfilters) { if (! DolibarrApi::_checkFilters($sqlfilters)) { @@ -81,7 +81,7 @@ class BankAccounts extends DolibarrApi $regexstring='\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)'; $sql.=" AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; } - + $sql.= $this->db->order($sortfield, $sortorder); if ($limit) { if ($page < 0) @@ -89,10 +89,10 @@ class BankAccounts extends DolibarrApi $page = 0; } $offset = $limit * $page; - + $sql.= $this->db->plimit($limit + 1, $offset); } - + dol_syslog("API Rest request"); $result = $this->db->query($sql); @@ -236,7 +236,7 @@ class BankAccounts extends DolibarrApi function _validate($data) { $account = array(); - foreach (Accounts::$FIELDS as $field) { + foreach (BankAccounts::$FIELDS as $field) { if (! isset($data[$field])) throw new RestException(400, "$field field missing"); $account[$field] = $data[$field]; diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 63b978a9e04..e10544f3c18 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -400,6 +400,22 @@ if (empty($reshook)) setEventMessages($discount->error, $discount->errors, 'errors'); } } + + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) + { + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09'); + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; + if (! empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $ret = $object->fetch($id); // Reload to get new records + + $result = $object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref); + if ($result < 0) setEventMessages($object->error, $object->errors, 'errors'); + } } else if ($action == 'setref_client' && $user->rights->facture->creer) @@ -1105,8 +1121,17 @@ if (empty($reshook)) foreach ($amountdeposit as $tva => $amount) { + $arraylist = array('amount' => 'FixAmount','variable' => 'VarAmount'); + $descline = $langs->trans('Deposit'); + $descline.= ' - '.$langs->trans($arraylist[$typeamount]); + if ($typeamount=='amount') { + $descline.= ' ('. price($valuedeposit, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)).')'; + } elseif ($typeamount=='variable') { + $descline.= ' ('. $valuedeposit.'%)'; + } + $descline.= ' - '.$srcobject->ref; $result = $object->addline( - $langs->trans('Deposit'), + $descline, $amount, // subprice 1, // quantity $tva, // vat rate @@ -1128,8 +1153,8 @@ if (empty($reshook)) 0, 0, 0, - 0, - $langs->trans('Deposit') + 0 + //,$langs->trans('Deposit') //Deprecated ); } @@ -1440,7 +1465,7 @@ if (empty($reshook)) { if (GETPOST('type') < 0 && ! GETPOST('search_idprod')) { - setEventMessages($langs->trans('ErrorChooseBetweenFreeAntryOrPredefinedProduct'), null, 'errors'); + setEventMessages($langs->trans('ErrorChooseBetweenFreeEntryOrPredefinedProduct'), null, 'errors'); $error ++; } } @@ -3075,6 +3100,7 @@ else if ($id > 0 || ! empty($ref)) $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, $user->rights->facture->creer, 'string', '', null, null, '', 1); // Thirdparty $morehtmlref.='
'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1); + if (empty($conf->global->MAIN_DISABLE_OTHER_LINK) && $object->thirdparty->id > 0) $morehtmlref.=' ('.$langs->trans("OtherBills").')'; // Project if (! empty($conf->projet->enabled)) { diff --git a/htdocs/compta/facture/fiche-rec.php b/htdocs/compta/facture/fiche-rec.php index d38ea012c3c..3a072f946be 100644 --- a/htdocs/compta/facture/fiche-rec.php +++ b/htdocs/compta/facture/fiche-rec.php @@ -1311,7 +1311,7 @@ else print ''; print '
'; print $langs->trans('RIB'); print ''; - if (($action != 'editbankaccount') && $user->rights->commande->creer && ! empty($object->brouillon)) + if (($action != 'editbankaccount') && $user->rights->facture->creer && ! empty($object->brouillon)) print 'id.'">'.img_edit($langs->trans('SetBankAccount'),1).'
'; print ''; diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index 72ea7e1a647..13e9a22d717 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -531,6 +531,7 @@ if ($resql) { $soc = new Societe($db); $soc->fetch($socid); + if (empty($search_societe)) $search_societe = $soc->name; } $param='&socid='.$socid; diff --git a/htdocs/compta/paiement/class/paiement.class.php b/htdocs/compta/paiement/class/paiement.class.php index f4e61380a9c..8e67825c085 100644 --- a/htdocs/compta/paiement/class/paiement.class.php +++ b/htdocs/compta/paiement/class/paiement.class.php @@ -337,6 +337,24 @@ class Paiement extends CommonObject $error++; } } + } + + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) + { + $outputlangs = $langs; + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $invoice->thirdparty->default_lang; + if (! empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $ret = $invoice->fetch($id); // Reload to get new records + + $result = $invoice->generateDocument($invoice->modelpdf, $outputlangs); + if ($result < 0) { + setEventMessages($invoice->error, $invoice->errors, 'errors'); + $error++; + } + } } } diff --git a/htdocs/compta/tva/index.php b/htdocs/compta/tva/index.php index 618ba11a37e..89accf57492 100644 --- a/htdocs/compta/tva/index.php +++ b/htdocs/compta/tva/index.php @@ -117,7 +117,7 @@ $textprevyear="".img_previo $textnextyear=" ".img_next($langs->trans("Next"), 'class="valignbottom"').""; print $conf->dol_optimize_smallscreen; -print load_fiche_titre($langs->trans("VAT"), $textprevyear." ".$langs->trans("Year")." ".$year_start." ".$textnextyear, 'title_accountancy.png'); +print load_fiche_titre($langs->transcountry("VAT", $mysoc->country_code), $textprevyear." ".$langs->trans("Year")." ".$year_start." ".$textnextyear, 'title_accountancy.png'); print $langs->trans("VATReportBuildWithOptionDefinedInModule").'
'; print '('.$langs->trans("TaxModuleSetupToModifyRules",DOL_URL_ROOT.'/admin/taxes.php').')
'; @@ -263,18 +263,18 @@ if (! empty($conf->global->MAIN_FEATURES_LEVEL)) print ""; print '' . $langs->trans("VATDue") . ''; // need to add translation - print '' . price(price2num($total, 1)) . ''; + print '' . price(price2num($total, 'MT')) . ''; print "\n"; print ""; print '' . $langs->trans("VATPaid") . ''; - print '' . price(price2num($obj->mm, 1)) . "\n"; + print '' . price(price2num($obj->mm, 'MT')) . "\n"; print "\n"; $restopay = $total - $obj->mm; print ""; print '' . $langs->trans("VATRestopay") . ''; // need to add translation - print '' . price(price2num($restopay, 1)) . ''; + print '' . price(price2num($restopay, 'MT')) . ''; print "\n"; print ''; diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index e08e10a0966..0c3ee14666a 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -1278,6 +1278,15 @@ class Contrat extends CommonObject //// End call triggers } } + + if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($this->array_options) && count($this->array_options)>0) // For avoid conflicts if trigger used + { + $result=$this->insertExtraFields(); + if ($result < 0) + { + $error++; + } + } // Commit or rollback if ($error) @@ -1633,8 +1642,8 @@ class Contrat extends CommonObject if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($array_options) && count($array_options)>0) // For avoid conflicts if trigger used { $contractline = new ContratLigne($this->db); - $contractline->array_options=$array_option; - $contractline->id= $this->db->last_insert_id(MAIN_DB_PREFIX.$contractline->table_element); + $contractline->array_options=$array_options; + $contractline->id= $rowid; $result=$contractline->insertExtraFields(); if ($result < 0) { diff --git a/htdocs/contrat/list.php b/htdocs/contrat/list.php index 4b638dcfef6..d53bc0a3ee1 100644 --- a/htdocs/contrat/list.php +++ b/htdocs/contrat/list.php @@ -306,6 +306,13 @@ if ($resql) $arrayofselected=is_array($toselect)?$toselect:array(); + if ($socid > 0) + { + $soc = new Societe($db); + $soc->fetch($socid); + if (empty($search_name)) $search_name = $soc->name; + } + $param=''; if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.$contextpage; if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.$limit; diff --git a/htdocs/contrat/services.php b/htdocs/contrat/services.php index 2fdec21f735..6534ef1e362 100644 --- a/htdocs/contrat/services.php +++ b/htdocs/contrat/services.php @@ -332,7 +332,7 @@ if ($conf->categorie->enabled && ($user->rights->produit->lire || $user->rights- $moreforfilter.='
'; $moreforfilter.=$langs->trans('IncludingProductWithTag'). ': '; $cate_arbo = $form->select_all_categories(Categorie::TYPE_PRODUCT, null, 'parent', null, null, 1); - $moreforfilter.=$form->selectarray('search_product_category', $cate_arbo, $search_product_category, 1, 0, 0, '', 0, 0, 0, 0, '', 1); + $moreforfilter.=$form->selectarray('search_product_category', $cate_arbo, $search_product_category, 1, 0, 0, '', 0, 0, 0, 0, 'maxwidth300', 1); $moreforfilter.='
'; } @@ -523,7 +523,6 @@ while ($i < min($num,$limit)) $contractstatic->ref=$obj->ref?$obj->ref:$obj->cid; - print ''; // Ref diff --git a/htdocs/core/actions_fetchobject.inc.php b/htdocs/core/actions_fetchobject.inc.php index 520d3c2d6da..7c25fbe7981 100644 --- a/htdocs/core/actions_fetchobject.inc.php +++ b/htdocs/core/actions_fetchobject.inc.php @@ -28,9 +28,9 @@ // $cancel must be defined // $id or $ref must be defined (object is loaded in this file with fetch) -if (($id > 0 || (! empty($ref) && ! in_array($action, array('create','createtask')))) && empty($cancel)) +if (($id > 0 || (! empty($ref) && ! in_array($action, array('create', 'createtask', 'add')))) && empty($cancel)) { - $ret = $object->fetch($id,$ref); + $ret = $object->fetch($id, $ref); if ($ret > 0) { $object->fetch_thirdparty(); @@ -38,7 +38,8 @@ if (($id > 0 || (! empty($ref) && ! in_array($action, array('create','createtask } else { - setEventMessages($object->error, $object->errors, 'errors'); + if (empty($object->error) && ! count($object->errors)) setEventMessages('Fetch on object return an error without filling $object->error nor $object->errors', null, 'errors'); + else setEventMessages($object->error, $object->errors, 'errors'); $action=''; } } diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index be6f13a22c7..f4a55352f96 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -594,7 +594,7 @@ if (! $error && $massaction == 'delete' && $permtodelete) $nbok = 0; foreach($toselect as $toselectid) { - $result=$objecttmp->fetch($toselectid); + $result=$objecttmp->fetch($toselectid); if ($result > 0) { if (in_array($objecttmp->element, array('societe','member'))) $result = $objecttmp->delete($objecttmp->id, $user, 1); diff --git a/htdocs/core/actions_sendmails.inc.php b/htdocs/core/actions_sendmails.inc.php index a796a94c68c..1998808bf11 100644 --- a/htdocs/core/actions_sendmails.inc.php +++ b/htdocs/core/actions_sendmails.inc.php @@ -391,6 +391,9 @@ if (($action == 'send' || $action == 'relance') && ! $_POST['addfile'] && ! $_PO $object->trackid = $trackid; $object->fk_element = $object->id; $object->elementtype = $object->element; + if (is_array($attachedfiles) && count($attachedfiles)>0) { + $object->attachedfiles = $attachedfiles; + } // Call of triggers if (! empty($trigger_name)) diff --git a/htdocs/core/ajax/selectsearchbox.php b/htdocs/core/ajax/selectsearchbox.php index 2e837fcbaae..2d92bc8f938 100644 --- a/htdocs/core/ajax/selectsearchbox.php +++ b/htdocs/core/ajax/selectsearchbox.php @@ -31,8 +31,17 @@ if (! isset($usedbyinclude) || empty($usedbyinclude)) if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1'); if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1'); if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1'); + if (! defined('NOREDIRECTBYMAINTOLOGIN')) define('NOREDIRECTBYMAINTOLOGIN','1'); $res=@include '../../main.inc.php'; + if ($res == 'ERROR_NOT_LOGGED') + { + $langs->load("other"); + $arrayresult['jumptologin']=array('img'=>'object_generic', 'label'=>$langs->trans("JumpToLogin"), 'text'=>' '.$langs->trans("JumpToLogin"), 'url'=>DOL_URL_ROOT.'/index.php'); + print json_encode($arrayresult); + if (is_object($db)) $db->close(); + exit; + } } include_once DOL_DOCUMENT_ROOT.'/core/lib/json.lib.php'; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index ddfb2780f3f..53de8e56eb8 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -334,23 +334,23 @@ abstract class CommonObject // No constructor as it is an abstract class - /** - * Check an object id/ref exists - * If you don't need/want to instantiate object and just need to know if object exists, use this method instead of fetch - * + /** + * Check an object id/ref exists + * If you don't need/want to instantiate object and just need to know if object exists, use this method instead of fetch + * * @param string $element String of element ('product', 'facture', ...) * @param int $id Id of object * @param string $ref Ref of object to check * @param string $ref_ext Ref ext of object to check * @return int <0 if KO, 0 if OK but not found, >0 if OK and exists - */ - static function isExistingObject($element, $id, $ref='', $ref_ext='') - { - global $db,$conf; + */ + static function isExistingObject($element, $id, $ref='', $ref_ext='') + { + global $db,$conf; $sql = "SELECT rowid, ref, ref_ext"; $sql.= " FROM ".MAIN_DB_PREFIX.$element; - $sql.= " WHERE entity IN (".getEntity($element, true).")" ; + $sql.= " WHERE entity IN (".getEntity($element).")" ; if ($id > 0) $sql.= " AND rowid = ".$db->escape($id); else if ($ref) $sql.= " AND ref = '".$db->escape($ref)."'"; @@ -371,17 +371,17 @@ abstract class CommonObject else return 0; } return -1; - } + } - /** - * Method to output saved errors - * - * @return string String with errors - */ - function errorsToString() - { - return $this->error.(is_array($this->errors)?(($this->error!=''?', ':'').join(', ',$this->errors)):''); - } + /** + * Method to output saved errors + * + * @return string String with errors + */ + function errorsToString() + { + return $this->error.(is_array($this->errors)?(($this->error!=''?', ':'').join(', ',$this->errors)):''); + } /** * Return full name (civility+' '+name+' '+lastname) @@ -1309,7 +1309,7 @@ abstract class CommonObject * Load properties id_previous and id_next * * @param string $filter Optional filter. Example: " AND (t.field1 = 'aa' OR t.field2 = 'bb')" - * @param int $fieldid Name of field to use for the select MAX and MIN + * @param string $fieldid Name of field to use for the select MAX and MIN * @param int $nodbprefix Do not include DB prefix to forge table name * @return int <0 if KO, >0 if OK */ @@ -1322,6 +1322,7 @@ abstract class CommonObject dol_print_error('',get_class($this)."::load_previous_next_ref was called on objet with property table_element not defined"); return -1; } + if ($fieldid == 'none') return 1; // this->ismultientitymanaged contains // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe @@ -3947,7 +3948,7 @@ abstract class CommonObject // Now we add first model found in directories scanned $listofdir=explode(',',$dirtoscan); - foreach($listofdir as $key=>$tmpdir) + foreach($listofdir as $key => $tmpdir) { $tmpdir=trim($tmpdir); $tmpdir=preg_replace('/DOL_DATA_ROOT/',DOL_DATA_ROOT,$tmpdir); @@ -4736,19 +4737,6 @@ abstract class CommonObject - - /** - * Function test if type is date - * - * @param array $info content informations of field - * @return bool - */ - protected function isDate($info) - { - if(isset($info['type']) && ($info['type']=='date' || $info['type']=='datetime' || $info['type']=='timestamp')) return true; - else return false; - } - /** * Function test if type is array * @@ -4781,13 +4769,26 @@ abstract class CommonObject else return false; } + + /** + * Function test if type is date + * + * @param array $info content informations of field + * @return bool + */ + public function isDate($info) + { + if(isset($info['type']) && ($info['type']=='date' || $info['type']=='datetime' || $info['type']=='timestamp')) return true; + else return false; + } + /** * Function test if type is integer * * @param array $info content informations of field * @return bool */ - protected function isInt($info) + public function isInt($info) { if(is_array($info)) { @@ -4803,11 +4804,11 @@ abstract class CommonObject * @param array $info content informations of field * @return bool */ - protected function isFloat($info) + public function isFloat($info) { if(is_array($info)) { - if(isset($info['type']) && $info['type']=='float') return true; + if (isset($info['type']) && (preg_match('/^(double|real)/i', $info['type']))) return true; else return false; } else return false; @@ -4819,7 +4820,7 @@ abstract class CommonObject * @param array $info content informations of field * @return bool */ - protected function isText($info) + public function isText($info) { if(is_array($info)) { @@ -4846,49 +4847,58 @@ abstract class CommonObject } /** - * Function to prepare the values to insert + * Function to prepare the values to insert. + * Note $this->${field} are set by the page that make the createCommon or the updateCommon. * * @return array */ private function set_save_query() { - $query=array(); - foreach ($this->fields as $field=>$info) + global $conf; + + $queryarray=array(); + foreach ($this->fields as $field=>$info) // Loop on definition of fields { + // Depending on field type ('datetime', ...) if($this->isDate($info)) { if(empty($this->{$field})) { - $query[$field] = NULL; + $queryarray[$field] = NULL; } else { - $query[$field] = $this->db->idate($this->{$field}); + $queryarray[$field] = $this->db->idate($this->{$field}); } } else if($this->isArray($info)) { - $query[$field] = serialize($this->{$field}); + $queryarray[$field] = serialize($this->{$field}); } else if($this->isInt($info)) { - $query[$field] = (int) price2num($this->{$field}); + if ($field == 'entity' && is_null($this->{$field})) $queryarray[$field]=$conf->entity; + else + { + $queryarray[$field] = (int) price2num($this->{$field}); + if (empty($queryarray[$field])) $queryarray[$field]=0; // May be rest to null later if property 'nullifempty' is on for this field. + } } else if($this->isFloat($info)) { - $query[$field] = (double) price2num($this->{$field}); - } - elseif($this->isNull($info)) - { - $query[$field] = (is_null($this->{$field}) || (empty($this->{$field}) && $this->{$field}!==0 && $this->{$field}!=='0') ? null : $this->{$field}); + $queryarray[$field] = (double) price2num($this->{$field}); + if (empty($queryarray[$field])) $queryarray[$field]=0; } else { - $query[$field] = $this->{$field}; + $queryarray[$field] = $this->{$field}; } + + if ($info['type'] == 'timestamp' && empty($queryarray[$field])) unset($queryarray[$field]); + if (! empty($info['nullifempty']) && empty($queryarray[$field])) $queryarray[$field] = null; } - return $query; + return $queryarray; } /** @@ -4896,7 +4906,7 @@ abstract class CommonObject * * @param stdClass $obj Contain data of object from database */ - private function set_vars_by_db(&$obj) + private function setVarsFromFetchObj(&$obj) { foreach ($this->fields as $field => $info) { @@ -4913,7 +4923,8 @@ abstract class CommonObject } elseif($this->isInt($info)) { - $this->{$field} = (int) $obj->{$field}; + if ($field == 'rowid') $this->id = (int) $obj->{$field}; + else $this->{$field} = (int) $obj->{$field}; } elseif($this->isFloat($info)) { @@ -4947,15 +4958,14 @@ abstract class CommonObject /** * Add quote to field value if necessary * - * @param string|int $value value to protect - * @return string|int + * @param string|int $value Value to protect + * @param array $fieldsentry Properties of field + * @return string */ - protected function quote($value) { - - if(is_null($value)) return 'NULL'; - else if(is_numeric($value)) return $value; - else return "'".$this->db->escape( $value )."'"; - + protected function quote($value, $fieldsentry) { + if (is_null($value)) return 'NULL'; + else if (preg_match('/^(int|double|real)/i', $fieldsentry['type'])) return $this->db->escape("$value"); + else return "'".$this->db->escape($value)."'"; } @@ -4970,23 +4980,29 @@ abstract class CommonObject { $error = 0; - $fields = array_merge(array('datec'=>$this->db->idate(dol_now())), $this->set_save_query()); + $now=dol_now(); + + $fieldvalues = $this->set_save_query(); + if (array_key_exists('date_creation', $fieldvalues) && empty($fieldvalues['date_creation'])) $fieldvalues['date_creation']=$this->db->idate($now); + if (array_key_exists('fk_user_creat', $fieldvalues) && ! ($fieldvalues['fk_user_creat'] > 0)) $fieldvalues['fk_user_creat']=$user->id; + unset($fieldvalues['rowid']); // We suppose the field rowid is reserved field for autoincrement field. $keys=array(); $values = array(); - foreach ($fields as $k => $v) { + foreach ($fieldvalues as $k => $v) { $keys[] = $k; - $values[] = $this->quote($v); + $values[] = $this->quote($v, $this->fields[$k]); } $this->db->begin(); if (! $error) { - $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.' - ( '.implode( ",", $keys ).' ) - VALUES ( '.implode( ",", $values ).' ) '; - $res = $this->db->query( $sql ); + $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element; + $sql.= ' ('.implode( ", ", $keys ).')'; + $sql.= ' VALUES ('.implode( ", ", $values ).')'; + + $res = $this->db->query( $sql ); if ($res===false) { $error++; $this->errors[] = $this->db->lasterror(); @@ -4998,7 +5014,7 @@ abstract class CommonObject if (!$notrigger) { // Call triggers - $result=$this->call_trigger(strtoupper(get_class(self)).'_CREATE',$user); + $result=$this->call_trigger(strtoupper(get_class($this)).'_CREATE',$user); if ($result < 0) { $error++; } // End call triggers } @@ -5023,7 +5039,7 @@ abstract class CommonObject */ public function createFromCloneCommon(User $user, $fromid) { - global $user; + global $user, $langs; $error = 0; @@ -5035,10 +5051,14 @@ abstract class CommonObject // Load source object $object->fetchCommon($fromid); - // Reset object - $object->id = 0; + // Reset some properties + unset($object->id); + unset($object->fk_user_creat); + unset($object->import_key); // Clear fields + $object->ref = "copy_of_".$object->ref; + $object->title = $langs->trans("CopyOf")." ".$object->title; // ... // Create clone @@ -5046,7 +5066,8 @@ abstract class CommonObject // Other options if ($result < 0) { - $error ++; + $error++; + $this->error = $object->error; $this->errors = $object->errors; dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); } @@ -5072,11 +5093,11 @@ abstract class CommonObject { if (empty($id) && empty($ref)) return false; - $sql = 'SELECT '.$this->get_field_list().', datec, tms'; + $sql = 'SELECT '.$this->get_field_list(); $sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element; if(!empty($id)) $sql.= ' WHERE rowid = '.$id; - else $sql.= ' WHERE ref = \''.$this->quote($ref).'\''; + else $sql.= " WHERE ref = ".$this->quote($ref, $this->fields['ref']); $res = $this->db->query($sql); if ($res) @@ -5085,12 +5106,7 @@ abstract class CommonObject { if ($obj) { - $this->id = $id; - $this->set_vars_by_db($obj); - - $this->datec = $this->db->idate($obj->datec); - $this->tms = $this->db->idate($obj->tms); - + $this->setVarsFromFetchObj($obj); return $this->id; } else @@ -5124,27 +5140,27 @@ abstract class CommonObject { $error = 0; - $fields = $this->set_save_query(); + $fieldvalues = $this->set_save_query(); + unset($fieldvalues['rowid']); // We don't update this field, it is the key to define which record to update. - foreach ($fields as $k => $v) { + foreach ($fieldvalues as $k => $v) { if (is_array($key)){ $i=array_search($k, $key); if ( $i !== false) { - $where[] = $key[$i].'=' . $this->quote( $v ) ; + $where[] = $key[$i].'=' . $this->quote($v, $this->fields[$k]); continue; } } else { if ( $k == $key) { - $where[] = $k.'=' .$this->quote( $v ) ; + $where[] = $k.'=' .$this->quote($v, $this->fields[$k]); continue; } } - $tmp[] = $k.'='.$this->quote($v); + $tmp[] = $k.'='.$this->quote($v, $this->fields[$k]); } $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element.' SET '.implode( ',', $tmp ).' WHERE rowid='.$this->id ; $this->db->begin(); - if (! $error) { $res = $this->db->query($sql); @@ -5157,7 +5173,7 @@ abstract class CommonObject if (! $error && ! $notrigger) { // Call triggers - $result=$this->call_trigger(strtoupper(get_class(self)).'_MODIFY',$user); + $result=$this->call_trigger(strtoupper(get_class($this)).'_MODIFY',$user); if ($result < 0) { $error++; } //Do also here what you must do to rollback action if trigger fail // End call triggers } @@ -5188,7 +5204,7 @@ abstract class CommonObject if (! $error) { if (! $notrigger) { // Call triggers - $result=$this->call_trigger(strtoupper(get_class(self)).'_DELETE', $user); + $result=$this->call_trigger(strtoupper(get_class($this)).'_DELETE', $user); if ($result < 0) { $error++; } // Do also here what you must do to rollback action if trigger fail // End call triggers } diff --git a/htdocs/core/class/doleditor.class.php b/htdocs/core/class/doleditor.class.php index db768b4c630..eaf72ffff71 100644 --- a/htdocs/core/class/doleditor.class.php +++ b/htdocs/core/class/doleditor.class.php @@ -82,7 +82,7 @@ class DolEditor // Check if extended editor is ok. If not we force textarea if ((empty($conf->fckeditor->enabled) && $okforextendededitor != 'ace') || empty($okforextendededitor)) $this->tool = 'textarea'; if ($okforextendededitor === 'ace') $this->tool='ace'; - if ($conf->dol_use_jmobile) $this->tool = 'textarea'; // TODO ckeditor ko with mobile ? ace ko with mobile ? + //if ($conf->dol_use_jmobile) $this->tool = 'textarea'; // ckeditor and ace seems ok with mobile // Define content and some properties if ($this->tool == 'ckeditor') diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index e44fa8a5aec..966f3f859c0 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -281,7 +281,7 @@ class ExtraFields */ private function create_label($attrname, $label='', $type='', $pos=0, $size=0, $elementtype='member', $unique=0, $required=0, $param='', $alwayseditable=0, $perms='', $list=0, $ishidden=0, $default='', $computed='') { - global $conf; + global $conf,$user; if ($elementtype == 'thirdparty') $elementtype='societe'; if ($elementtype == 'contact') $elementtype='socpeople'; @@ -305,7 +305,27 @@ class ExtraFields $params=''; } - $sql = "INSERT INTO ".MAIN_DB_PREFIX."extrafields(name, label, type, pos, size, entity, elementtype, fieldunique, fieldrequired, param, alwayseditable, perms, list, ishidden, fielddefault, fieldcomputed)"; + $sql = "INSERT INTO ".MAIN_DB_PREFIX."extrafields("; + $sql.= " name,"; + $sql.= " label,"; + $sql.= " type,"; + $sql.= " pos,"; + $sql.= " size,"; + $sql.= " entity,"; + $sql.= " elementtype,"; + $sql.= " fieldunique,"; + $sql.= " fieldrequired,"; + $sql.= " param,"; + $sql.= " alwayseditable,"; + $sql.= " perms,"; + $sql.= " list,"; + $sql.= " ishidden,"; + $sql.= " fielddefault,"; + $sql.= " fieldcomputed,"; + $sql.= " fk_user_author,"; + $sql.= " fk_user_modif,"; + $sql.= " datec"; + $sql.= " )"; $sql.= " VALUES('".$attrname."',"; $sql.= " '".$this->db->escape($label)."',"; $sql.= " '".$type."',"; @@ -321,9 +341,12 @@ class ExtraFields $sql.= " ".$list.","; $sql.= " ".$ishidden.","; $sql.= " ".($default?"'".$this->db->escape($default)."'":"null").","; - $sql.= " ".($computed?"'".$this->db->escape($computed)."'":"null"); + $sql.= " ".($computed?"'".$this->db->escape($computed)."'":"null").","; + $sql .= " " . $user->id . ","; + $sql .= " " . $user->id . ","; + $sql .= "'" . $this->db->idate(dol_now()) . "'"; $sql.=')'; - + dol_syslog(get_class($this)."::create_label", LOG_DEBUG); if ($this->db->query($sql)) { @@ -562,7 +585,7 @@ class ExtraFields */ private function update_label($attrname,$label,$type,$size,$elementtype,$unique=0,$required=0,$pos=0,$param='',$alwayseditable=0,$perms='',$list=0,$ishidden=0,$default='',$computed='') { - global $conf; + global $conf, $user; dol_syslog(get_class($this)."::update_label ".$attrname.", ".$label.", ".$type.", ".$size.", ".$elementtype.", ".$unique.", ".$required.", ".$pos.", ".$alwayseditable.", ".$perms.", ".$list.", ".$ishidden.", ".$default.", ".$computed); // Clean parameters @@ -603,7 +626,10 @@ class ExtraFields $sql.= " list,"; $sql.= " ishidden,"; $sql.= " fielddefault,"; - $sql.= " fieldcomputed"; + $sql.= " fieldcomputed,"; + $sql.= " fk_user_author,"; + $sql.= " fk_user_modif,"; + $sql.= " datec"; $sql.= ") VALUES ("; $sql.= "'".$attrname."',"; $sql.= " ".$conf->entity.","; @@ -620,7 +646,10 @@ class ExtraFields $sql.= " ".$list.", "; $sql.= " ".$ishidden.", "; $sql.= " ".($default?"'".$this->db->escape($default)."'":"null").","; - $sql.= " ".($computed?"'".$this->db->escape($computed)."'":"null"); + $sql.= " ".($computed?"'".$this->db->escape($computed)."'":"null").","; + $sql .= " " . $user->id . ","; + $sql .= " " . $user->id . ","; + $sql .= "'" . $this->db->idate(dol_now()) . "'"; $sql.= ")"; $resql2=$this->db->query($sql); diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 0f16a25c43f..880f32cc580 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -4417,7 +4417,7 @@ class Form dol_syslog(__METHOD__, LOG_DEBUG); - $sql = "SELECT DISTINCT t.rowid, t.code, t.taux, t.recuperableonly"; + $sql = "SELECT DISTINCT t.rowid, t.code, t.taux, t.localtax1, t.localtax1_type, t.localtax2, t.localtax2_type, t.recuperableonly"; $sql.= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c"; $sql.= " WHERE t.fk_pays = c.rowid"; $sql.= " AND t.active > 0"; @@ -4436,8 +4436,20 @@ class Form $this->cache_vatrates[$i]['rowid'] = $obj->rowid; $this->cache_vatrates[$i]['code'] = $obj->code; $this->cache_vatrates[$i]['txtva'] = $obj->taux; - $this->cache_vatrates[$i]['libtva'] = $obj->taux.'%'.($obj->code?' ('.$obj->code.')':''); // Label must contains only 0-9 , . % or * $this->cache_vatrates[$i]['nprtva'] = $obj->recuperableonly; + $this->cache_vatrates[$i]['localtax1'] = $obj->localtax1; + $this->cache_vatrates[$i]['localtax1_type'] = $obj->localtax1_type; + $this->cache_vatrates[$i]['localtax2'] = $obj->localtax2; + $this->cache_vatrates[$i]['localtax2_type'] = $obj->localtax1_type; + + $this->cache_vatrates[$i]['label'] = $obj->taux.'%'.($obj->code?' ('.$obj->code.')':''); // Label must contains only 0-9 , . % or * + $this->cache_vatrates[$i]['labelallrates'] = $obj->taux.'/'.($obj->localtax1?$obj->localtax1:'0').'/'.($obj->localtax2?$obj->localtax2:'0').($obj->code?' ('.$obj->code.')':''); // Must never be used as key, only label + $positiverates=''; + if ($obj->taux) $positiverates.=($positiverates?'/':'').$obj->taux; + if ($obj->localtax1) $positiverates.=($positiverates?'/':'').$obj->localtax1; + if ($obj->localtax2) $positiverates.=($positiverates?'/':'').$obj->localtax2; + if (empty($positiverates)) $positiverates='0'; + $this->cache_vatrates[$i]['labelpositiverates'] = $positiverates.($obj->code?' ('.$obj->code.')':''); // Must never be used as key, only label } return $num; @@ -4611,7 +4623,16 @@ class Form $selectedfound=true; } } - $return.= '>'.vatrate($rate['libtva']); + $return.= '>'; + //if (! empty($conf->global->MAIN_VAT_SHOW_POSITIVE_RATES)) + if ($mysoc->country_code == 'IN' || ! empty($conf->global->MAIN_VAT_LABEL_IS_POSITIVE_RATES)) + { + $return.= $rate['labelpositiverates']; + } + else + { + $return.= vatrate($rate['label']); + } //$return.=($rate['code']?' '.$rate['code']:''); $return.= (empty($rate['code']) && $rate['nprtva']) ? ' *': ''; // We show the * (old behaviour only if new vat code is not used) @@ -5604,6 +5625,14 @@ class Form { $listofidcompanytoscan=$object->thirdparty->id; if (($object->thirdparty->parent > 0) && ! empty($conf->global->THIRDPARTY_INCLUDE_PARENT_IN_LINKTO)) $listofidcompanytoscan.=','.$object->thirdparty->parent; + if (($object->fk_project > 0) && ! empty($conf->global->THIRDPARTY_INCLUDE_PROJECT_THIRDPARY_IN_LINKTO)) + { + include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; + $tmpproject=new Project($this->db); + $tmpproject->fetch($object->fk_project); + if ($tmpproject->socid > 0 && ($tmpproject->socid != $object->thirdparty->id)) $listofidcompanytoscan.=','.$tmpproject->socid; + unset($tmpproject); + } $possiblelinks=array( 'propal'=>array('enabled'=>$conf->propal->enabled, 'perms'=>1, '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').')'), @@ -5835,7 +5864,7 @@ class Form * @param string $paramid Name of parameter to use to name the id into the URL next/previous link. * @param string $morehtml More html content to output just before the nav bar. * @param int $shownav Show Condition (navigation is shown if value is 1). - * @param string $fieldid Name of field id into database to use for select next and previous (we make the select max and min on this field). + * @param string $fieldid Name of field id into database to use for select next and previous (we make the select max and min on this field). Use 'none' to disable next/prev. * @param string $fieldref Name of field ref of object (object->ref) to show or 'none' to not show ref. * @param string $morehtmlref More html to show after ref. * @param string $moreparam More param to add in nav link url. Must start with '&...'. diff --git a/htdocs/core/class/html.formwebsite.class.php b/htdocs/core/class/html.formwebsite.class.php new file mode 100644 index 00000000000..666311d1744 --- /dev/null +++ b/htdocs/core/class/html.formwebsite.class.php @@ -0,0 +1,1254 @@ + + * + * 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 htdocs/core/class/html.formwebsite.class.php + * \ingroup core + * \brief File of class to manage component html for module website + */ + + +/** + * Class to manage component html for module website + */ +class FormWebsite +{ + private $db; + public $error; + + + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + function __construct($db) + { + $this->db = $db; + + return 1; + } + + + /** + * Return HTML select list of export models + * + * @param string $selected Id modele pre-selectionne + * @param string $htmlname Name of HTML select + * @param int $useempty Show empty value or not + * @return string Html component + */ + function selectWebsite($selected='',$htmlname='exportmodelid',$useempty=0) + { + $out=''; + + $sql = "SELECT rowid, ref"; + $sql.= " FROM ".MAIN_DB_PREFIX."website"; + $sql.= " WHERE 1 = 1"; + $sql.= " ORDER BY rowid"; + $result = $this->db->query($sql); + if ($result) + { + $out.='"; + } + else { + dol_print_error($this->db); + } + + return $out; + } + + + /** + * Return list of export models + * + * @param string $selected Id modele pre-selectionne + * @param string $htmlname Nom de la zone select + * @param string $type Type des modeles recherches + * @param int $useempty Affiche valeur vide dans liste + * @return void + */ + function select_import_model($selected='',$htmlname='importmodelid',$type='',$useempty=0) + { + $sql = "SELECT rowid, label"; + $sql.= " FROM ".MAIN_DB_PREFIX."import_model"; + $sql.= " WHERE type = '".$type."'"; + $sql.= " ORDER BY rowid"; + $result = $this->db->query($sql); + if ($result) + { + print '"; + } + else { + dol_print_error($this->db); + } + } + + + /** + * Return list of ecotaxes with label + * + * @param string $selected Preselected ecotaxes + * @param string $htmlname Name of combo list + * @return integer + */ + function select_ecotaxes($selected='',$htmlname='ecotaxe_id') + { + global $langs; + + $sql = "SELECT e.rowid, e.code, e.libelle, e.price, e.organization,"; + $sql.= " c.label as country"; + $sql.= " FROM ".MAIN_DB_PREFIX."c_ecotaxe as e,".MAIN_DB_PREFIX."c_country as c"; + $sql.= " WHERE e.active = 1 AND e.fk_pays = c.rowid"; + $sql.= " ORDER BY country, e.organization ASC, e.code ASC"; + + dol_syslog(get_class($this).'::select_ecotaxes', LOG_DEBUG); + $resql=$this->db->query($sql); + if ($resql) + { + print ''; + return 0; + } + else + { + dol_print_error($this->db); + return 1; + } + } + + + /** + * Return list of revenue stamp for country + * + * @param string $selected Value of preselected revenue stamp + * @param string $htmlname Name of combo list + * @param string $country_code Country Code + * @return string HTML select list + */ + function select_revenue_stamp($selected='',$htmlname='revenuestamp',$country_code='') + { + global $langs; + + $out=''; + + $sql = "SELECT r.taux"; + $sql.= " FROM ".MAIN_DB_PREFIX."c_revenuestamp as r,".MAIN_DB_PREFIX."c_country as c"; + $sql.= " WHERE r.active = 1 AND r.fk_pays = c.rowid"; + $sql.= " AND c.code = '".$country_code."'"; + + dol_syslog(get_class($this).'::select_revenue_stamp', LOG_DEBUG); + $resql=$this->db->query($sql); + if ($resql) + { + $out.=''; + return $out; + } + else + { + dol_print_error($this->db); + return ''; + } + } + + + /** + * Return a HTML select list to select a percent + * + * @param integer $selected pourcentage pre-selectionne + * @param string $htmlname nom de la liste deroulante + * @param int $disabled Disabled or not + * @param int $increment increment value + * @param int $start start value + * @param int $end end value + * @param int $showempty Add also an empty line + * @return string HTML select string + */ + function select_percent($selected=0,$htmlname='percent',$disabled=0,$increment=5,$start=0,$end=100,$showempty=0) + { + $return = ''; + + return $return; + } + + /** + * Return select list for categories (to use in form search selectors) + * + * @param int $type Type of category ('customer', 'supplier', 'contact', 'product', 'member'). Old mode (0, 1, 2, ...) is deprecated. + * @param integer $selected Preselected value + * @param string $htmlname Name of combo list + * @param int $nocateg Show also an entry "Not categorized" + * @param int $showempty Add also an empty line + * @param string $morecss More CSS + * @return string Html combo list code + * @see select_all_categories + */ + function select_categories($type, $selected=0, $htmlname='search_categ', $nocateg=0, $showempty=1, $morecss='') + { + global $conf, $langs; + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; + + // For backward compatibility + if (is_numeric($type)) + { + dol_syslog(__METHOD__ . ': using numeric value for parameter type is deprecated. Use string code instead.', LOG_WARNING); + } + + // Load list of "categories" + $static_categs = new Categorie($this->db); + $tab_categs = $static_categs->get_full_arbo($type); + + $moreforfilter = ''; + // Enhance with select2 + if ($conf->use_javascript_ajax) + { + include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php'; + $comboenhancement = ajax_combobox('select_categ_'.$htmlname); + $moreforfilter.=$comboenhancement; + } + + // Print a select with each of them + $moreforfilter.=''; + + return $moreforfilter; + } + + + /** + * Return select list for categories (to use in form search selectors) + * + * @param string $selected Preselected value + * @param string $htmlname Name of combo list (example: 'search_sale') + * @param User $user Object user + * @param int $showstatus 0=show user status only if status is disabled, 1=always show user status into label, -1=never show user status + * @param int $showempty 1=show also an empty value + * @param string $morecss More CSS + * @return string Html combo list code + */ + function select_salesrepresentatives($selected,$htmlname,$user,$showstatus=0,$showempty=1,$morecss='') + { + global $conf,$langs; + $langs->load('users'); + + $out = ''; + // Enhance with select2 + if ($conf->use_javascript_ajax) + { + include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php'; + + $comboenhancement = ajax_combobox($htmlname); + if ($comboenhancement) + { + $out.=$comboenhancement; + } + } + // Select each sales and print them in a select input + $out.=''; + + return $out; + } + + /** + * Return list of project and tasks + * + * @param int $selectedtask Pre-selected task + * @param int $projectid Project id + * @param string $htmlname Name of html select + * @param int $modeproject 1 to restrict on projects owned by user + * @param int $modetask 1 to restrict on tasks associated to user + * @param int $mode 0=Return list of tasks and their projects, 1=Return projects and tasks if exists + * @param int $useempty 0=Allow empty values + * @param int $disablechildoftaskid 1=Disable task that are child of the provided task id + * @return void + */ + function selectProjectTasks($selectedtask='', $projectid=0, $htmlname='task_parent', $modeproject=0, $modetask=0, $mode=0, $useempty=0, $disablechildoftaskid=0) + { + global $user, $langs; + + require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php'; + + //print $modeproject.'-'.$modetask; + $task=new Task($this->db); + $tasksarray=$task->getTasksArray($modetask?$user:0, $modeproject?$user:0, $projectid, 0, $mode); + if ($tasksarray) + { + print ''; + } + else + { + print '
'.$langs->trans("NoProject").'
'; + } + } + + /** + * Write lines of a project (all lines of a project if parent = 0) + * + * @param int $inc Cursor counter + * @param int $parent Id of parent task we want to see + * @param array $lines Array of task lines + * @param int $level Level + * @param int $selectedtask Id selected task + * @param int $selectedproject Id selected project + * @param int $disablechildoftaskid 1=Disable task that are child of the provided task id + * @return void + */ + private function _pLineSelect(&$inc, $parent, $lines, $level=0, $selectedtask=0, $selectedproject=0, $disablechildoftaskid=0) + { + global $langs, $user, $conf; + + $lastprojectid=0; + + $numlines=count($lines); + for ($i = 0 ; $i < $numlines ; $i++) + { + if ($lines[$i]->fk_parent == $parent) + { + $var = !$var; + + //var_dump($selectedproject."--".$selectedtask."--".$lines[$i]->fk_project."_".$lines[$i]->id); // $lines[$i]->id may be empty if project has no lines + + // Break on a new project + if ($parent == 0) // We are on a task at first level + { + if ($lines[$i]->fk_project != $lastprojectid) // Break found on project + { + if ($i > 0) print ''; + print '\n"; + + $lastprojectid=$lines[$i]->fk_project; + $inc++; + } + } + + $newdisablechildoftaskid=$disablechildoftaskid; + + // Print task + if (isset($lines[$i]->id)) // We use isset because $lines[$i]->id may be null if project has no task and are on root project (tasks may be caught by a left join). We enter here only if '0' or >0 + { + // Check if we must disable entry + $disabled=0; + if ($disablechildoftaskid && (($lines[$i]->id == $disablechildoftaskid || $lines[$i]->fk_parent == $disablechildoftaskid))) + { + $disabled++; + if ($lines[$i]->fk_parent == $disablechildoftaskid) $newdisablechildoftaskid=$lines[$i]->id; // If task is child of a disabled parent, we will propagate id to disable next child too + } + + print '\n"; + $inc++; + } + + $level++; + if ($lines[$i]->id) $this->_pLineSelect($inc, $lines[$i]->id, $lines, $level, $selectedtask, $selectedproject, $newdisablechildoftaskid); + $level--; + } + } + } + + + /** + * Output a HTML thumb of color or a text if not defined. + * + * @param string $color String with hex (FFFFFF) or comma RGB ('255,255,255') + * @param string $textifnotdefined Text to show if color not defined + * @return string HTML code for color thumb + * @see selectColor + */ + static function showColor($color, $textifnotdefined='') + { + $textcolor='FFF'; + if ($color) + { + $tmp=explode(',', $color); + if (count($tmp) > 1) // This is a comma RGB ('255','255','255') + { + $r = $tmp[0]; + $g = $tmp[1]; + $b = $tmp[2]; + } + else + { + $hexr=$color[0].$color[1]; + $hexg=$color[2].$color[3]; + $hexb=$color[4].$color[5]; + $r = hexdec($hexr); + $g = hexdec($hexg); + $b = hexdec($hexb); + } + $bright = (max($r, $g, $b) + min($r, $g, $b)) / 510.0; // HSL algorithm + if ($bright > 0.6) $textcolor='000'; + } + + include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + $color = colorArrayToHex(colorStringToArray($color,array()),''); + + if ($color) print ''; + else print $textifnotdefined; + } + + /** + * Output a HTML code to select a color + * + * @param string $set_color Pre-selected color + * @param string $prefix Name of HTML field + * @param string $form_name Deprecated. Not used. + * @param int $showcolorbox 1=Show color code and color box, 0=Show only color code + * @param array $arrayofcolors Array of colors. Example: array('29527A','5229A3','A32929','7A367A','B1365F','0D7813') + * @return void + * @deprecated Use instead selectColor + * @see selectColor() + */ + function select_color($set_color='', $prefix='f_color', $form_name='', $showcolorbox=1, $arrayofcolors='') + { + print $this->selectColor($set_color, $prefix, $form_name, $showcolorbox, $arrayofcolors); + } + + /** + * Output a HTML code to select a color. Field will return an hexa color like '334455'. + * + * @param string $set_color Pre-selected color + * @param string $prefix Name of HTML field + * @param string $form_name Deprecated. Not used. + * @param int $showcolorbox 1=Show color code and color box, 0=Show only color code + * @param array $arrayofcolors Array of colors. Example: array('29527A','5229A3','A32929','7A367A','B1365F','0D7813') + * @param string $morecss Add css style into input field + * @return string + * @see showColor + */ + static function selectColor($set_color='', $prefix='f_color', $form_name='', $showcolorbox=1, $arrayofcolors='', $morecss='') + { + // Deprecation warning + if ($form_name) { + dol_syslog(__METHOD__ . ": form_name parameter is deprecated", LOG_WARNING); + } + + global $langs,$conf; + + $out=''; + + if (! is_array($arrayofcolors) || count($arrayofcolors) < 1) + { + $langs->load("other"); + if (empty($conf->dol_use_jmobile)) + { + $out.= ''; + $out.= ''; + $out.= ''; + } + $out.= ''; + } + else // In most cases, this is not used. We used instead function with no specific list of colors + { + if (empty($conf->dol_use_jmobile)) + { + $out.= ''; + $out.= ''; + $out.= ''; + } + $out.= ''; + } + + return $out; + } + + /** + * Creation d'un icone de couleur + * + * @param string $color Couleur de l'image + * @param string $module Nom du module + * @param string $name Nom de l'image + * @param int $x Largeur de l'image en pixels + * @param int $y Hauteur de l'image en pixels + * @return void + */ + function CreateColorIcon($color,$module,$name,$x='12',$y='12') + { + global $conf; + + $file = $conf->$module->dir_temp.'/'.$name.'.png'; + + // On cree le repertoire contenant les icones + if (! file_exists($conf->$module->dir_temp)) + { + dol_mkdir($conf->$module->dir_temp); + } + + // On cree l'image en vraies couleurs + $image = imagecreatetruecolor($x,$y); + + $color = substr($color,1,6); + + $rouge = hexdec(substr($color,0,2)); //conversion du canal rouge + $vert = hexdec(substr($color,2,2)); //conversion du canal vert + $bleu = hexdec(substr($color,4,2)); //conversion du canal bleu + + $couleur = imagecolorallocate($image,$rouge,$vert,$bleu); + //print $rouge.$vert.$bleu; + imagefill($image,0,0,$couleur); //on remplit l'image + // On cree la couleur et on l'attribue a une variable pour ne pas la perdre + ImagePng($image,$file); //renvoie une image sous format png + ImageDestroy($image); + } + + /** + * Return HTML combo list of week + * + * @param string $selected Preselected value + * @param string $htmlname Nom de la zone select + * @param int $useempty Affiche valeur vide dans liste + * @return string + */ + function select_dayofweek($selected='',$htmlname='weekid',$useempty=0) + { + global $langs; + + $week = array( 0=>$langs->trans("Day0"), + 1=>$langs->trans("Day1"), + 2=>$langs->trans("Day2"), + 3=>$langs->trans("Day3"), + 4=>$langs->trans("Day4"), + 5=>$langs->trans("Day5"), + 6=>$langs->trans("Day6")); + + $select_week = ''; + return $select_week; + } + + /** + * Return HTML combo list of month + * + * @param string $selected Preselected value + * @param string $htmlname Name of HTML select object + * @param int $useempty Show empty in list + * @param int $longlabel Show long label + * @return string + */ + function select_month($selected='',$htmlname='monthid',$useempty=0,$longlabel=0) + { + global $langs; + + require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; + + if ($longlabel) $montharray = monthArray($langs, 0); // Get array + else $montharray = monthArray($langs, 1); + + $select_month = ''; + return $select_month; + } + + /** + * Return HTML combo list of years + * + * @param string $selected Preselected value (''=current year, -1=none, year otherwise) + * @param string $htmlname Name of HTML select object + * @param int $useempty Affiche valeur vide dans liste + * @param int $min_year Offset of minimum year into list (by default current year -10) + * @param int $max_year Offset of maximum year into list (by default current year + 5) + * @param int $offset Offset + * @param int $invert Invert + * @param string $option Option + * @return string + */ + function select_year($selected='',$htmlname='yearid',$useempty=0, $min_year=10, $max_year=5, $offset=0, $invert=0, $option='') + { + print $this->selectyear($selected,$htmlname,$useempty,$min_year,$max_year,$offset,$invert,$option); + } + + /** + * Return HTML combo list of years + * + * @param string $selected Preselected value (''=current year, -1=none, year otherwise) + * @param string $htmlname Name of HTML select object + * @param int $useempty Affiche valeur vide dans liste + * @param int $min_year Offset of minimum year into list (by default current year -10) + * @param int $max_year Offset of maximum year into list (by default current year + 5) + * @param int $offset Offset + * @param int $invert Invert + * @param string $option Option + * @return string + */ + function selectyear($selected='',$htmlname='yearid',$useempty=0, $min_year=10, $max_year=5, $offset=0, $invert=0, $option='') + { + $out=''; + + $currentyear = date("Y")+$offset; + $max_year = $currentyear+$max_year; + $min_year = $currentyear-$min_year; + if(empty($selected) && empty($useempty)) $selected = $currentyear; + + $out.= '\n"; + + return $out; + } + + /** + * Show form to select address + * + * @param int $page Page + * @param string $selected Id condition pre-selectionne + * @param int $socid Id of third party + * @param string $htmlname Nom du formulaire select + * @param string $origin Origine de l'appel pour pouvoir creer un retour + * @param int $originid Id de l'origine + * @return void + */ + function form_address($page, $selected, $socid, $htmlname='address_id', $origin='', $originid='') + { + global $langs,$conf; + global $form; + + if ($htmlname != "none") + { + print '
'; + print ''; + print ''; + $form->select_address($selected, $socid, $htmlname, 1); + print ''; + $langs->load("companies"); + print '   '.$langs->trans("AddAddress").''; + print '
'; + } + else + { + if ($selected) + { + require_once DOL_DOCUMENT_ROOT .'/societe/class/address.class.php'; + $address=new Address($this->db); + $result=$address->fetch_address($selected); + print ''.$address->label.''; + } + else + { + print " "; + } + } + } + + + + /** + * Get array with HTML tabs with boxes of a particular area including personalized choices of user. + * Class 'Form' must be known. + * + * @param User $user Object User + * @param String $areacode Code of area for pages ('0'=value for Home page) + * @return array array('selectboxlist'=>, 'boxactivated'=>, 'boxlista'=>, 'boxlistb'=>) + */ + static function getBoxesArea($user,$areacode) + { + global $conf,$langs,$db; + + include_once DOL_DOCUMENT_ROOT.'/core/class/infobox.class.php'; + + $confuserzone='MAIN_BOXES_'.$areacode; + + // $boxactivated will be array of boxes enabled into global setup + // $boxidactivatedforuser will be array of boxes choosed by user + + $selectboxlist=''; + $boxactivated=InfoBox::listBoxes($db, 'activated', $areacode, (empty($user->conf->$confuserzone)?null:$user), array(), 0); // Search boxes of common+user (or common only if user has no specific setup) + + $boxidactivatedforuser=array(); + foreach($boxactivated as $box) + { + if (empty($user->conf->$confuserzone) || $box->fk_user == $user->id) $boxidactivatedforuser[$box->id]=$box->id; // We keep only boxes to show for user + } + + // Define selectboxlist + $arrayboxtoactivatelabel=array(); + if (! empty($user->conf->$confuserzone)) + { + $boxorder=''; + $langs->load("boxes"); // Load label of boxes + foreach($boxactivated as $box) + { + if (! empty($boxidactivatedforuser[$box->id])) continue; // Already visible for user + $label=$langs->transnoentitiesnoconv($box->boxlabel); + if (preg_match('/graph/',$box->class)) $label.=' ('.$langs->trans("Graph").')'; + //$label = ''.$label; KO with select2. No html rendering. + $arrayboxtoactivatelabel[$box->id]=$label; // We keep only boxes not shown for user, to show into combo list + } + foreach($boxidactivatedforuser as $boxid) + { + if (empty($boxorder)) $boxorder.='A:'; + $boxorder.=$boxid.','; + } + + //var_dump($boxidactivatedforuser); + + // Class Form must have been already loaded + $selectboxlist.='
'; + $selectboxlist.=''; + $selectboxlist.=''; + $selectboxlist.=''; + $selectboxlist.=''; + $selectboxlist.=Form::selectarray('boxcombo', $arrayboxtoactivatelabel, -1, $langs->trans("ChooseBoxToAdd").'...', 0, 0, '', 0, 0, 0, 'ASC', 'maxwidth150onsmartphone', 0, 'hidden selected', 0, 1); + if (empty($conf->use_javascript_ajax)) $selectboxlist.=' '; + $selectboxlist.='
'; + $selectboxlist.=ajax_combobox("boxcombo"); + } + + // Javascript code for dynamic actions + if (! empty($conf->use_javascript_ajax)) + { + $selectboxlist.=''."\n"; + } + + // Define boxlista and boxlistb + $nbboxactivated=count($boxidactivatedforuser); + + if ($nbboxactivated) + { + $langs->load("boxes"); + $langs->load("projects"); + + $emptybox=new ModeleBoxes($db); + + $boxlista.="\n\n"; + $boxlista.='
'."\n"; + + // Define $box_max_lines + $box_max_lines=5; + if (! empty($conf->global->MAIN_BOXES_MAXLINES)) $box_max_lines=$conf->global->MAIN_BOXES_MAXLINES; + + $ii=0; + foreach ($boxactivated as $key => $box) + { + if ((! empty($user->conf->$confuserzone) && $box->fk_user == 0) || (empty($user->conf->$confuserzone) && $box->fk_user != 0)) continue; + if (empty($box->box_order) && $ii < ($nbboxactivated / 2)) $box->box_order='A'.sprintf("%02d",($ii+1)); // When box_order was not yet set to Axx or Bxx and is still 0 + if (preg_match('/^A/i',$box->box_order)) // column A + { + $ii++; + //print 'box_id '.$boxactivated[$ii]->box_id.' '; + //print 'box_order '.$boxactivated[$ii]->box_order.'
'; + // Show box + $box->loadBox($box_max_lines); + $boxlista.= $box->outputBox(); + } + } + + if (empty($conf->browser->phone)) + { + $emptybox->box_id='A'; + $emptybox->info_box_head=array(); + $emptybox->info_box_contents=array(); + $boxlista.= $emptybox->outputBox(array(),array()); + } + $boxlista.= "
\n"; + $boxlista.= "\n"; + + $boxlistb.= "\n\n"; + $boxlistb.= '\n"; + $boxlistb.= "\n"; + + } + + return array('selectboxlist'=>count($boxactivated)?$selectboxlist:'', 'boxactivated'=>$boxactivated, 'boxlista'=>$boxlista, 'boxlistb'=>$boxlistb); + } + + + /** + * Return a HTML select list of bank accounts + * + * @param string $htmlname Name of select zone + * @param string $dictionarytable Dictionary table + * @param string $keyfield Field for key + * @param string $labelfield Label field + * @param string $selected Selected value + * @param int $useempty 1=Add an empty value in list, 2=Add an empty value in list only if there is more than 2 entries. + * @param string $moreattrib More attributes on HTML select tag + * @return void + */ + function select_dictionary($htmlname,$dictionarytable,$keyfield='code',$labelfield='label',$selected='',$useempty=0,$moreattrib='') + { + global $langs, $conf; + + $langs->load("admin"); + + $sql = "SELECT rowid, ".$keyfield.", ".$labelfield; + $sql.= " FROM ".MAIN_DB_PREFIX.$dictionarytable; + $sql.= " ORDER BY ".$labelfield; + + dol_syslog(get_class($this)."::select_dictionary", LOG_DEBUG); + $result = $this->db->query($sql); + if ($result) + { + $num = $this->db->num_rows($result); + $i = 0; + if ($num) + { + print '"; + } + else + { + print $langs->trans("DictionaryEmpty"); + } + } + else { + dol_print_error($this->db); + } + } + +} + diff --git a/htdocs/core/class/smtps.class.php b/htdocs/core/class/smtps.class.php index 9e6250f9f8d..c92558bf1d3 100644 --- a/htdocs/core/class/smtps.class.php +++ b/htdocs/core/class/smtps.class.php @@ -271,7 +271,7 @@ class SMTPs { $this->_moreinheader = $_val; } - + /** * get trackid * @@ -291,7 +291,7 @@ class SMTPs { return $this->_moreinheader; } - + /** * Set errors to * @@ -411,7 +411,7 @@ class SMTPs function _server_authenticate() { global $conf; - + // Send the RFC2554 specified EHLO. // This improvment as provided by 'SirSir' to // accomodate both SMTP AND ESMTP capable servers @@ -462,7 +462,7 @@ class SMTPs { $this->_setErr(126, '"' . $host . '" does not support authenticated connections.'); return $_retVal; - } + } } // Send Authentication to Server // Check for errors along the way @@ -903,7 +903,7 @@ class SMTPs if ( $_strReplyTo ) $this->_msgReplyTo = $this->_strip_email($_strReplyTo); } - + /** * Retrieves the Address from which mail will be the reply-to * @@ -913,15 +913,15 @@ class SMTPs function getReplyTo($_part = true) { $_retValue = ''; - + if ( $_part === true ) $_retValue = $this->_msgReplyTo; else $_retValue = $this->_msgReplyTo[$_part]; - + return $_retValue; } - + /** * Inserts given addresses into structured format. * This method takes a list of given addresses, via an array @@ -1217,6 +1217,8 @@ class SMTPs */ function getHeader() { + global $conf; + $_header = 'From: ' . $this->getFrom('org') . "\r\n" . 'To: ' . $this->getTO() . "\r\n"; @@ -1233,13 +1235,13 @@ class SMTPs if ( $this->getBCC() ) $_header .= 'Bcc: ' . $this->getBCC() . "\r\n"; */ - + $host=$this->getHost(); $host=preg_replace('@tcp://@i','',$host); // Remove prefix $host=preg_replace('@ssl://@i','',$host); // Remove prefix $host=dol_getprefix('email'); - + //NOTE: Message-ID should probably contain the username of the user who sent the msg $_header .= 'Subject: ' . $this->getSubject() . "\r\n"; $_header .= 'Date: ' . date("r") . "\r\n"; @@ -1258,7 +1260,7 @@ class SMTPs } if ( $this->getMoreInHeader() ) $_header .= $this->getMoreInHeader(); // Value must include the "\r\n"; - + //$_header .= // 'Read-Receipt-To: ' . $this->getFrom( 'org' ) . "\r\n" // 'Return-Receipt-To: ' . $this->getFrom( 'org' ) . "\r\n"; @@ -1279,9 +1281,10 @@ class SMTPs $_header .= "Reply-To: ".$this->getReplyTo('addr') ."\r\n"; $_header .= 'X-Mailer: Dolibarr version ' . DOL_VERSION .' (using SMTPs Mailer)' . "\r\n"; + $_header .= 'X-Dolibarr-Option: '.($conf->global->MAIN_MAIL_USE_MULTI_PART?'MAIN_MAIL_USE_MULTI_PART':'No MAIN_MAIL_USE_MULTI_PART') . "\r\n"; $_header .= 'Mime-Version: 1.0' . "\r\n"; - + return $_header; } @@ -1310,17 +1313,17 @@ class SMTPs $strContentAltText = html_entity_decode(strip_tags($strContent)); $strContentAltText = rtrim(wordwrap($strContentAltText, 75, "\r\n")); } - + // Make RFC2045 Compliant //$strContent = rtrim(chunk_split($strContent)); // Function chunck_split seems ko if not used on a base64 content $strContent = rtrim(wordwrap($strContent, 75, "\r\n")); // TODO Using this method creates unexpected line break on text/plain content. - + $this->_msgContent[$strType] = array(); $this->_msgContent[$strType]['mimeType'] = $strMimeType; $this->_msgContent[$strType]['data'] = $strContent; $this->_msgContent[$strType]['dataText'] = $strContentAltText; - + if ( $this->getMD5flag() ) $this->_msgContent[$strType]['md5'] = dol_hash($strContent, 3); //} @@ -1334,7 +1337,7 @@ class SMTPs function getBodyContent() { global $conf; - + // Generate a new Boundary string $this->_setBoundary(); @@ -1382,7 +1385,7 @@ class SMTPs $content .= "\r\n"; $content .= "--" . $this->_getBoundary('mixed') . "\r\n"; - + if (key_exists('image', $this->_msgContent)) // If inline image found { $content.= 'Content-Type: multipart/alternative; boundary="'.$this->_getBoundary('alternative').'"' . "\r\n"; @@ -1390,7 +1393,7 @@ class SMTPs $content .= "--" . $this->_getBoundary('alternative') . "\r\n"; } - + // $this->_msgContent must be sorted with key 'text' or 'html' first then 'image' then 'attachment' @@ -1450,18 +1453,18 @@ class SMTPs $content.= "\r\n"; $content.= "--" . $this->_getBoundary('related') . "\r\n"; } - + if (! key_exists('image', $this->_msgContent) && $_content['dataText'] && ! empty($conf->global->MAIN_MAIL_USE_MULTI_PART)) // Add plain text message part before html part { $content.= 'Content-Type: multipart/alternative; boundary="'.$this->_getBoundary('alternative').'"' . "\r\n"; $content .= "\r\n"; $content .= "--" . $this->_getBoundary('alternative') . "\r\n"; - + $content.= "Content-Type: text/plain; charset=" . $this->getCharSet() . "\r\n"; $content.= "\r\n". $_content['dataText'] . "\r\n"; $content.= "--" . $this->_getBoundary('alternative') . "\r\n"; - } - + } + $content .= 'Content-Type: ' . $_content['mimeType'] . '; ' // . 'charset="' . $this->getCharSet() . '"'; . 'charset=' . $this->getCharSet() . ''; @@ -1483,7 +1486,7 @@ class SMTPs { $content.= "--" . $this->_getBoundary('alternative') . "--". "\r\n"; } - + $content .= "\r\n"; } } diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 77502f1737c..0b8282ad5b6 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -393,6 +393,7 @@ function dol_dir_is_emtpy($folder) * * @param string $file Filename * @return int <0 if KO, Number of lines in files if OK + * @see dol_nboflines */ function dol_count_nb_of_line($file) { @@ -448,12 +449,12 @@ function dol_filemtime($pathoffile) * Make replacement of strings into a file. * * @param string $srcfile Source file (can't be a directory) - * @param array $arrayreplacement Array with strings to replace + * @param array $arrayreplacement Array with strings to replace. Example: array('valuebefore'=>'valueafter', ...) * @param string $destfile Destination file (can't be a directory). If empty, will be same than source file. * @param int $newmask Mask for new file (0 by default means $conf->global->MAIN_UMASK). Example: '0666' * @param int $indexdatabase Index new file into database. * @return int <0 if error, 0 if nothing done (dest file already exists), >0 if OK - * @see dolCopyr + * @see dolCopyr dolReplaceRegExInFile */ function dolReplaceInFile($srcfile, $arrayreplacement, $destfile='', $newmask=0, $indexdatabase=0) { @@ -514,6 +515,23 @@ function dolReplaceInFile($srcfile, $arrayreplacement, $destfile='', $newmask=0, return 1; } +/** + * Make replacement of strings into a file. + * + * @param string $srcfile Source file (can't be a directory) + * @param array $arrayreplacement Array with strings to replace. Example: array('valuebefore'=>'valueafter', ...) + * @param string $destfile Destination file (can't be a directory). If empty, will be same than source file. + * @param int $newmask Mask for new file (0 by default means $conf->global->MAIN_UMASK). Example: '0666' + * @param int $indexdatabase Index new file into database. + * @return int <0 if error, 0 if nothing done (dest file already exists), >0 if OK + * @see dolCopyr dolReplaceInFile + */ +function dolReplaceRegExInFile($srcfile, $arrayreplacement, $destfile='', $newmask=0, $indexdatabase=0) +{ + // TODO + +} + /** * Copy a file to another file. * diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index fae3c4eae5e..85f3ed199e9 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -624,18 +624,26 @@ function dol_buildpath($path, $type=0) /** * Create a clone of instance of object (new instance with same value for properties) - * Property that are reference are also new object (true clone) + * With native = 0: Property that are reference are also new object (true clone). This means $this->db is not valid. + * With native = 1: Use PHP clone. Property that are reference are same pointer. This means $this->db is still valid. * * @param object $object Object to clone + * @param int $native Native method or true method * @return object Object clone * @see https://php.net/manual/language.oop5.cloning.php */ -function dol_clone($object) +function dol_clone($object, $native=0) { //dol_syslog(__FUNCTION__ . " is deprecated", LOG_WARNING); - //$myclone = clone $object; // PHP clone is a shallow copy only, not a real clone, so properties of references will keep references (refer to the same target/variable - $myclone=unserialize(serialize($object)); + if (empty($native)) + { + $myclone=unserialize(serialize($object)); + } + else + { + $myclone = clone $object; // PHP clone is a shallow copy only, not a real clone, so properties of references will keep references (refer to the same target/variable) + } return $myclone; } @@ -1127,7 +1135,7 @@ function dol_get_fiche_end($notab=0) * @param string $paramid Name of parameter to use to name the id into the URL next/previous link * @param string $morehtml More html content to output just before the nav bar * @param int $shownav Show Condition (navigation is shown if value is 1) - * @param string $fieldid Nom du champ en base a utiliser pour select next et previous (we make the select max and min on this field) + * @param string $fieldid Nom du champ en base a utiliser pour select next et previous (we make the select max and min on this field). Use 'none' for no prev/next search. * @param string $fieldref Nom du champ objet ref (object->ref) a utiliser pour select next et previous * @param string $morehtmlref More html to show after ref * @param string $moreparam More param to add in nav link url. @@ -1278,7 +1286,8 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r if ($object->element == 'project' && ! $object->public) $picto = 'project'; // instead of projectpub $nophoto=img_picto('', 'object_'.$picto, '', false, 1); } - $morehtmlleft.='
No photo
'; + $morehtmlleft.=''; + $morehtmlleft.='
No photo
'; $morehtmlleft.=''; } } @@ -2545,7 +2554,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ if ($pictoisfullpath) { // Clean parameters - if (! preg_match('/(\.png|\.gif)$/i',$picto)) $picto .= '.png'; + if (! preg_match('/(\.png|\.gif|\.svg)$/i',$picto)) $picto .= '.png'; $fullpathpicto = $picto; } else @@ -2567,7 +2576,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ } // Clean parameters - if (! preg_match('/(\.png|\.gif)$/i',$picto)) $picto .= '.png'; + if (! preg_match('/(\.png|\.gif|\.svg)$/i',$picto)) $picto .= '.png'; // If alt path are defined, define url where img file is, according to physical path foreach ($conf->file->dol_document_root as $type => $dirroot) // ex: array(["main"]=>"/home/maindir/htdocs", ["alt0"]=>"/home/moddir0/htdocs", ...) { @@ -4766,22 +4775,57 @@ function dol_string_nohtmltag($StringHtml,$removelinefeed=1,$pagecodeto='UTF-8') * Return first line of text. Cut will depends if content is HTML or not. * * @param string $text Input text + * @param int $nboflines Nb of lines to get (default is 1 = first line only) * @return string Output text * @see dol_nboflines_bis, dol_string_nohtmltag, dol_escape_htmltag */ -function dolGetFirstLineOfText($text) +function dolGetFirstLineOfText($text, $nboflines=1) { - if (dol_textishtml($text)) + if ($nboflines == 1) { - $firstline=preg_replace('/]*>.*$/s','',$text); // The s pattern modifier means the . can match newline characters - $firstline=preg_replace('/]*>.*$/s','',$firstline); // The s pattern modifier means the . can match newline characters + if (dol_textishtml($text)) + { + $firstline=preg_replace('/]*>.*$/s','',$text); // The s pattern modifier means the . can match newline characters + $firstline=preg_replace('/]*>.*$/s','',$firstline); // The s pattern modifier means the . can match newline characters + } + else + { + $firstline=preg_replace('/[\n\r].*/','',$text); + } + return $firstline.((strlen($firstline) != strlen($text))?'...':''); } else { - $firstline=preg_replace('/[\n\r].*/','',$text); + $ishtml=0; + if (dol_textishtml($text)) + { + $text=preg_replace('/\n/','',$text); + $ishtml=1; + $repTable = array("\t" => " ", "\n" => " ", "\r" => " ", "\0" => " ", "\x0B" => " "); + } + else + { + $repTable = array("\t" => " ", "\n" => "
", "\r" => " ", "\0" => " ", "\x0B" => " "); + } + + $text = strtr($text, $repTable); + if ($charset == 'UTF-8') { $pattern = '/(]*>)/Uu'; } // /U is to have UNGREEDY regex to limit to one html tag. /u is for UTF8 support + else $pattern = '/(]*>)/U'; // /U is to have UNGREEDY regex to limit to one html tag. + $a = preg_split($pattern, $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + + $firstline=''; + $i=0; + $nba = count($a); // 2x nb of lines in $a because $a contains also a line for each new line separator + while (($i < $nba) && ($i < ($nboflines * 2))) + { + if ($i % 2 == 0) $firstline .= $a[$i]; + elseif (($i < (($nboflines * 2) - 1)) && ($i < ($nba - 1))) $firstline .= ($ishtml?"
\n":"\n"); + $i++; + } + unset($a); + return $firstline.(($i < $nba)?'...':''); } - return $firstline.((strlen($firstline) != strlen($text))?'...':''); } @@ -4943,7 +4987,7 @@ function dol_nboflines($s,$maxchar=0) /** - * Return nb of lines of a formated text with \n and
(we can't have both \n and br) + * Return nb of lines of a formated text with \n and
(WARNING: string must not have mixed \n and br separators) * * @param string $text Text * @param int $maxlinesize Largeur de ligne en caracteres (ou 0 si pas de limite - defaut) @@ -4979,6 +5023,8 @@ function dol_nboflines_bis($text,$maxlinesize=0,$charset='UTF-8') } } } + + unset($a); return $nblines; } diff --git a/htdocs/core/lib/modulebuilder.lib.php b/htdocs/core/lib/modulebuilder.lib.php index af9ab67d8fe..1df10e6a9c7 100644 --- a/htdocs/core/lib/modulebuilder.lib.php +++ b/htdocs/core/lib/modulebuilder.lib.php @@ -77,6 +77,8 @@ function rebuildObjectClass($destdir, $module, $objectname, $newmask) $i++; $typephp=''; $texttoinsert.= "\t\t'".$key."' => array('type'=>'".$val['type']."', 'label'=>'".$val['label']."',"; + $texttoinsert.= " 'visible'=>".($val['visible']?$val['visible']:0).","; + $texttoinsert.= " 'enabled'=>".($val['enabled']?$val['enabled']:0).","; if ($val['position']) $texttoinsert.= " 'position'=>".$val['position'].","; if ($val['notnull']) $texttoinsert.= " 'notnull'=>".$val['notnull'].","; if ($val['index']) $texttoinsert.= " 'index'=>".$val['index'].","; diff --git a/htdocs/core/lib/website.lib.php b/htdocs/core/lib/website.lib.php index 37f01a0ffe3..354da07c6f2 100644 --- a/htdocs/core/lib/website.lib.php +++ b/htdocs/core/lib/website.lib.php @@ -31,17 +31,17 @@ function dolWebsiteOutput($content) { global $db, $langs, $conf, $user; - global $dolibarr_main_url_root; + global $dolibarr_main_url_root, $dolibarr_main_data_root; dol_syslog("dolWebsiteOutput start"); + // 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 + if (! defined('USEDOLIBARRSERVER')) { - // 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 - $symlinktomediaexists=1; // Make a change into HTML code to allow to include images from medias directory correct with direct link for virtual server @@ -55,12 +55,57 @@ function dolWebsiteOutput($content) } else { - $content=preg_replace('/()/', '\1medias/\4\5', $content, -1, $nbrep); + $content=preg_replace('/()/', '\1medias/\4\5', $content, -1, $nbrep); + $content=preg_replace('/(url\(["\']?)[^\)]*viewimage\.php([^\)]*)modulepart=medias([^\)]*)file=([^\)]*)(["\']?\))/', '\1medias/\4\5', $content, -1, $nbrep); } } + else + { + global $website; + + // Replace relative link / with dolibarr URL + $content=preg_replace('/(href=")\/\"/', '\1'.DOL_URL_ROOT.'/public/websites/index.php?website='.$website->ref.'&pageid='.$website->fk_default_home.'"', $content, -1, $nbrep); + // Replace relative link /xxx.php with dolibarr URL + $content=preg_replace('/(href=")\/?([^\"]*)(\.php\")/', '\1'.DOL_URL_ROOT.'/public/websites/index.php?website='.$website->ref.'&pageref=\2"', $content, -1, $nbrep); + } dol_syslog("dolWebsiteOutput end"); print $content; } + +/** + * Clean an HTML page to report only content, so we can include it into another page + * It outputs content of file sanitized from html and body part. + * + * @param string $contentfile Path to file to include (must include website root. Example: 'mywebsite/mypage.php') + * @return void + */ +function dolIncludeHtmlContent($contentfile) +{ + global $conf, $db, $langs, $mysoc, $user, $website; + global $includehtmlcontentopened; + + $MAXLEVEL=20; + + $fullpathfile=DOL_DATA_ROOT.'/websites/'.$contentfile; + //$content = file_get_contents($fullpathfile); + //print preg_replace(array('/^.*]*>/ims','/<\/body>.*$/ims'), array('', ''), $content);*/ + + if (empty($includehtmlcontentopened)) $includehtmlcontentopened=0; + $includehtmlcontentopened++; + if ($includehtmlcontentopened > $MAXLEVEL) + { + print 'ERROR: RECURSIVE CONTENT LEVEL. Depth of recursive call is more than the limit of '.$MAXLEVEL.".\n"; + return; + } + $res = include $fullpathfile; // Include because we want to execute code content + if (! $res) + { + print 'ERROR: FAILED TO INCLUDE PAGE '.$contentfile.".\n"; + } + + $includehtmlcontentopened--; +} + diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index 2fcf1fa4ff2..530be07da39 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -871,7 +871,7 @@ function print_left_eldy_menu($db,$menu_array_before,$menu_array_after,&$tabMenu // VAT if (empty($conf->global->TAX_DISABLE_VAT_MENUS)) { - $newmenu->add("/compta/tva/index.php?leftmenu=tax_vat&mainmenu=accountancy",$langs->trans("VAT"),1,$user->rights->tax->charges->lire, '', $mainmenu, 'tax_vat'); + $newmenu->add("/compta/tva/index.php?leftmenu=tax_vat&mainmenu=accountancy",$langs->transcountry("VAT", $mysoc->country_code),1,$user->rights->tax->charges->lire, '', $mainmenu, 'tax_vat'); if ($usemenuhider || empty($leftmenu) || preg_match('/^tax_vat/i',$leftmenu)) $newmenu->add("/compta/tva/card.php?leftmenu=tax_vat&action=create",$langs->trans("New"),2,$user->rights->tax->charges->creer); if ($usemenuhider || empty($leftmenu) || preg_match('/^tax_vat/i',$leftmenu)) $newmenu->add("/compta/tva/reglement.php?leftmenu=tax_vat",$langs->trans("List"),2,$user->rights->tax->charges->lire); if ($usemenuhider || empty($leftmenu) || preg_match('/^tax_vat/i',$leftmenu)) $newmenu->add("/compta/tva/clients.php?leftmenu=tax_vat", $langs->trans("ReportByCustomers"), 2, $user->rights->tax->charges->lire); diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index 98bd412abc2..a3f8676fb65 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -1447,55 +1447,55 @@ class DolibarrModules // Can not be abstract, because we need to insta * * @return int Error count (0 if ok) */ - function insert_tabs() - { - global $conf; + function insert_tabs() + { + global $conf; - $err=0; + $err=0; - if (! empty($this->tabs)) - { - $i=0; - foreach ($this->tabs as $key => $value) - { - if (is_array($value) && count($value) == 0) continue; // Discard empty arrays + if (! empty($this->tabs)) + { + $i=0; + foreach ($this->tabs as $key => $value) + { + if (is_array($value) && count($value) == 0) continue; // Discard empty arrays - $entity=$conf->entity; - $newvalue = $value; + $entity=$conf->entity; + $newvalue = $value; - if (is_array($value)) - { - $newvalue = $value['data']; - if (isset($value['entity'])) $entity = $value['entity']; - } + if (is_array($value)) + { + $newvalue = $value['data']; + if (isset($value['entity'])) $entity = $value['entity']; + } - if ($newvalue) - { - $sql = "INSERT INTO ".MAIN_DB_PREFIX."const ("; - $sql.= "name"; - $sql.= ", type"; - $sql.= ", value"; - $sql.= ", note"; - $sql.= ", visible"; - $sql.= ", entity"; - $sql.= ")"; - $sql.= " VALUES ("; - $sql.= $this->db->encrypt($this->const_name."_TABS_".$i,1); - $sql.= ", 'chaine'"; - $sql.= ", ".$this->db->encrypt($value,1); - $sql.= ", null"; - $sql.= ", '0'"; - $sql.= ", ".$conf->entity; - $sql.= ")"; + if ($newvalue) + { + $sql = "INSERT INTO ".MAIN_DB_PREFIX."const ("; + $sql.= "name"; + $sql.= ", type"; + $sql.= ", value"; + $sql.= ", note"; + $sql.= ", visible"; + $sql.= ", entity"; + $sql.= ")"; + $sql.= " VALUES ("; + $sql.= $this->db->encrypt($this->const_name."_TABS_".$i,1); + $sql.= ", 'chaine'"; + $sql.= ", ".$this->db->encrypt($newvalue,1); + $sql.= ", null"; + $sql.= ", '0'"; + $sql.= ", ".$entity; + $sql.= ")"; - dol_syslog(get_class($this)."::insert_tabs", LOG_DEBUG); - $this->db->query($sql); - } - $i++; - } - } - return $err; - } + dol_syslog(get_class($this)."::insert_tabs", LOG_DEBUG); + $this->db->query($sql); + } + $i++; + } + } + return $err; + } /** * Adds constants diff --git a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php index 396ac54e9b5..a3ae305549d 100644 --- a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php +++ b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php @@ -45,28 +45,28 @@ class pdf_einstein extends ModelePDFCommandes * @var DoliDb Database handler */ public $db; - + /** * @var string model name */ public $name; - + /** * @var string model description (short text) */ public $description; - + /** * @var string document type */ public $type; - + /** * @var array() Minimum version of PHP required by module. * e.g.: PHP ≥ 5.3 = array(5, 3) */ - public $phpmin = array(5, 2); - + public $phpmin = array(5, 2); + /** * Dolibarr version of the loaded document * @public string @@ -240,11 +240,11 @@ class pdf_einstein extends ModelePDFCommandes $pdf=pdf_getInstance($this->format); $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance $pdf->SetAutoPageBreak(1,0); - + $heightforinfotot = 40; // Height reserved to output the info and total part $heightforfreetext= (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT)?$conf->global->MAIN_PDF_FREETEXT_HEIGHT:5); // Height reserved to output the free text on last page $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin) - + if (class_exists('TCPDF')) { $pdf->setPrintHeader(false); @@ -263,10 +263,10 @@ class pdf_einstein extends ModelePDFCommandes $pdf->SetDrawColor(128,128,128); $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref)); - $pdf->SetSubject($outputlangs->transnoentities("Order")); + $pdf->SetSubject($outputlangs->transnoentities("PdfOrderTitle")); $pdf->SetCreator("Dolibarr ".DOL_VERSION); $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs))); - $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("Order")." ".$outputlangs->convToOutputCharset($object->thirdparty->name)); + $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("PdfOrderTitle")." ".$outputlangs->convToOutputCharset($object->thirdparty->name)); if (! empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) $pdf->SetCompression(false); $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right @@ -317,16 +317,16 @@ class pdf_einstein extends ModelePDFCommandes $pdf->writeHTMLCell(190, 3, $this->posxdesc-1, $tab_top-1, dol_htmlentitiesbr($desc_incoterms), 0, 1); $nexY = $pdf->GetY(); $height_incoterms=$nexY-$tab_top; - + // Rect prend une longueur en 3eme param $pdf->SetDrawColor(192,192,192); $pdf->Rect($this->marge_gauche, $tab_top-1, $this->page_largeur-$this->marge_gauche-$this->marge_droite, $height_incoterms+1); - + $tab_top = $nexY+6; $height_incoterms += 4; } } - + // Affiche notes $notetoshow=empty($object->note_public)?'':$object->note_public; if (! empty($conf->global->MAIN_ADD_SALE_REP_SIGNATURE_IN_NOTE)) @@ -478,7 +478,7 @@ class pdf_einstein extends ModelePDFCommandes // Collecte des totaux par valeur de tva dans $this->tva["taux"]=total_tva if ($conf->multicurrency->enabled && $object->multicurrency_tx != 1) $tvaligne=$object->lines[$i]->multicurrency_total_tva; else $tvaligne=$object->lines[$i]->total_tva; - + $localtax1ligne=$object->lines[$i]->total_localtax1; $localtax2ligne=$object->lines[$i]->total_localtax2; $localtax1_rate=$object->lines[$i]->localtax1_tx; @@ -585,7 +585,7 @@ class pdf_einstein extends ModelePDFCommandes $posy=$this->_tableau_versements($pdf, $object, $posy, $outputlangs); } */ - + // Pied de page $this->_pagefoot($pdf,$object,$outputlangs); if (method_exists($pdf,'AliasNbPages')) $pdf->AliasNbPages(); @@ -1201,7 +1201,7 @@ class pdf_einstein extends ModelePDFCommandes * @param string $titlekey Translation key to show as title of document * @return void */ - function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $titlekey="Order") + function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $titlekey="PdfOrderTitle") { global $conf,$langs,$hookmanager; @@ -1294,7 +1294,7 @@ class pdf_einstein extends ModelePDFCommandes $pdf->MultiCell(100, 3, $langs->trans("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); } } - + $posy+=2; // Show list of linked objects diff --git a/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php b/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php index 64d0da9b5fd..f9dac51389f 100644 --- a/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php +++ b/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php @@ -211,7 +211,7 @@ class doc_generic_contract_odt extends ModelePDFContract if (! is_object($object)) { $id = $object; - $object = new Contract($this->db); + $object = new Contrat($this->db); $result=$object->fetch($id); if ($result < 0) { diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index 0de3a8df3d7..6c10f67507f 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -1,13 +1,13 @@ * Copyright (C) 2005-2012 Regis Houssin - * Copyright (C) 2008 Raphael Bertrand + * Copyright (C) 2008 Raphael Bertrand * Copyright (C) 2010-2014 Juanjo Menent - * Copyright (C) 2012 Christophe Battarel - * Copyright (C) 2012 Cédric Salvador - * Copyright (C) 2012-2014 Raphaël Doursenaud - * Copyright (C) 2015 Marcos García - * Copyright (C) 2017 Ferran Marcet + * Copyright (C) 2012 Christophe Battarel + * Copyright (C) 2012 Cédric Salvador + * Copyright (C) 2012-2014 Raphaël Doursenaud + * Copyright (C) 2015 Marcos García + * Copyright (C) 2017 Ferran Marcet * * 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 @@ -255,16 +255,16 @@ class pdf_crabe extends ModelePDFFactures // Set nblignes with the new facture lines content after hook $nblignes = count($object->lines); $nbpayments = count($object->getListOfPayments()); - + // Create pdf instance $pdf=pdf_getInstance($this->format); $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance $pdf->SetAutoPageBreak(1,0); - + $heightforinfotot = 50+(4*$nbpayments); // Height reserved to output the info and total part and payment part $heightforfreetext= (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT)?$conf->global->MAIN_PDF_FREETEXT_HEIGHT:5); // Height reserved to output the free text on last page $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin) - + if (class_exists('TCPDF')) { $pdf->setPrintHeader(false); @@ -284,10 +284,10 @@ class pdf_crabe extends ModelePDFFactures $pdf->SetDrawColor(128,128,128); $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref)); - $pdf->SetSubject($outputlangs->transnoentities("Invoice")); + $pdf->SetSubject($outputlangs->transnoentities("PdfInvoiceTitle")); $pdf->SetCreator("Dolibarr ".DOL_VERSION); $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs))); - $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("Invoice")." ".$outputlangs->convToOutputCharset($object->thirdparty->name)); + $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("PdfInvoiceTitle")." ".$outputlangs->convToOutputCharset($object->thirdparty->name)); if (! empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) $pdf->SetCompression(false); $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right @@ -509,7 +509,7 @@ class pdf_crabe extends ModelePDFFactures $qty = pdf_getlineqty($object, $i, $outputlangs, $hidedetails); $pdf->SetXY($this->posxqty, $curY); // Enough for 6 chars - + if ($this->situationinvoice) { $pdf->MultiCell($this->posxprogress-$this->posxqty-0.8, 4, $qty, 0, 'R'); @@ -769,7 +769,7 @@ class pdf_crabe extends ModelePDFFactures $pdf->SetFont('','', $default_font_size - 4); - + // Loop on each deposits and credit notes included $sql = "SELECT re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc,"; $sql.= " re.description, re.fk_facture_source,"; @@ -822,7 +822,7 @@ class pdf_crabe extends ModelePDFFactures $sql.= " WHERE pf.fk_paiement = p.rowid AND pf.fk_facture = ".$object->id; //$sql.= " WHERE pf.fk_paiement = p.rowid AND pf.fk_facture = 1"; $sql.= " ORDER BY p.datep"; - + $resql=$this->db->query($sql); if ($resql) { @@ -1052,7 +1052,7 @@ class pdf_crabe extends ModelePDFFactures $pdf->SetFillColor(255,255,255); $pdf->SetXY($col1x, $tab2_top + 0); $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("TotalHT"), 0, 'L', 1); - + $total_ht = ($conf->multicurrency->enabled && $object->mylticurrency_tx != 1 ? $object->multicurrency_total_ht : $object->total_ht); $pdf->SetXY($col2x, $tab2_top + 0); $pdf->MultiCell($largcol2, $tab2_hl, price($sign * ($total_ht + (! empty($object->remise)?$object->remise:0)), 0, $outputlangs), 0, 'R', 1); @@ -1071,7 +1071,7 @@ class pdf_crabe extends ModelePDFFactures else { // FIXME amount of vat not supported with multicurrency - + //Local tax 1 before VAT //if (! empty($conf->global->FACTURE_LOCAL_TAX1_OPTION) && $conf->global->FACTURE_LOCAL_TAX1_OPTION=='localtax1on') //{ @@ -1141,26 +1141,26 @@ class pdf_crabe extends ModelePDFFactures } //} - + // VAT // Situations totals migth be wrong on huge amounts if ($object->situation_cycle_ref && $object->situation_counter > 1) { - + $sum_pdf_tva = 0; foreach($this->tva as $tvakey => $tvaval){ $sum_pdf_tva+=$tvaval; // sum VAT amounts to compare to object } - + if($sum_pdf_tva!=$object->total_tva) { // apply coef to recover the VAT object amount (the good one) $coef_fix_tva = $object->total_tva / $sum_pdf_tva; - + foreach($this->tva as $tvakey => $tvaval) { $this->tva[$tvakey]=$tvaval * $coef_fix_tva; } } - + } - + foreach($this->tva as $tvakey => $tvaval) { if ($tvakey != 0) // On affiche pas taux 0 @@ -1416,7 +1416,7 @@ class pdf_crabe extends ModelePDFFactures if (empty($hidetop)) { $pdf->SetXY($this->posxqty-1, $tab_top+1); - + if($this->situationinvoice) { $pdf->MultiCell($this->posxprogress-$this->posxqty-1,2, $outputlangs->transnoentities("Qty"),'','C'); @@ -1430,14 +1430,14 @@ class pdf_crabe extends ModelePDFFactures $pdf->MultiCell($this->posxdiscount-$this->posxqty-1,2, $outputlangs->transnoentities("Qty"),'','C'); } } - + if ($this->situationinvoice) { $pdf->line($this->posxprogress - 1, $tab_top, $this->posxprogress - 1, $tab_top + $tab_height); - + if (empty($hidetop)) { - + $pdf->SetXY($this->posxprogress, $tab_top+1); - + if($conf->global->PRODUCT_USE_UNITS) { $pdf->MultiCell($this->posxunit-$this->posxprogress,2, $outputlangs->transnoentities("Progress"),'','C'); @@ -1450,9 +1450,9 @@ class pdf_crabe extends ModelePDFFactures { $pdf->MultiCell($this->postotalht-$this->posxprogress,2, $outputlangs->transnoentities("Progress"),'','C'); } - + } - + } if($conf->global->PRODUCT_USE_UNITS) { @@ -1559,7 +1559,7 @@ class pdf_crabe extends ModelePDFFactures $pdf->SetFont('','B', $default_font_size + 3); $pdf->SetXY($posx,$posy); $pdf->SetTextColor(0,0,60); - $title=$outputlangs->transnoentities("Invoice"); + $title=$outputlangs->transnoentities("PdfInvoiceTitle"); if ($object->type == 1) $title=$outputlangs->transnoentities("InvoiceReplacement"); if ($object->type == 2) $title=$outputlangs->transnoentities("InvoiceAvoir"); if ($object->type == 3) $title=$outputlangs->transnoentities("InvoiceDeposit"); @@ -1573,10 +1573,10 @@ class pdf_crabe extends ModelePDFFactures $pdf->SetXY($posx,$posy); $pdf->SetTextColor(0,0,60); $textref=$outputlangs->transnoentities("Ref")." : " . $outputlangs->convToOutputCharset($object->ref); - if ($object->statut == Facture::STATUS_DRAFT) + if ($object->statut == Facture::STATUS_DRAFT) { $pdf->SetTextColor(128,0,0); - $textref.=' - '.$outputlangs->trans("NotValidated"); + $textref.=' - '.$outputlangs->transnoentities("NotValidated"); } $pdf->MultiCell($w, 4, $textref, '', 'R'); @@ -1635,7 +1635,7 @@ class pdf_crabe extends ModelePDFFactures $pdf->SetTextColor(0,0,60); $pdf->MultiCell($w, 3, $outputlangs->transnoentities("DatePointOfTax")." : " . dol_print_date($object->date_pointoftax,"day",false,$outputlangs), '', 'R'); } - + if ($object->type != 2) { $posy+=3; @@ -1663,10 +1663,10 @@ class pdf_crabe extends ModelePDFFactures $posy+=4; $pdf->SetXY($posx,$posy); $pdf->SetTextColor(0,0,60); - $pdf->MultiCell($w, 3, $langs->trans("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); + $pdf->MultiCell($w, 3, $langs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); } } - + $posy+=1; // Show list of linked objects diff --git a/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php b/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php index 0339f2ea255..130aa90ecfd 100644 --- a/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php +++ b/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php @@ -167,7 +167,7 @@ class doc_generic_proposal_odt extends ModelePDFPropales $texte.=$file['name'].'
'; } $texte.='
'; - + if ($conf->global->MAIN_PROPAL_CHOOSE_ODT_DOCUMENT > 0) { // Model for creation @@ -252,7 +252,7 @@ class doc_generic_proposal_odt extends ModelePDFPropales if (! is_object($object)) { $id = $object; - $object = new Propale($this->db); + $object = new Propal($this->db); $result=$object->fetch($id); if ($result < 0) { diff --git a/htdocs/core/modules/propale/doc/pdf_azur.modules.php b/htdocs/core/modules/propale/doc/pdf_azur.modules.php index 3eb284ec7fc..250796dd9d5 100644 --- a/htdocs/core/modules/propale/doc/pdf_azur.modules.php +++ b/htdocs/core/modules/propale/doc/pdf_azur.modules.php @@ -273,7 +273,7 @@ class pdf_azur extends ModelePDFPropales $pdf=pdf_getInstance($this->format); $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance $pdf->SetAutoPageBreak(1,0); - + if (class_exists('TCPDF')) { $pdf->setPrintHeader(false); @@ -292,10 +292,10 @@ class pdf_azur extends ModelePDFPropales $pdf->SetDrawColor(128,128,128); $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref)); - $pdf->SetSubject($outputlangs->transnoentities("CommercialProposal")); + $pdf->SetSubject($outputlangs->transnoentities("PdfCommercialProposalTitle")); $pdf->SetCreator("Dolibarr ".DOL_VERSION); $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs))); - $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("CommercialProposal")." ".$outputlangs->convToOutputCharset($object->thirdparty->name)); + $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("PdfCommercialProposalTitle")." ".$outputlangs->convToOutputCharset($object->thirdparty->name)); if (! empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) $pdf->SetCompression(false); $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right @@ -322,19 +322,19 @@ class pdf_azur extends ModelePDFPropales $pdf->AddPage(); if (! empty($tplidx)) $pdf->useTemplate($tplidx); $pagenb++; - + $heightforinfotot = 40; // Height reserved to output the info and total part $heightforsignature = empty($conf->global->PROPAL_DISABLE_SIGNATURE)?(pdfGetHeightForHtmlContent($pdf, $outputlangs->transnoentities("ProposalCustomerSignature"))+10):0; $heightforfreetext= (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT)?$conf->global->MAIN_PDF_FREETEXT_HEIGHT:5); // Height reserved to output the free text on last page $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin) - //print $heightforinfotot + $heightforsignature + $heightforfreetext + $heightforfooter;exit; - + //print $heightforinfotot + $heightforsignature + $heightforfreetext + $heightforfooter;exit; + $this->_pagehead($pdf, $object, 1, $outputlangs); $pdf->SetFont('','', $default_font_size - 1); $pdf->MultiCell(0, 3, ''); // Set interline to 3 $pdf->SetTextColor(0,0,0); - + $tab_top = 90; $tab_top_newpage = (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)?42:10); $tab_height = 130; @@ -383,7 +383,7 @@ class pdf_azur extends ModelePDFPropales $notetoshow.='Affaire suivi par '.$tmpuser->getFullName($langs); if ($tmpuser->email) $notetoshow.=', Mail: '.$tmpuser->email; if ($tmpuser->office_phone) $notetoshow.=', Tel: '.$tmpuser->office_phone; - } + } if ($notetoshow) { $tab_top = 88 + $height_incoterms; @@ -452,7 +452,7 @@ class pdf_azur extends ModelePDFPropales $curX = $this->posxdesc-1; $showpricebeforepagebreak=1; - + $pdf->startTransaction(); pdf_writelinedesc($pdf,$object,$i,$outputlangs,$this->posxpicture-$curX,3,$curX,$curY,$hideref,$hidedesc); $pageposafter=$pdf->getPage(); @@ -554,14 +554,14 @@ class pdf_azur extends ModelePDFPropales // Collecte des totaux par valeur de tva dans $this->tva["taux"]=total_tva if ($conf->multicurrency->enabled && $object->multicurrency_tx != 1) $tvaligne=$object->lines[$i]->multicurrency_total_tva; else $tvaligne=$object->lines[$i]->total_tva; - + $localtax1ligne=$object->lines[$i]->total_localtax1; $localtax2ligne=$object->lines[$i]->total_localtax2; $localtax1_rate=$object->lines[$i]->localtax1_tx; $localtax2_rate=$object->lines[$i]->localtax2_tx; $localtax1_type=$object->lines[$i]->localtax1_type; - $localtax2_type=$object->lines[$i]->localtax2_type; - + $localtax2_type=$object->lines[$i]->localtax2_type; + if ($object->remise_percent) $tvaligne-=($tvaligne*$object->remise_percent)/100; if ($object->remise_percent) $localtax1ligne-=($localtax1ligne*$object->remise_percent)/100; if ($object->remise_percent) $localtax2ligne-=($localtax2ligne*$object->remise_percent)/100; @@ -669,7 +669,7 @@ class pdf_azur extends ModelePDFPropales { $posy=$this->_signature_area($pdf, $object, $posy, $outputlangs); } - + // Pied de page $this->_pagefoot($pdf,$object,$outputlangs); if (method_exists($pdf,'AliasNbPages')) $pdf->AliasNbPages(); @@ -1428,7 +1428,7 @@ class pdf_azur extends ModelePDFPropales $pdf->SetFont('','B',$default_font_size + 3); $pdf->SetXY($posx,$posy); $pdf->SetTextColor(0,0,60); - $title=$outputlangs->transnoentities("CommercialProposal"); + $title=$outputlangs->transnoentities("PdfCommercialProposalTitle"); $pdf->MultiCell(100, 4, $title, '', 'R'); $pdf->SetFont('','B',$default_font_size); @@ -1481,7 +1481,7 @@ class pdf_azur extends ModelePDFPropales $pdf->MultiCell(100, 3, $langs->trans("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); } } - + $posy+=2; // Show list of linked objects diff --git a/htdocs/core/tpl/bloc_showhide.tpl.php b/htdocs/core/tpl/bloc_showhide.tpl.php index 2c5d71c79d5..80b928815cb 100644 --- a/htdocs/core/tpl/bloc_showhide.tpl.php +++ b/htdocs/core/tpl/bloc_showhide.tpl.php @@ -21,43 +21,45 @@ if (isset($parameters['showblocbydefault'])) $hide=(empty($parameters['showblocb if (isset($object->extraparams[$blocname]['showhide'])) $hide = (empty($object->extraparams[$blocname]['showhide']) ? true : false); ?> + - +'."\n"; +print '$(document).ready(function() {'."\n"; +print '$("#hide-'.$blocname.'").click(function(){'."\n"; +print ' setShowHide(0);'."\n"; +print ' $("#'.$blocname.'_bloc").hide("blind", {direction: "vertical"}, 300).removeClass("nohideobject");'."\n"; +print ' $(this).hide();'."\n"; +print ' $("#show-'.$blocname.'").show();'."\n"; +print '});'."\n"; - +print 'function setShowHide(status) {'."\n"; +print ' var id = '.$object->id.";\n"; +print " var element = '".$object->element."';\n"; +print " var htmlelement = '".$blocname."';\n"; +print ' var type = "showhide";'."\n"; +print ' $.get("'.dol_buildpath('/core/ajax/extraparams.php', 1); +print '?id="+id+"&element="+element+"&htmlelement="+htmlelement+"&type="+type+"&value="+status);'."\n"; +print '}'."\n"; -
-
-
+print '});'."\n"; +print ''."\n"; -
+print '
'.img_picto('', '1uparrow.png').'
'."\n"; +print '
'.img_picto('', '1downarrow.png').'
'."\n"; +print '
'.$title.'
'."\n"; +print '
'."\n"; - - -
-
- - \ No newline at end of file +include DOL_DOCUMENT_ROOT.'/core/tpl/'.$blocname.'.tpl.php'; +print '

'; +?> + diff --git a/htdocs/core/tpl/notes.tpl.php b/htdocs/core/tpl/notes.tpl.php index 2538e052ae4..87071e94203 100644 --- a/htdocs/core/tpl/notes.tpl.php +++ b/htdocs/core/tpl/notes.tpl.php @@ -1,7 +1,7 @@ - * Copyright (C) 2013 Florian Henry - * Copyright (C) 2014 Laurent Destailleur +/* Copyright (C) 2012 Regis Houssin + * Copyright (C) 2013 Florian Henry + * Copyright (C) 2014-2017 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 @@ -17,9 +17,10 @@ * along with this program. If not, see . */ -// $cssclass must be defined by caller. For example cssclass='fieldtitle" -$module = $object->element; -$note_public = 'note_public'; +// $permission must be defined by caller. +// $cssclass must be defined by caller. For example cssclass='fieldtitle" +$module = $object->element; +$note_public = 'note_public'; $note_private = 'note_private'; $colwidth=(isset($colwidth)?$colwidth:(empty($cssclass)?'25':'')); diff --git a/htdocs/core/website.inc.php b/htdocs/core/website.inc.php new file mode 100644 index 00000000000..65db787734a --- /dev/null +++ b/htdocs/core/website.inc.php @@ -0,0 +1,28 @@ + + * +* 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 htdocs/core/website.inc.php + * \brief Common file loaded used by all website pages (after master.inc.php) + * The global variable $website must be defined. + */ + + +include_once DOL_DOCUMENT_ROOT.'/websites/class/website.class.php'; +$website=new Website($db); +$website->fetch(0,$websitekey); diff --git a/htdocs/cron/card.php b/htdocs/cron/card.php index a371069d7cf..dce56ff5468 100644 --- a/htdocs/cron/card.php +++ b/htdocs/cron/card.php @@ -380,7 +380,7 @@ if (($action=="create") || ($action=="edit")) print ''; print $langs->trans('CronArgs').""; - print "params."\" /> "; + print "params."\" /> "; print ""; print ""; print $form->textwithpicto('',$langs->trans("CronArgsHelp"),1,'help'); @@ -408,10 +408,10 @@ if (($action=="create") || ($action=="edit")) print ''; print $langs->trans('CronEvery').""; print ""; - print "'; + for ($i=1; $i<=60; $i++) { - if (! empty($object->unitfrequency) && ($object->frequency/$object->unitfrequency) == $i) + if ($object->frequency == $i) { print ""; } diff --git a/htdocs/cron/class/cronjob.class.php b/htdocs/cron/class/cronjob.class.php index f9b4ac67f03..b7de98b0c1c 100644 --- a/htdocs/cron/class/cronjob.class.php +++ b/htdocs/cron/class/cronjob.class.php @@ -1,6 +1,6 @@ - * Copyright (C) 2013 Florian Henry + * Copyright (C) 2013 Florian Henry * * 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 @@ -61,7 +61,7 @@ class Cronjob extends CommonObject public $fk_user_mod; public $nbrun; public $libname; - + public $test; // A test condition to know if job is visible/qualified /** * Constructor @@ -194,12 +194,12 @@ class Cronjob extends CommonObject $sql.= " ".(! isset($this->md5params)?'NULL':"'".$this->db->escape($this->md5params)."'").","; $sql.= " ".(! isset($this->module_name)?'NULL':"'".$this->db->escape($this->module_name)."'").","; $sql.= " ".(! isset($this->priority)?'0':$this->priority).","; - $sql.= " ".(! isset($this->datelastrun) || dol_strlen($this->datelastrun)==0?'NULL':$this->db->idate($this->datelastrun)).","; - $sql.= " ".(! isset($this->datenextrun) || dol_strlen($this->datenextrun)==0?'NULL':$this->db->idate($this->datenextrun)).","; - $sql.= " ".(! isset($this->dateend) || dol_strlen($this->dateend)==0?'NULL':$this->db->idate($this->dateend)).","; - $sql.= " ".(! isset($this->datestart) || dol_strlen($this->datestart)==0?'NULL':$this->db->idate($this->datestart)).","; + $sql.= " ".(! isset($this->datelastrun) || dol_strlen($this->datelastrun)==0?'NULL':"'".$this->db->idate($this->datelastrun)."'").","; + $sql.= " ".(! isset($this->datenextrun) || dol_strlen($this->datenextrun)==0?'NULL':"'".$this->db->idate($this->datenextrun)."'").","; + $sql.= " ".(! isset($this->dateend) || dol_strlen($this->dateend)==0?'NULL':"'".$this->db->idate($this->dateend)."'").","; + $sql.= " ".(! isset($this->datestart) || dol_strlen($this->datestart)==0?'NULL':"'".$this->db->idate($this->datestart)."'").","; $sql.= " ".(! isset($this->lastresult)?'NULL':"'".$this->db->escape($this->lastresult)."'").","; - $sql.= " ".(! isset($this->datelastresult) || dol_strlen($this->datelastresult)==0?'NULL':$this->db->idate($this->datelastresult)).","; + $sql.= " ".(! isset($this->datelastresult) || dol_strlen($this->datelastresult)==0?'NULL':"'".$this->db->idate($this->datelastresult)."'").","; $sql.= " ".(! isset($this->lastoutput)?'NULL':"'".$this->db->escape($this->lastoutput)."'").","; $sql.= " ".(! isset($this->unitfrequency)?'NULL':"'".$this->unitfrequency."'").","; $sql.= " ".(! isset($this->frequency)?'0':$this->frequency).","; diff --git a/htdocs/cron/list.php b/htdocs/cron/list.php index 913da57ac39..e00ac9dcc71 100644 --- a/htdocs/cron/list.php +++ b/htdocs/cron/list.php @@ -18,7 +18,7 @@ */ /** - * \file htdocs/cron/cron/list.php + * \file htdocs/cron/list.php * \ingroup cron * \brief Lists Jobs */ @@ -356,11 +356,7 @@ if ($num > 0) if (! verifCond($obj->test)) continue; // Discard line with test = false - // title profil - if ($style=='pair') {$style='impair';} - else {$style='pair';} - - print ''; + print ''; print ''; print ''; diff --git a/htdocs/fichinter/card.php b/htdocs/fichinter/card.php index 953b48a8adf..8035c2a2e98 100644 --- a/htdocs/fichinter/card.php +++ b/htdocs/fichinter/card.php @@ -1577,7 +1577,7 @@ else if ($id > 0 || ! empty($ref)) { if ($action != 'editdescription' && ($action != 'presend')) { // Validate - if ($object->statut == 0 && (count($object->lines) > 0 || !empty($conf->global->FICHINTER_DISABLE_DETAILS))) { + if ($object->statut == Fichinter::STATUS_DRAFT && (count($object->lines) > 0 || !empty($conf->global->FICHINTER_DISABLE_DETAILS))) { if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->ficheinter->creer) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->ficheinter->ficheinter_advance->validate)) { print ''; @@ -1585,7 +1585,7 @@ else if ($id > 0 || ! empty($ref)) } // Modify - if ($object->statut == 1 && ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->ficheinter->creer) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->ficheinter->ficheinter_advance->unvalidate))) + if ($object->statut == Fichinter::STATUS_VALIDATED && ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->ficheinter->creer) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->ficheinter->ficheinter_advance->unvalidate))) { print '
'; if (empty($conf->global->FICHINTER_DISABLE_DETAILS)) print $langs->trans("Modify"); @@ -1594,7 +1594,7 @@ else if ($id > 0 || ! empty($ref)) } // Send - if ($object->statut > 0) + if ($object->statut > Fichinter::STATUS_DRAFT) { if (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->ficheinter->ficheinter_advance->send) { @@ -1606,10 +1606,10 @@ else if ($id > 0 || ! empty($ref)) // Event agenda if (! empty($conf->global->FICHINTER_ADDLINK_TO_EVENT)) { - if (! empty($conf->agenda->enabled) && $object->statut > 0) + if (! empty($conf->agenda->enabled) && $object->statut > Fichinter::STATUS_DRAFT) { $langs->load("agenda"); - if ($object->statut < 2) + if ($object->statut < Fichinter::STATUS_BILLED) { if ($user->rights->agenda->myactions->create) print ''; else print ''; @@ -1618,10 +1618,10 @@ else if ($id > 0 || ! empty($ref)) } // Proposal - if (! empty($conf->propal->enabled) && $object->statut > 0) + if (! empty($conf->propal->enabled) && $object->statut > Fichinter::STATUS_DRAFT) { $langs->load("propal"); - if ($object->statut < 2) + if ($object->statut < Fichinter::STATUS_BILLED) { if ($user->rights->propal->creer) print ''; else print ''; @@ -1629,10 +1629,10 @@ else if ($id > 0 || ! empty($ref)) } // Invoicing - if (! empty($conf->facture->enabled) && $object->statut > 0) + if (! empty($conf->facture->enabled) && $object->statut > Fichinter::STATUS_DRAFT) { $langs->load("bills"); - if ($object->statut < 2) + if ($object->statut < Fichinter::STATUS_BILLED) { if ($user->rights->facture->creer) print ''; else print ''; @@ -1640,7 +1640,7 @@ else if ($id > 0 || ! empty($ref)) if (! empty($conf->global->FICHINTER_CLASSIFY_BILLED)) // Option deprecated. In a future, billed must be managed with a dedicated field to 0 or 1 { - if ($object->statut != 2) + if ($object->statut != Fichinter::STATUS_BILLED) { print ''; } @@ -1652,7 +1652,7 @@ else if ($id > 0 || ! empty($ref)) } // Done - if (empty($conf->global->FICHINTER_CLASSIFY_BILLED) && $object->statut > 0 && $object->statut < 3) + if (empty($conf->global->FICHINTER_CLASSIFY_BILLED) && $object->statut > Fichinter::STATUS_DRAFT && $object->statut < Fichinter::STATUS_CLOSED) { print ''; } @@ -1663,7 +1663,7 @@ else if ($id > 0 || ! empty($ref)) } // Delete - if (($object->statut == 0 && $user->rights->ficheinter->creer) || $user->rights->ficheinter->supprimer) + if (($object->statut == Fichinter::STATUS_DRAFT && $user->rights->ficheinter->creer) || $user->rights->ficheinter->supprimer) { print ''; diff --git a/htdocs/fichinter/class/fichinter.class.php b/htdocs/fichinter/class/fichinter.class.php index 6142d87de7a..eaf10c357e4 100644 --- a/htdocs/fichinter/class/fichinter.class.php +++ b/htdocs/fichinter/class/fichinter.class.php @@ -39,7 +39,7 @@ class Fichinter extends CommonObject public $fk_element='fk_fichinter'; public $table_element_line='fichinterdet'; public $picto = 'intervention'; - + /** * {@inheritdoc} */ @@ -62,6 +62,23 @@ class Fichinter extends CommonObject var $lines = array(); + /** + * Draft status + */ + const STATUS_DRAFT = 0; + /** + * Validated status + */ + const STATUS_VALIDATED = 1; + /** + * Billed + */ + const STATUS_BILLED = 2; + /** + * Closed + */ + const STATUS_CLOSED = 3; + /** * Constructor * @@ -361,7 +378,7 @@ class Fichinter extends CommonObject $this->fk_contrat = $obj->fk_contrat; $this->user_creation= $obj->fk_user_author; - + $this->extraparams = (array) json_decode($obj->extraparams, true); if ($this->statut == 0) $this->brouillon = 1; @@ -546,23 +563,23 @@ class Fichinter extends CommonObject */ function getAmount() { global $db; - + $amount = 0; - + $this->author = new User($db); $this->author->fetch($this->user_creation); - + $thm = $this->author->thm; - + foreach($this->lines as &$line) { - + $amount+=$line->qty * $thm; - + } - + return $amount; } - + /** * Returns the label status * @@ -599,7 +616,7 @@ class Fichinter extends CommonObject return ''.$langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts[$statut]),$this->statuts_logo[$statut]); if ($mode == 6) return ''.$langs->trans($this->statuts[$statut]).' '.img_picto($langs->trans($this->statuts[$statut]),$this->statuts_logo[$statut]); - + return ''; } @@ -949,7 +966,7 @@ class Fichinter extends CommonObject return -2; } - + /** * Load an object from its id and create a new one in database @@ -1001,7 +1018,7 @@ class Fichinter extends CommonObject $this->date_creation = ''; $this->date_validation = ''; $this->ref_client = ''; - + // Create clone $result=$this->create($user); if ($result < 0) $error++; @@ -1013,7 +1030,7 @@ class Fichinter extends CommonObject { $this->addline($user, $this->id, $line->desc, $line->datei, $line->duration); } - + // Hook of thirdparty module if (is_object($hookmanager)) { @@ -1043,8 +1060,8 @@ class Fichinter extends CommonObject return -1; } } - - + + /** * Adding a line of intervention into data base * diff --git a/htdocs/fichinter/list.php b/htdocs/fichinter/list.php index 3acef343aa9..75f151d0850 100644 --- a/htdocs/fichinter/list.php +++ b/htdocs/fichinter/list.php @@ -253,6 +253,13 @@ if ($resql) $arrayofselected=is_array($toselect)?$toselect:array(); + if ($socid > 0) + { + $soc = new Societe($db); + $soc->fetch($socid); + if (empty($search_company)) $search_company = $soc->name; + } + $param=''; if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.$contextpage; if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.$limit; diff --git a/htdocs/fourn/facture/list.php b/htdocs/fourn/facture/list.php index 3fadb82d067..fcaa024e186 100644 --- a/htdocs/fourn/facture/list.php +++ b/htdocs/fourn/facture/list.php @@ -427,6 +427,7 @@ if ($resql) { $soc = new Societe($db); $soc->fetch($socid); + if (empty($search_societe)) $search_societe = $soc->name; } $param='&socid='.$socid; @@ -493,7 +494,7 @@ if ($resql) if (! GETPOST('cancel')) { - $objecttmp=new FactureFourn($db); + $objecttmp=new FactureFournisseur($db); $listofselectedid=array(); $listofselectedthirdparties=array(); $listofselectedref=array(); diff --git a/htdocs/index.php b/htdocs/index.php index 187273ef2b4..9b190ac1e2b 100644 --- a/htdocs/index.php +++ b/htdocs/index.php @@ -448,7 +448,7 @@ if (! empty($conf->facture->enabled) && $user->rights->facture->lire) } // Number of supplier invoices (has paid) -if (! empty($conf->supplier_invoice->enabled) && ! empty($conf->facture->enabled) && $user->rights->facture->lire) +if (! empty($conf->supplier_invoice->enabled) && ! empty($user->rights->fournisseur->facture->lire)) { include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php'; $board=new FactureFournisseur($db); diff --git a/htdocs/install/mysql/data/llx_c_tva.sql b/htdocs/install/mysql/data/llx_c_tva.sql index 3b401abd37d..7f9c5f97ea4 100644 --- a/htdocs/install/mysql/data/llx_c_tva.sql +++ b/htdocs/install/mysql/data/llx_c_tva.sql @@ -133,10 +133,13 @@ insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values ( 3 insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values ( 34, 3, '0','0','VAT Rate 0',1); -- INDIA (id country=117) -insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (1171, 117, '12.5','0','VAT standard rate',1); -insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (1172, 117, '4','0','VAT reduced rate',1); -insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (1173, 117, '1','0','VAT super-reduced rate',1); -insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (1174, 117, '0','0','VAT Rate 0',1); +insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (1171, 117, '12.5','0','VAT standard rate',0); +insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (1172, 117, '4','0','VAT reduced rate',0); +insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (1173, 117, '1','0','VAT super-reduced rate',0); +insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (1174, 117, '0','0','VAT Rate 0',0); + +insert into llx_c_tva(rowid,fk_pays,code,taux,localtax1,localtax1_type,localtax2,localtax2_type,recuperableonly,note,active) values (1176, 117, 'IGST+CGST', 8, 8, '1', 0, '0', 0, 'IGST+CGST', 1); +insert into llx_c_tva(rowid,fk_pays,code,taux,localtax1,localtax1_type,localtax2,localtax2_type,recuperableonly,note,active) values (1177, 117, 'SGST', 0, 0, '0', 16, '1', 0, 'SGST', 1); -- IRELAND (id country=8) insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (81, 8, '0','0','VAT Rate 0',1); diff --git a/htdocs/install/mysql/migration/3.6.0-3.7.0.sql b/htdocs/install/mysql/migration/3.6.0-3.7.0.sql index dd0aba11632..6dc2521ca5d 100755 --- a/htdocs/install/mysql/migration/3.6.0-3.7.0.sql +++ b/htdocs/install/mysql/migration/3.6.0-3.7.0.sql @@ -1106,6 +1106,7 @@ ALTER TABLE llx_projet_task_time ADD INDEX idx_projet_task_time_datehour (task_d ALTER TABLE llx_projet_task MODIFY COLUMN duration_effective real DEFAULT 0 NULL; ALTER TABLE llx_projet_task MODIFY COLUMN planned_workload real DEFAULT 0 NULL; +-- VPGSQL8.2 ALTER TABLE llx_projet_task ALTER COLUMN planned_workload DROP NOT NULL; -- add extrafield on ficheinter lines CREATE TABLE llx_fichinterdet_extrafields diff --git a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql index c997d511fdb..63bc1a8d7a3 100755 --- a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql +++ b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql @@ -110,6 +110,7 @@ ALTER TABLE llx_projet_task_time ADD COLUMN task_date_withhour integer DEFAULT 0 ALTER TABLE llx_projet_task MODIFY COLUMN duration_effective real DEFAULT 0 NULL; ALTER TABLE llx_projet_task MODIFY COLUMN planned_workload real DEFAULT 0 NULL; +-- VPGSQL8.2 ALTER TABLE llx_projet_task ALTER COLUMN planned_workload DROP NOT NULL; ALTER TABLE llx_commande_fournisseur MODIFY COLUMN date_livraison datetime; diff --git a/htdocs/install/mysql/migration/3.8.0-3.9.0.sql b/htdocs/install/mysql/migration/3.8.0-3.9.0.sql index 03ff8c76d93..48a6b191ebf 100644 --- a/htdocs/install/mysql/migration/3.8.0-3.9.0.sql +++ b/htdocs/install/mysql/migration/3.8.0-3.9.0.sql @@ -611,3 +611,7 @@ INSERT INTO llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) VALUES (14 -- VMYSQL4.1 ALTER TABLE llx_c_type_resource CHANGE COLUMN rowid rowid integer NOT NULL AUTO_INCREMENT; ALTER TABLE llx_import_model MODIFY COLUMN type varchar(50); + +-- Negative buying prices + +UPDATE llx_facturedet SET buy_price_ht = ABS(buy_price_ht) diff --git a/htdocs/install/mysql/migration/3.9.0-4.0.0.sql b/htdocs/install/mysql/migration/3.9.0-4.0.0.sql index 7ed89ebb173..c67bd51b430 100644 --- a/htdocs/install/mysql/migration/3.9.0-4.0.0.sql +++ b/htdocs/install/mysql/migration/3.9.0-4.0.0.sql @@ -547,4 +547,6 @@ INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle, active) VALUES (178, -- VMYSQL4.1 ALTER TABLE llx_establishment CHANGE COLUMN fk_user_mod fk_user_mod integer NULL; -- VPGSQL8.2 ALTER TABLE llx_establishment ALTER COLUMN fk_user_mod DROP NOT NULL; -ALTER TABLE llx_multicurrency_rate ADD COLUMN entity integer DEFAULT 1; \ No newline at end of file +ALTER TABLE llx_multicurrency_rate ADD COLUMN entity integer DEFAULT 1; + +ALTER TABLE llx_user MODIFY COLUMN login varchar(50); \ No newline at end of file diff --git a/htdocs/install/mysql/migration/5.0.0-6.0.0.sql b/htdocs/install/mysql/migration/5.0.0-6.0.0.sql index d18da18ac6a..43f4162e9cb 100644 --- a/htdocs/install/mysql/migration/5.0.0-6.0.0.sql +++ b/htdocs/install/mysql/migration/5.0.0-6.0.0.sql @@ -467,6 +467,8 @@ DELETE FROM llx_categorie_project WHERE fk_categorie NOT IN (SELECT rowid FROM l ALTER TABLE llx_inventory ADD COLUMN ref varchar(48); +-- VPGSQL8.2 ALTER TABLE llx_projet_task ALTER COLUMN planned_workload DROP NOT NULL; + CREATE TABLE llx_loan_schedule ( rowid integer AUTO_INCREMENT PRIMARY KEY, @@ -571,3 +573,10 @@ UPDATE llx_bank SET label= '(CustomerInvoicePayment)' WHERE label= 'Règlement c UPDATE llx_bank SET label= '(payment_salary)' WHERE label LIKE 'Règlement salaire'; ALTER TABLE llx_mailing_cibles MODIFY COLUMN source_url varchar(255); + +-- VPGSQL8.2 CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_website FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); +-- VPGSQL8.2 CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_website_page FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); + + +insert into llx_c_tva(rowid,fk_pays,code,taux,localtax1,localtax1_type,localtax2,localtax2_type,recuperableonly,note,active) values (1176, 117, 'IGST-CGST', 8, 8, '1', 0, '0', 0, 'IGST-CGST', 1); +insert into llx_c_tva(rowid,fk_pays,code,taux,localtax1,localtax1_type,localtax2,localtax2_type,recuperableonly,note,active) values (1177, 117, 'SGST', 0, 0, '0', 16, '1', 0, 'SGST', 1); diff --git a/htdocs/install/mysql/migration/6.0.0-7.0.0.sql b/htdocs/install/mysql/migration/6.0.0-7.0.0.sql index 43c2b813536..ba6be6291f6 100644 --- a/htdocs/install/mysql/migration/6.0.0-7.0.0.sql +++ b/htdocs/install/mysql/migration/6.0.0-7.0.0.sql @@ -28,4 +28,19 @@ ALTER TABLE llx_facture_fourn ADD COLUMN date_pointoftax date DEFAULT NULL; ALTER TABLE llx_facture_fourn ADD COLUMN date_valid date; +ALTER TABLE llx_website_page MODIFY COLUMN pageurl varchar(255); +ALTER TABLE llx_website_page ADD COLUMN lang varchar(6); +ALTER TABLE llx_website_page ADD COLUMN fk_page integer; + +ALTER TABLE llx_fichinter ADD COLUMN import_key varchar(14); +ALTER TABLE llx_livraison ADD COLUMN import_key varchar(14); +ALTER TABLE llx_livraison ADD COLUMN extraparams varchar(255); +ALTER TABLE llx_don ADD COLUMN extraparams varchar(255); + +ALTER TABLE llx_accounting_account ADD COLUMN import_key varchar(14); +ALTER TABLE llx_accounting_account ADD COLUMN extraparams varchar(255); +ALTER TABLE llx_accounting_bookkeeping ADD COLUMN import_key varchar(14); +ALTER TABLE llx_accounting_bookkeeping ADD COLUMN extraparams varchar(255); + +ALTER TABLE llx_accounting_bookkeeping ADD COLUMN date_lim_reglement datetime; diff --git a/htdocs/install/mysql/tables/llx_accounting_account.sql b/htdocs/install/mysql/tables/llx_accounting_account.sql index 8abd342cee5..b65863afe3f 100644 --- a/htdocs/install/mysql/tables/llx_accounting_account.sql +++ b/htdocs/install/mysql/tables/llx_accounting_account.sql @@ -35,4 +35,6 @@ create table llx_accounting_account fk_user_author integer DEFAULT NULL, fk_user_modif integer DEFAULT NULL, active tinyint DEFAULT 1 NOT NULL + import_key varchar(14), + extraparams varchar(255) -- for other parameters with json format )ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_accounting_bookkeeping.sql b/htdocs/install/mysql/tables/llx_accounting_bookkeeping.sql index f33db4be484..e9a4921a840 100644 --- a/htdocs/install/mysql/tables/llx_accounting_bookkeeping.sql +++ b/htdocs/install/mysql/tables/llx_accounting_bookkeeping.sql @@ -40,14 +40,16 @@ CREATE TABLE llx_accounting_bookkeeping multicurrency_code varchar(255), -- FEC:Idevise lettering_code varchar(255), -- FEC:EcritureLet date_lettering datetime, -- FEC:DateLet + date_lim_reglement datetime, -- | date limite de reglement fk_user_author integer NOT NULL, -- | user creating fk_user_modif integer, -- | user making last change date_creation datetime, -- FEC:EcritureDate | creation date tms timestamp, -- | date last modification - import_key varchar(14), code_journal varchar(32) NOT NULL, -- FEC:JournalCode journal_label varchar(255), -- FEC:JournalLib piece_num integer NOT NULL, -- FEC:EcritureNum validated tinyint DEFAULT 0 NOT NULL, -- | 0 line not validated / 1 line validated (No deleting / No modification) date_validated datetime -- FEC:ValidDate + import_key varchar(14), + extraparams varchar(255) -- for other parameters with json format ) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_accounting_bookkeeping_tmp.sql b/htdocs/install/mysql/tables/llx_accounting_bookkeeping_tmp.sql index 9ead8c6c6ba..e49c937d6ed 100644 --- a/htdocs/install/mysql/tables/llx_accounting_bookkeeping_tmp.sql +++ b/htdocs/install/mysql/tables/llx_accounting_bookkeeping_tmp.sql @@ -40,6 +40,7 @@ CREATE TABLE llx_accounting_bookkeeping_tmp multicurrency_code varchar(255), -- FEC:Idevise lettering_code varchar(255), -- FEC:EcritureLet date_lettering datetime, -- FEC:DateLet + date_lim_reglement datetime, -- | date limite de reglement fk_user_author integer NOT NULL, -- | user creating fk_user_modif integer, -- | user making last change date_creation datetime, -- FEC:EcritureDate | creation date diff --git a/htdocs/install/mysql/tables/llx_don.sql b/htdocs/install/mysql/tables/llx_don.sql index b7b7c89f9cd..e2fbdba9efb 100644 --- a/htdocs/install/mysql/tables/llx_don.sql +++ b/htdocs/install/mysql/tables/llx_don.sql @@ -51,5 +51,6 @@ create table llx_don note_private text, note_public text, model_pdf varchar(255), - import_key varchar(14) + import_key varchar(14), + extraparams varchar(255) -- for other parameters with json format )ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_extrafields.sql b/htdocs/install/mysql/tables/llx_extrafields.sql index aee51524e6f..101254ea186 100644 --- a/htdocs/install/mysql/tables/llx_extrafields.sql +++ b/htdocs/install/mysql/tables/llx_extrafields.sql @@ -37,5 +37,9 @@ create table llx_extrafields param text, -- extra parameters to define possible values of field list integer DEFAULT 0, -- list of values for field that are combo lists langs varchar(24), -- example: fileofmymodule@mymodule - ishidden integer DEFAULT 0 -- ??? example of use case ??? + ishidden integer DEFAULT 0, -- Can be foreign key of external system + fk_user_author integer, -- user making creation + fk_user_modif integer, -- user making last change + datec datetime, -- date de creation + tms timestamp )ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_fichinter.sql b/htdocs/install/mysql/tables/llx_fichinter.sql index 926a05a738e..0ec67d6585c 100644 --- a/htdocs/install/mysql/tables/llx_fichinter.sql +++ b/htdocs/install/mysql/tables/llx_fichinter.sql @@ -31,8 +31,8 @@ create table llx_fichinter date_valid datetime, -- date de validation datei date, -- date de livraison du bon d'intervention fk_user_author integer, -- user making creation - fk_user_modif integer, -- user making last change - fk_user_valid integer, -- valideur de la fiche + fk_user_modif integer, -- user making last change + fk_user_valid integer, -- user validating record fk_statut smallint DEFAULT 0, dateo date, -- date de début d'intervention datee date, -- date de fin d'intervention @@ -42,5 +42,6 @@ create table llx_fichinter note_private text, note_public text, model_pdf varchar(255), - extraparams varchar(255) -- for stock other parameters with json format + import_key varchar(14), + extraparams varchar(255) -- for other parameters with json format )ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_livraison.sql b/htdocs/install/mysql/tables/llx_livraison.sql index c999cfdb3c2..6b09303f94d 100644 --- a/htdocs/install/mysql/tables/llx_livraison.sql +++ b/htdocs/install/mysql/tables/llx_livraison.sql @@ -41,6 +41,8 @@ create table llx_livraison note_public text, model_pdf varchar(255), fk_incoterms integer, -- for incoterms - location_incoterms varchar(255) -- for incoterms - + location_incoterms varchar(255), -- for incoterms + + import_key varchar(14), + extraparams varchar(255) -- for other parameters with json format )ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_user.sql b/htdocs/install/mysql/tables/llx_user.sql index d033ba5eca4..9df2f57a22b 100644 --- a/htdocs/install/mysql/tables/llx_user.sql +++ b/htdocs/install/mysql/tables/llx_user.sql @@ -33,7 +33,7 @@ create table llx_user tms timestamp, fk_user_creat integer, fk_user_modif integer, - login varchar(24) NOT NULL, + login varchar(50) NOT NULL, pass varchar(128), pass_crypted varchar(128), pass_temp varchar(128), -- temporary password when asked for forget password diff --git a/htdocs/install/mysql/tables/llx_website_page.sql b/htdocs/install/mysql/tables/llx_website_page.sql index 69b6c417528..13ab3558c98 100644 --- a/htdocs/install/mysql/tables/llx_website_page.sql +++ b/htdocs/install/mysql/tables/llx_website_page.sql @@ -21,10 +21,12 @@ CREATE TABLE llx_website_page ( rowid integer AUTO_INCREMENT NOT NULL PRIMARY KEY, fk_website integer NOT NULL, - pageurl varchar(16) NOT NULL, + pageurl varchar(255) NOT NULL, title varchar(255), description varchar(255), keywords varchar(255), + lang varchar(6), + fk_page integer, content mediumtext, -- text is not enough in size status integer, fk_user_create integer, diff --git a/htdocs/install/pgsql/functions/functions.sql b/htdocs/install/pgsql/functions/functions.sql index 2e4125e39e4..e5b9d47a0ba 100644 --- a/htdocs/install/pgsql/functions/functions.sql +++ b/htdocs/install/pgsql/functions/functions.sql @@ -163,6 +163,9 @@ CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_user_extrafields FOR CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_usergroup FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_usergroup_extrafields FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_product_price_by_qty FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); +CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_website FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); +CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_website_page FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); +CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_extrafields FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); -- Add triggers for timestamp fields named date_m diff --git a/htdocs/install/step1.php b/htdocs/install/step1.php index a8d17388d41..bf2caf1b255 100644 --- a/htdocs/install/step1.php +++ b/htdocs/install/step1.php @@ -423,13 +423,11 @@ if (! $error && $db->connected && $action == "set") // Les documents sont en dehors de htdocs car ne doivent pas pouvoir etre telecharges en passant outre l'authentification $dir[0] = $main_data_dir."/mycompany"; $dir[1] = $main_data_dir."/users"; - $dir[2] = $main_data_dir."/custom"; - $dir[3] = $main_data_dir."/facture"; - $dir[4] = $main_data_dir."/propale"; - $dir[5] = $main_data_dir."/ficheinter"; - $dir[6] = $main_data_dir."/produit"; - $dir[7] = $main_data_dir."/doctemplates"; - $dir[7] = $main_data_dir."/extensions"; + $dir[2] = $main_data_dir."/facture"; + $dir[3] = $main_data_dir."/propale"; + $dir[4] = $main_data_dir."/ficheinter"; + $dir[5] = $main_data_dir."/produit"; + $dir[6] = $main_data_dir."/doctemplates"; // Boucle sur chaque repertoire de dir[] pour les creer s'ils nexistent pas $num=count($dir); diff --git a/htdocs/langs/en_IN/main.lang b/htdocs/langs/en_IN/main.lang index 80f13de139f..13a90b526c4 100644 --- a/htdocs/langs/en_IN/main.lang +++ b/htdocs/langs/en_IN/main.lang @@ -24,3 +24,7 @@ LinkToProposal=Link to quotation LinkToSupplierProposal=Link to supplier quotation SearchIntoCustomerProposals=Customer quotations SearchIntoSupplierProposals=Supplier quotations + +AmountVAT=Amount tax IGST +AmountLT1=Amount tax CGST +AmountLT2=Amount tax SGST diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index a4de6f7470c..9d897396036 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1058,7 +1058,7 @@ RestoreDesc2=Restore archive file (zip file for example) of documents directory RestoreDesc3=Restore the data, from a backup dump file, into the database of the new Dolibarr installation or into the database of this current installation (%s). Warning, once restore is finished, you must use a login/password, that existed when backup was made, to connect again. To restore a backup database into this current installation, you can follow this assistant. RestoreMySQL=MySQL import ForcedToByAModule= This rule is forced to %s by an activated module -PreviousDumpFiles=Available database backup dump files +PreviousDumpFiles=Generated database backup files WeekStartOnDay=First day of week RunningUpdateProcessMayBeRequired=Running the upgrade process seems to be required (Programs version %s differs from database version %s) YouMustRunCommandFromCommandLineAfterLoginToUser=You must run this command from command line after login to a shell with user %s or you must add -W option at end of command line to provide %s password. diff --git a/htdocs/langs/en_US/bills.lang b/htdocs/langs/en_US/bills.lang index 189ef5c1fe2..03ddb1f958e 100644 --- a/htdocs/langs/en_US/bills.lang +++ b/htdocs/langs/en_US/bills.lang @@ -45,6 +45,7 @@ InvoiceHasAvoir=Was source of one or several credit notes CardBill=Invoice card PredefinedInvoices=Predefined Invoices Invoice=Invoice +PdfInvoiceTitle=Invoice Invoices=Invoices InvoiceLine=Invoice line InvoiceCustomer=Customer invoice diff --git a/htdocs/langs/en_US/compta.lang b/htdocs/langs/en_US/compta.lang index 79ad6cfd628..4c6dc5bf169 100644 --- a/htdocs/langs/en_US/compta.lang +++ b/htdocs/langs/en_US/compta.lang @@ -30,18 +30,34 @@ Piece=Accounting Doc. AmountHTVATRealReceived=Net collected AmountHTVATRealPaid=Net paid VATToPay=VAT sells -VATReceived=VAT received -VATToCollect=VAT purchases -VATSummary=VAT Balance -LT2SummaryES=IRPF Balance +VATReceived=Tax received +VATToCollect=Tax purchases +VATSummary=Tax Balance +VATPaid=Tax paid +LT1Summary=Tax 2 summary +LT2Summary=Tax 3 summary LT1SummaryES=RE Balance -VATPaid=VAT paid -LT2PaidES=IRPF Paid +LT2SummaryES=IRPF Balance +LT1SummaryIN=CGST Balance +LT2SummaryIN=SGST Balance +LT1Paid=Tax 2 paid +LT2Paid=Tax 3 paid LT1PaidES=RE Paid -LT2CustomerES=IRPF sales -LT2SupplierES=IRPF purchases +LT2PaidES=IRPF Paid +LT1PaidIN=CGST Paid +LT2PaidIN=SGST Paid +LT1Customer=Tax 2 sales +LT1Supplier=Tax 2 purchases LT1CustomerES=RE sales LT1SupplierES=RE purchases +LT1CustomerIN=CGST sales +LT1SupplierIN=CGST purchases +LT2Customer=Tax 3 sales +LT2Supplier=Tax 3 purchases +LT2CustomerES=IRPF sales +LT2SupplierES=IRPF purchases +LT2CustomerIN=SGST sales +LT2SupplierIN=SGST purchases VATCollected=VAT collected ToPay=To pay SpecialExpensesArea=Area for all special payments diff --git a/htdocs/langs/en_US/cron.lang b/htdocs/langs/en_US/cron.lang index 8eb03114c64..78a4ea789f8 100644 --- a/htdocs/langs/en_US/cron.lang +++ b/htdocs/langs/en_US/cron.lang @@ -14,6 +14,8 @@ FileToLaunchCronJobs=Command line to launch cron jobs CronExplainHowToRunUnix=On Unix environment you should use the following crontab entry to run the command line each 5 minutes CronExplainHowToRunWin=On Microsoft(tm) Windows environement you can use Scheduled task tools to run the command line each 5 minutes CronMethodDoesNotExists=Class %s does not contains any method %s +CronJobDefDesc=Cron job profiles are defined into the module descriptor file. When module is activated, they are loaded and available so you can administer the jobs from the admin tools menu %s. +CronJobProfiles=List of predefined cron job profiles # Menu EnabledAndDisabled=Enabled and disabled # Page list @@ -53,16 +55,17 @@ CronSaveSucess=Save successfully CronNote=Comment CronFieldMandatory=Fields %s is mandatory CronErrEndDateStartDt=End date cannot be before start date +StatusAtInstall=Status at installation CronStatusActiveBtn=Enable CronStatusInactiveBtn=Disable CronTaskInactive=This job is disabled CronId=Id CronClassFile=Filename with class -CronModuleHelp=Name of Dolibarr module directory (also work with external Dolibarr module).
For exemple to call the fetch method of Dolibarr Product object /htdocs/product/class/product.class.php, the value for module is product -CronClassFileHelp=The relative path and file name to load (path is relative to web server root directory).
For exemple to call the fetch method of Dolibarr Product object htdocs/product/class/product.class.php, the value for class file name is product/class/product.class.php -CronObjectHelp=The object name to load.
For exemple to call the fetch method of Dolibarr Product object /htdocs/product/class/product.class.php, the value for class file name is Product -CronMethodHelp=The object method to launch.
For exemple to call the fetch method of Dolibarr Product object /htdocs/product/class/product.class.php, the value for method is fecth -CronArgsHelp=The method arguments.
For exemple to call the fetch method of Dolibarr Product object /htdocs/product/class/product.class.php, the value for paramters can be 0, ProductRef +CronModuleHelp=Name of Dolibarr module directory (also work with external Dolibarr module).
For exemple to call the fetch method of Dolibarr Product object /htdocs/product/class/product.class.php, the value for module is
product +CronClassFileHelp=The relative path and file name to load (path is relative to web server root directory).
For exemple to call the fetch method of Dolibarr Product object htdocs/product/class/product.class.php, the value for class file name is
product/class/product.class.php +CronObjectHelp=The object name to load.
For exemple to call the fetch method of Dolibarr Product object /htdocs/product/class/product.class.php, the value for class file name is
Product +CronMethodHelp=The object method to launch.
For exemple to call the fetch method of Dolibarr Product object /htdocs/product/class/product.class.php, the value for method is
fetch +CronArgsHelp=The method arguments.
For exemple to call the fetch method of Dolibarr Product object /htdocs/product/class/product.class.php, the value for paramters can be
0, ProductRef CronCommandHelp=The system command line to execute. CronCreateJob=Create new Scheduled Job CronFrom=From diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index ff874d2fc1b..42bc2ff925a 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -356,17 +356,26 @@ Totalforthispage=Total for this page TotalTTC=Total (inc. tax) TotalTTCToYourCredit=Total (inc. tax) to your credit TotalVAT=Total tax +TotalVATIN=Total IGST TotalLT1=Total tax 2 TotalLT2=Total tax 3 TotalLT1ES=Total RE TotalLT2ES=Total IRPF +TotalLT1IN=Total CGST +TotalLT2IN=Total SGST HT=Net of tax TTC=Inc. tax INCT=Inc. all taxes VAT=Sales tax +VATIN=IGST VATs=Sales taxes +VATINs=IGST taxes +LT1=Sales tax 2 +LT2=Sales tax 3 LT1ES=RE LT2ES=IRPF +LT1IN=CGST +LT2IN=SGST VATRate=Tax Rate Average=Average Sum=Sum @@ -785,6 +794,7 @@ HRAndBank=HR and Bank AutomaticallyCalculated=Automatically calculated TitleSetToDraft=Go back to draft ConfirmSetToDraft=Are you sure you want to go back to Draft status ? +ImportId=Import id # Week day Monday=Monday Tuesday=Tuesday diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang index 9a7fbb7b3bc..9b3ad61a310 100644 --- a/htdocs/langs/en_US/modulebuilder.lang +++ b/htdocs/langs/en_US/modulebuilder.lang @@ -13,7 +13,7 @@ FilesForObjectInitialized=Files for new object '%s' initialized FilesForObjectUpdated=Files for object '%s' updated (.sql files and .class.php file) ModuleBuilderDescdescription=Enter here all general information that describe your module ModuleBuilderDescspecifications=You can enter here a long text to describe the specifications of your module that is not already structured into other tabs. So you have within easy reach all the rules to develop. Also this text content will be included into the generated documentation (see last tab). You can use Markdown format, but it is recommanded to use Asciidoc format (Comparison between .md and .asciidoc: http://asciidoctor.org/docs/user-manual/#compared-to-markdown) -ModuleBuilderDescobjects=Define here the objects you want to manage with your module. A sql file, a page to list them, to create/edit/view a card and an API will be generated. +ModuleBuilderDescobjects=Define here the objects you want to manage with your module. A CRUD DAO class, SQL files, page to list record of objects, to create/edit/view a record and an API will be generated. ModuleBuilderDescmenus=This tab is dedicated to define menu entries provided by your module. ModuleBuilderDescpermissions=This tab is dedicated to define the new permissions you want to provide with your module. ModuleBuilderDesctriggers=This is the view of triggers provided by your module. To include code executed when a triggered business event is launched, just edit this file. @@ -25,13 +25,13 @@ EnterNameOfObjectToDeleteDesc=You can delete an object. WARNING: All files relat DangerZone=Danger zone BuildPackage=Build package/documentation BuildDocumentation=Build documentation -ModuleIsNotActive=This module was not activated yet. Ggo into %s to make it live or click here: +ModuleIsNotActive=This module was not activated yet. Go into %s to make it live or click here: ModuleIsLive=This module has been activated. Any change on it may break a current active feature. DescriptionLong=Long description EditorName=Name of editor EditorUrl=URL of editor DescriptorFile=Descriptor file of module -ClassFile=File for PHP class +ClassFile=File for PHP DAO CRUD class ApiClassFile=File for PHP API class PageForList=PHP page for list of record PageForCreateEditView=PHP page to create/edit/view a record @@ -50,7 +50,10 @@ HooksFile=File for hooks code WidgetFile=Widget file ReadmeFile=Readme file ChangeLog=ChangeLog file +TestClassFile=File for PHP Unit Test class SqlFile=Sql file +SqlFileExtraFields=Sql file for complementary attributes SqlFileKey=Sql file for keys AnObjectAlreadyExistWithThisNameAndDiffCase=An object already exists with this name and a different case -UseAsciiDocFormat=You can use Markdown format, but it is recommanded to use Asciidoc format (Comparison between .md and .asciidoc: http://asciidoctor.org/docs/user-manual/#compared-to-markdown) \ No newline at end of file +UseAsciiDocFormat=You can use Markdown format, but it is recommanded to use Asciidoc format (Comparison between .md and .asciidoc: http://asciidoctor.org/docs/user-manual/#compared-to-markdown) +IsAMeasure=Is a measure \ No newline at end of file diff --git a/htdocs/langs/en_US/orders.lang b/htdocs/langs/en_US/orders.lang index 363fb504a5b..c62d08412ce 100644 --- a/htdocs/langs/en_US/orders.lang +++ b/htdocs/langs/en_US/orders.lang @@ -4,6 +4,7 @@ SuppliersOrdersArea=Suppliers orders area OrderCard=Order card OrderId=Order Id Order=Order +PdfOrderTitle=Order Orders=Orders OrderLine=Order line OrderDate=Order date @@ -117,6 +118,7 @@ SecondApprovalAlreadyDone=Second approval already done SupplierOrderReceivedInDolibarr=Supplier order %s received %s SupplierOrderSubmitedInDolibarr=Supplier order %s submited SupplierOrderClassifiedBilled=Supplier order %s set billed +OtherOrders=Other orders ##### Types de contacts ##### TypeContact_commande_internal_SALESREPFOLL=Representative following-up customer order TypeContact_commande_internal_SHIPPING=Representative following-up shipping diff --git a/htdocs/langs/en_US/other.lang b/htdocs/langs/en_US/other.lang index e519f7af405..bd52f5dcaa2 100644 --- a/htdocs/langs/en_US/other.lang +++ b/htdocs/langs/en_US/other.lang @@ -18,6 +18,7 @@ NextMonthOfInvoice=Following month (number 1-12) of invoice date TextNextMonthOfInvoice=Following month (text) of invoice date ZipFileGeneratedInto=Zip file generated into %s. DocFileGeneratedInto=Doc file generated into %s. +JumpToLogin=Disconnected. Go to login page... YearOfInvoice=Year of invoice date PreviousYearOfInvoice=Previous year of invoice date diff --git a/htdocs/langs/en_US/propal.lang b/htdocs/langs/en_US/propal.lang index aefe8e89cd2..2cbbc509076 100644 --- a/htdocs/langs/en_US/propal.lang +++ b/htdocs/langs/en_US/propal.lang @@ -6,6 +6,7 @@ ProposalsDraft=Draft commercial proposals ProposalsOpened=Open commercial proposals Prop=Commercial proposals CommercialProposal=Commercial proposal +PdfCommercialProposalTitle=Commercial proposal ProposalCard=Proposal card NewProp=New commercial proposal NewPropal=New proposal @@ -63,6 +64,7 @@ ProposalLine=Proposal line AvailabilityPeriod=Availability delay SetAvailability=Set availability delay AfterOrder=after order +OtherProposals=Other proposals ##### Availability ##### AvailabilityTypeAV_NOW=Immediate AvailabilityTypeAV_1W=1 week diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang index 460665255b1..11c013cb768 100644 --- a/htdocs/langs/en_US/stocks.lang +++ b/htdocs/langs/en_US/stocks.lang @@ -69,6 +69,7 @@ NoPredefinedProductToDispatch=No predefined products for this object. So no disp DispatchVerb=Dispatch StockLimitShort=Limit for alert StockLimit=Stock limit for alert +StockLimitDesc="" (empty) default value means no alert.
"0" can be used with 'Stock can be negative' configuration. PhysicalStock=Physical stock RealStock=Real Stock RealStockDesc=Physical or real stock is the stock you currently have into your internal warehouses/emplacements. @@ -192,4 +193,4 @@ InventoryFlushed=Inventory flushed ExitEditMode=Exit edition inventoryDeleteLine=Delete line RegulateStock=Regulate Stock -ListInventory=List +ListInventory=List \ No newline at end of file diff --git a/htdocs/langs/en_US/website.lang b/htdocs/langs/en_US/website.lang index 18d9193b3f9..82d0022b1f9 100644 --- a/htdocs/langs/en_US/website.lang +++ b/htdocs/langs/en_US/website.lang @@ -7,20 +7,22 @@ WEBSITE_PAGENAME=Page name/alias WEBSITE_HTML_HEADER=HTML Header WEBSITE_CSS_URL=URL of external CSS file WEBSITE_CSS_INLINE=CSS content -PageNameAliasHelp=Name or alias of the page.
This alias is also used to forge a SEO URL when website is read from a Virtual host of a Web server (like Apacke, Nginx, ...). Use the button "%s" to edit this alias. +PageNameAliasHelp=Name or alias of the page.
This alias is also used to forge a SEO URL when website is ran from a Virtual host of a Web server (like Apacke, Nginx, ...). Use the button "%s" to edit this alias. MediaFiles=Media library -EditCss=Edit Style/CSS +EditCss=Edit Style/CSS or HTML header EditMenu=Edit menu EditPageMeta=Edit Meta -EditPageContent=Edit Content +EditPageSource=Edit HTML Source +EditPageContent=Edit with CKEditor Website=Web site -Webpage=Web page -AddPage=Add page +Webpage=Web page/container +AddPage=Add page/container HomePage=Home Page PreviewOfSiteNotYetAvailable=Preview of your website %s not yet available. You must first add a page. RequestedPageHasNoContentYet=Requested page with id %s has no content yet, or cache file .tpl.php was removed. Edit content of the page to solve this. -PageDeleted=Page '%s' of website %s deleted -PageAdded=Page '%s' added +PageContent=Page/Contenair +PageDeleted=Page/Contenair '%s' of website %s deleted +PageAdded=Page/Contenair '%s' added ViewSiteInNewTab=View site in new tab ViewPageInNewTab=View page in new tab SetAsHomePage=Set as Home page @@ -30,4 +32,12 @@ SetHereVirtualHost=If you can create, on your web server (Apache, Nginx, ...), a PreviewSiteServedByWebServer=Preview %s in a new tab.

The %s will be served by an external web server (like Apache, Nginx, IIS). You must install and setup this server before to point to directory:
%s
URL served by external server:
%s PreviewSiteServedByDolibarr=Preview %s in a new tab.

The %s will be served by Dolibarr server so it does not need any extra web server (like Apache, Nginx, IIS) to be installed.
The inconvenient is that URL of pages are not user friendly and start with path of your Dolibarr.
URL served by Dolibarr:
%s

To use your own external web server to serve this web site, create a virtual host on your web server that point on directory
%s
then enter the name of this virtual server and click on the other preview button. VirtualHostUrlNotDefined=URL of the virtual host served by external web server not defined -NoPageYet=No pages yet \ No newline at end of file +NoPageYet=No pages yet +SyntaxHelp=Help on code syntax +YouCanEditHtmlSourceckeditor=You can edit HTML source code using the "Source" button in editor. +YouCanEditHtmlSource=You can include PHP code into this source using tags <?php ?>. The following global variables are available: $conf, $langs, $db, $mysoc, $user, $website.

You can also include content of another Page/Container with the following syntax: <?php dolIncludeHtmlContent($websitekey.'/contentaliastoinclude.php'); ?>

To include a link to download a file stored into the documents/medias directory, use syntax:
<a href="/document.php?modulepart=medias&file=filename.ext">. +ClonePage=Clone page/container +CloneSite=Clone site +ConfirmClonePage=Please enter code/alias of new page and if it is a translation of the cloned page. +PageIsANewTranslation=The new page is a translation of the current page ? +LanguageMustNotBeSameThanClonedPage=You clone a page as a translation. The language of the new page must be different than language of source page. \ No newline at end of file diff --git a/htdocs/langs/fr_FR/withdrawals.lang b/htdocs/langs/fr_FR/withdrawals.lang index 07c87c60b23..d82237d0a64 100644 --- a/htdocs/langs/fr_FR/withdrawals.lang +++ b/htdocs/langs/fr_FR/withdrawals.lang @@ -76,7 +76,7 @@ ThisWillAlsoAddPaymentOnInvoice=Ceci créera également les paiements sur les fa StatisticsByLineStatus=Statistiques par statut des lignes RUM=RUM RUMLong=Référence Unique de Mandat -RUMWillBeGenerated=Le numéro de RUM sera généré une fois les informations de compte bancaire sont enregistrées +RUMWillBeGenerated=Si vide le numéro de RUM sera généré une fois les informations de compte bancaire sont enregistrées WithdrawMode=Mode de prélévement (FRST ou RECUR) WithdrawRequestAmount=Montant de la demande de prélèvement WithdrawRequestErrorNilAmount=Impossible de créer une demande de prélèvement pour un montant nul diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 1edc67d582f..090a35d6c83 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -457,9 +457,7 @@ if (! defined('NOLOGIN')) $passwordtotest = GETPOST('password','none',2); $entitytotest = (GETPOST('entity','int') ? GETPOST('entity','int') : (!empty($conf->entity) ? $conf->entity : 1)); - // Validation of login/pass/entity - // If ok, the variable login will be returned - // If error, we will put error message in session under the name dol_loginmesg + // Define if we received data to test the login. $goontestloop=false; if (isset($_SERVER["REMOTE_USER"]) && in_array('http',$authmode)) $goontestloop=true; if ($dolibarr_main_authentication == 'forceuser' && ! empty($dolibarr_auto_user)) $goontestloop=true; @@ -473,6 +471,9 @@ if (! defined('NOLOGIN')) $langs->setDefaultLang($langcode); } + // Validation of login/pass/entity + // If ok, the variable login will be returned + // If error, we will put error message in session under the name dol_loginmesg if ($test && $goontestloop) { $login = checkLoginPassEntity($usertotest,$passwordtotest,$entitytotest,$authmode); @@ -531,9 +532,10 @@ if (! defined('NOLOGIN')) // End test login / passwords if (! $login || (in_array('ldap',$authmode) && empty($passwordtotest))) // With LDAP we refused empty password because some LDAP are "opened" for anonymous access so connexion is a success. { - // We show login page + // No data to test login, so we show the login page dol_syslog("--- Access to ".$_SERVER["PHP_SELF"]." showing the login form and exit"); - dol_loginfunction($langs,$conf,(! empty($mysoc)?$mysoc:'')); + if (defined('NOREDIRECTBYMAINTOLOGIN')) return 'ERROR_NOT_LOGGED'; + else dol_loginfunction($langs,$conf,(! empty($mysoc)?$mysoc:'')); exit; } diff --git a/htdocs/master.inc.php b/htdocs/master.inc.php index fc1c41895a4..a8d068cfd7d 100644 --- a/htdocs/master.inc.php +++ b/htdocs/master.inc.php @@ -160,10 +160,6 @@ else if (defined('DOLENTITY') && is_numeric(DOLENTITY)) // For public page wit { $conf->entity = DOLENTITY; } -else if (!empty($_COOKIE['DOLENTITY'])) // For other application with MultiCompany module (TODO: We should remove this. entity to use should never be stored into client side) -{ - $conf->entity = $_COOKIE['DOLENTITY']; -} // Sanitize entity if (! is_numeric($conf->entity)) $conf->entity=1; diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index d789dc77b55..06a9b4037d7 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -28,9 +28,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/modulebuilder.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; -$langs->load("admin"); -$langs->load("modulebuilder"); -$langs->load("other"); +$langs->loadLangs(array("admin", "modulebuilder", "other", "cron")); $action=GETPOST('action','aZ09'); $confirm=GETPOST('confirm','alpha'); @@ -108,10 +106,15 @@ if ($dirins && $action == 'initmodule' && $modulename) // Delete some files dol_delete_file($destdir.'/myobject_card.php'); + dol_delete_file($destdir.'/myobject_note.php'); + dol_delete_file($destdir.'/myobject_document.php'); + dol_delete_file($destdir.'/myobject_agenda.php'); dol_delete_file($destdir.'/myobject_list.php'); + dol_delete_file($destdir.'/lib/myobject.lib.php'); dol_delete_file($destdir.'/test/phpunit/MyObjectTest.php'); - dol_delete_file($destdir.'/sql/llx_myobject.key.sql'); dol_delete_file($destdir.'/sql/llx_myobject.sql'); + dol_delete_file($destdir.'/sql/llx_myobject_extrafields.sql'); + dol_delete_file($destdir.'/sql/llx_myobject.key.sql'); dol_delete_file($destdir.'/scripts/myobject.php'); dol_delete_file($destdir.'/img/object_myobject.png'); dol_delete_file($destdir.'/class/myobject.class.php'); @@ -131,7 +134,7 @@ if ($dirins && $action == 'initmodule' && $modulename) 'MyModule'=>$modulename, 'MYMODULE'=>strtoupper($modulename), 'My module'=>$modulename, - 'htdocs/modulebuilder/template/'=>'', + 'htdocs/modulebuilder/template/'=>strtolower($modulename), '---Put here your own copyright and developer email---'=>dol_print_date($now,'%Y').' '.$user->getFullName($langs).($user->email?' <'.$user->email.'>':'') ); @@ -187,11 +190,16 @@ if ($dirins && $action == 'initobject' && $module && $objectname) // Delete some files $filetogenerate = array( 'myobject_card.php'=>strtolower($objectname).'_card.php', - 'myobject_list.php'=>strtolower($objectname).'_list.php', - 'test/phpunit/MyObjectTest.php'=>'test/phpunit/'.$objectname.'Test.php', - 'sql/llx_myobject.key.sql'=>'sql/llx_'.strtolower($objectname).'.key.sql', + 'myobject_note.php'=>strtolower($objectname).'_note.php', + 'myobject_document.php'=>strtolower($objectname).'_document.php', + 'myobject_agenda.php'=>strtolower($objectname).'_agenda.php', + 'myobject_list.php'=>strtolower($objectname).'_list.php', + 'lib/myobject.lib.php'=>'lib/'.strtolower($objectname).'.lib.php', + 'test/phpunit/MyObjectTest.php'=>'test/phpunit/'.$objectname.'Test.php', 'sql/llx_myobject.sql'=>'sql/llx_'.strtolower($objectname).'.sql', - 'scripts/myobject.php'=>'scripts/'.strtolower($objectname).'.php', + 'sql/llx_myobject_extrafields.sql'=>'sql/llx_'.strtolower($objectname).'_extrafields.sql', + 'sql/llx_myobject.key.sql'=>'sql/llx_'.strtolower($objectname).'.key.sql', + 'scripts/myobject.php'=>'scripts/'.strtolower($objectname).'.php', 'img/object_myobject.png'=>'img/object_'.strtolower($objectname).'.png', 'class/myobject.class.php'=>'class/'.strtolower($objectname).'.class.php', 'class/api_myobject.class.php'=>'class/api_'.strtolower($objectname).'.class.php', @@ -217,6 +225,46 @@ if ($dirins && $action == 'initobject' && $module && $objectname) else { // Copy is ok + if ($destfile == 'class/'.$objectname.'.txt') + { + // Regenerate left menu entry in descriptor + $stringtoadd=''; + // TODO Loop on each .txt file in class dir. + $stringtoadd.=" +\t\t\$this->menu[\$r++]=array( + 'fk_menu'=>'fk_mainmenu=mymodule', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type'=>'left', // This is a Left menu entry + 'titre'=>'List MyObject', + 'mainmenu'=>'mymodule', + 'leftmenu'=>'mymodule_myobject', + 'url'=>'/mymodule/myobject_list.php', + 'langs'=>'mymodule@mymodule', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>1100+\$r, + 'enabled'=>'\$conf->mymodule->enabled', // Define condition to show or hide menu entry. Use '\$conf->mymodule->enabled' if entry must be visible if module is enabled. Use '\$leftmenu==\'system\'' to show if leftmenu system is selected. + 'perms'=>'1', // Use 'perms'=>'\$user->rights->mymodule->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both +\t\t\$this->menu[\$r++]=array( + 'fk_menu'=>'fk_mainmenu=mymodule,fk_leftmenu=mymodule_myobject', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type'=>'left', // This is a Left menu entry + 'titre'=>'New MyObject', + 'mainmenu'=>'mymodule', + 'leftmenu'=>'mymodule_myobject', + 'url'=>'/mymodule/myobject_card.php?action=create', + 'langs'=>'mymodule@mymodule', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>1100+\$r, + 'enabled'=>'\$conf->mymodule->enabled', // Define condition to show or hide menu entry. Use '\$conf->mymodule->enabled' if entry must be visible if module is enabled. Use '\$leftmenu==\'system\'' to show if leftmenu system is selected. + 'perms'=>'1', // Use 'perms'=>'\$user->rights->mymodule->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both + "; + $moduledescriptorfile=$dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php'; + // TODO Allow a replace with regex using dolReplaceRegexInFile + dolReplaceInFile($moduledescriptorfile, array('END MODULEBUILDER LEFTMENU MYOBJECT */' => '*/'."\n".$stringtoadd."\n\t\t/* END MODULEBUILDER LEFTMENU MYOBJECT */")); + + // Add module descriptor to list of files to replace "MyObject' string with real name of object. + $filetogenerate[]='core/modules/mod'.$module.'.class.php'; + } } } } @@ -234,7 +282,7 @@ if ($dirins && $action == 'initobject' && $module && $objectname) 'MyModule'=>$module, 'MYMODULE'=>strtoupper($module), 'My module'=>$module, - 'htdocs/modulebuilder/template/'=>'', + 'htdocs/modulebuilder/template/'=>strtolower($modulename), 'myobject'=>strtolower($objectname), 'MyObject'=>$objectname ); @@ -318,7 +366,7 @@ if ($dirins && $action == 'confirm_delete') if ($dirins && $action == 'confirm_deleteobject' && $objectname) { - if (preg_match('/\s/', $objectname)) + if (preg_match('/[^a-z0-9]/i', $objectname)) { $error++; setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors'); @@ -335,11 +383,16 @@ if ($dirins && $action == 'confirm_deleteobject' && $objectname) // Delete some files $filetogenerate = array( 'myobject_card.php'=>strtolower($objectname).'_card.php', - 'myobject_list.php'=>strtolower($objectname).'_list.php', - 'test/phpunit/MyObjectTest.php'=>'test/phpunit/'.$objectname.'Test.php', - 'sql/llx_myobject.key.sql'=>'sql/llx_'.strtolower($objectname).'.key.sql', + 'myobject_note.php'=>strtolower($objectname).'_note.php', + 'myobject_document.php'=>strtolower($objectname).'_note.php', + 'myobject_agenda.php'=>strtolower($objectname).'_agenda.php', + 'myobject_list.php'=>strtolower($objectname).'_list.php', + 'lib/myobject.lib.php'=>'lib/'.strtolower($objectname).'.lib.php', + 'test/phpunit/MyObjectTest.php'=>'test/phpunit/'.$objectname.'Test.php', 'sql/llx_myobject.sql'=>'sql/llx_'.strtolower($objectname).'.sql', - 'scripts/myobject.php'=>'scripts/'.strtolower($objectname).'.php', + 'sql/llx_myobject_extrafields.sql'=>'sql/llx_'.strtolower($objectname).'_extrafields.sql', + 'sql/llx_myobject.key.sql'=>'sql/llx_'.strtolower($objectname).'.key.sql', + 'scripts/myobject.php'=>'scripts/'.strtolower($objectname).'.php', 'img/object_myobject.png'=>'img/object_'.strtolower($objectname).'.png', 'class/myobject.class.php'=>'class/'.strtolower($objectname).'.class.php', 'class/api_myobject.class.php'=>'class/api_'.strtolower($objectname).'.class.php', @@ -383,6 +436,7 @@ if ($dirins && $action == 'confirm_deleteproperty' && $propertykey) // File of sql $fileforsql = $dirins.'/'.$modulelowercase.'/sql/'.$objectlowercase.'.sql'; + $fileforsqlextra = $dirins.'/'.$modulelowercase.'/sql/'.$objectlowercase.'_extrafields.sql'; $fileforsqlkey = $dirins.'/'.$modulelowercase.'/sql/'.$objectlowercase.'.key.sql'; @@ -560,7 +614,11 @@ if ($action == 'savefile' && empty($cancel)) // Enable module if ($action == 'set' && $user->admin) { - $param='module='.$module; + $param=''; + if ($module) $param.='&module='.$module; + if ($tab) $param.='&tab='.$tab; + if ($tabobj) $param.='&tabobj='.$tabobj; + $value = GETPOST('value','alpha'); $resarray = activateModule($value); if (! empty($resarray['errors'])) setEventMessages('', $resarray['errors'], 'errors'); @@ -591,7 +649,11 @@ if ($action == 'set' && $user->admin) // Disable module if ($action == 'reset' && $user->admin) { - $param='module='.$module; + $param=''; + if ($module) $param.='&module='.$module; + if ($tab) $param.='&tab='.$tab; + if ($tabobj) $param.='&tabobj='.$tabobj; + $value = GETPOST('value','alpha'); $result=unActivateModule($value); if ($result) setEventMessages($result, null, 'errors'); @@ -626,43 +688,24 @@ print load_fiche_titre($text, '', 'title_setup'); $listofmodules=array(); -/* -if (!empty($conf->modulebuilder->enabled) && $mainmenu == 'modulebuilder') // Entry for Module builder -{ - global $dolibarr_main_document_root_alt; - if (! empty($dolibarr_main_document_root_alt) && is_array($dolibarr_main_document_root_alt)) - { - foreach ($dolibarr_main_document_root_alt as $diralt) - {*/ - $dirsincustom=dol_dir_list($dirins, 'directories'); - - if (is_array($dirsincustom) && count($dirsincustom) > 0) - { - foreach ($dirsincustom as $dircustomcursor) - { - $fullname = $dircustomcursor['fullname']; - if (dol_is_file($fullname.'/'.$FILEFLAG)) - { - // Get real name of module (MyModule instead of mymodule) - $descriptorfiles = dol_dir_list($fullname.'/core/modules/', 'files', 0, 'mod.*\.class\.php$'); - $modulenamewithcase=''; - foreach($descriptorfiles as $descriptorcursor) - { - $modulenamewithcase=preg_replace('/^mod/', '', $descriptorcursor['name']); - $modulenamewithcase=preg_replace('/\.class\.php$/', '', $modulenamewithcase); - } - if ($modulenamewithcase) $listofmodules[$dircustomcursor['name']]=$modulenamewithcase; - //var_dump($listofmodules); - } - } - } -/* } - } - else - { - $newmenu->add('', 'NoGeneratedModuleFound', 0, 0); - }*/ - +$dirsincustom=dol_dir_list($dirins, 'directories'); +if (is_array($dirsincustom) && count($dirsincustom) > 0) { + foreach ($dirsincustom as $dircustomcursor) { + $fullname = $dircustomcursor['fullname']; + if (dol_is_file($fullname . '/' . $FILEFLAG)) { + // Get real name of module (MyModule instead of mymodule) + $descriptorfiles = dol_dir_list($fullname . '/core/modules/', 'files', 0, 'mod.*\.class\.php$'); + $modulenamewithcase = ''; + foreach ($descriptorfiles as $descriptorcursor) { + $modulenamewithcase = preg_replace('/^mod/', '', $descriptorcursor['name']); + $modulenamewithcase = preg_replace('/\.class\.php$/', '', $modulenamewithcase); + } + if ($modulenamewithcase) + $listofmodules[$dircustomcursor['name']] = $modulenamewithcase; + // var_dump($listofmodules); + } + } +} // Show description of content $newdircustom=$dirins; @@ -700,7 +743,6 @@ if ($message) } print $langs->trans("ModuleBuilderDesc3", count($listofmodules), $FILEFLAG).'
'; -//print '
'; // Load module descriptor @@ -800,7 +842,11 @@ elseif (! empty($module)) $modulelowercase=strtolower($module); $const_name = 'MAIN_MODULE_'.strtoupper($module); - $param='&tab='.$tab.'&module='.$module; + $param=''; + if ($tab) $param.= '&tab='.$tab; + if ($module) $param.='&module='.$module; + if ($tabobj) $param.='&tabobj='.$tabobj; + $urltomodulesetup=''.$langs->trans('Home').'-'.$langs->trans("Setup").'-'.$langs->trans("Modules").''; $linktoenabledisable=''; if (! empty($conf->global->$const_name)) // If module is already activated @@ -862,6 +908,11 @@ elseif (! empty($module)) $head2[$h][2] = 'widgets'; $h++; + $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=cron&module='.$module; + $head2[$h][1] = $langs->trans("CronList"); + $head2[$h][2] = 'cron'; + $h++; + $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=buildpackage&module='.$module; $head2[$h][1] = $langs->trans("BuildPackage"); $head2[$h][2] = 'buildpackage'; @@ -1154,7 +1205,9 @@ elseif (! empty($module)) $pathtoapi = strtolower($module).'/class/api_'.strtolower($tabobj).'.class.php'; $pathtolist = strtolower($module).'/'.strtolower($tabobj).'_list.php'; $pathtocard = strtolower($module).'/'.strtolower($tabobj).'_card.php'; + $pathtophpunit = strtolower($module).'/test/phpunit/'.$tabobj.'Test.php'; $pathtosql = strtolower($module).'/sql/llx_'.strtolower($tabobj).'.sql'; + $pathtosqlextra = strtolower($module).'/sql/llx_'.strtolower($tabobj).'_extrafields.sql'; $pathtosqlkey = strtolower($module).'/sql/llx_'.strtolower($tabobj).'.key.sql'; print '
'; print ' '.$langs->trans("ClassFile").' : '.$pathtoclass.''; @@ -1163,9 +1216,15 @@ elseif (! empty($module)) print ' '.$langs->trans("ApiClassFile").' : '.$pathtoapi.''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; + print ' '.$langs->trans("TestClassFile").' : '.$pathtophpunit.''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print '
'; print ' '.$langs->trans("SqlFile").' : '.$pathtosql.''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; + print ' '.$langs->trans("SqlFileExtraFields").' : '.$pathtosqlextra.''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print '
'; print ' '.$langs->trans("SqlFileKey").' : '.$pathtosqlkey.''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; @@ -1205,11 +1264,14 @@ elseif (! empty($module)) print $form->textwithpicto($langs->trans("Label"), $langs->trans("YouCanUseTranslationKey")); print ''; print ''.$langs->trans("Type").''; - print ''.$langs->trans("Position").''; print ''.$langs->trans("NotNull").''; - print ''.$langs->trans("SearchAll").''; //print ''.$langs->trans("DefaultValue").''; print ''.$langs->trans("DatabaseIndex").''; + print ''.$langs->trans("Position").''; + print ''.$langs->trans("Enabled").''; + print ''.$langs->trans("Visible").''; + print ''.$langs->trans("IsAMeasure").''; + print ''.$langs->trans("SearchAll").''; print ''.$langs->trans("Comment").''; print ''; print ''; @@ -1217,11 +1279,14 @@ elseif (! empty($module)) print ''; print ''; print ''; - print ''; print ''; - print ''; //print ''; print ''; + print ''; + print ''; + print ''; + print ''; + print ''; print ''; print ''; print ''; @@ -1248,11 +1313,14 @@ elseif (! empty($module)) $propname=$propkey; $proplabel=$propval['label']; $proptype=$propval['type']; - $propposition=$propval['position']; $propnotnull=$propval['notnull']; $propsearchall=$propval['searchall']; //$propdefault=$propval['default']; $propindex=$propval['index']; + $propposition=$propval['position']; + $propenabled=$propval['enabled']; + $propvisible=$propval['visible']; + $propisameasure=$propval['isameasure']; $propcomment=$propval['comment']; print ''; @@ -1266,21 +1334,30 @@ elseif (! empty($module)) print ''; print $proptype; print ''; - print ''; - print $propposition; - print ''; print ''; print $propnotnull?'X':''; print ''; - print ''; - print $propsearchall?'X':''; - print ''; /*print ''; print $propdefault; print '';*/ print ''; print $propindex?'X':''; print ''; + print ''; + print $propposition; + print ''; + print ''; + print $propenabled?$propenabled:''; + print ''; + print ''; + print $propvisible?$propvisible:''; + print ''; + print ''; + print $propisameasure?$propisameasure:''; + print ''; + print ''; + print $propsearchall?'X':''; + print ''; print ''; print $propcomment; print ''; @@ -1466,6 +1543,119 @@ elseif (! empty($module)) } } + if ($tab == 'cron') + { + $pathtofile = $modulelowercase.'/core/modules/mod'.$module.'.class.php'; + + $cronjobs = $moduleobj->cronjobs; + + if ($action != 'editfile' || empty($file)) + { + print $langs->trans("CronJobDefDesc", ''.$langs->trans('CronList').'').'
'; + print '
'; + + print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print '
'; + + print '
'; + print load_fiche_titre($langs->trans("CronJobProfiles"), '', ''); + + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + + print '
'; + print ''; + + print ''; + print_liste_field_titre($langs->trans("CronLabel"),$_SERVER["PHP_SELF"],"","",$param,'',$sortfield,$sortorder); + print_liste_field_titre($langs->trans("CronTask"),'','',"",$param,'',$sortfield,$sortorder); + print_liste_field_titre($langs->trans("CronFrequency"),'',"","",$param,'',$sortfield,$sortorder); + print_liste_field_titre($langs->trans("StatusAtInstall"),$_SERVER["PHP_SELF"],"","",$param,'',$sortfield,$sortorder); + print_liste_field_titre($langs->trans("Comment"),$_SERVER["PHP_SELF"],"","",$param,'',$sortfield,$sortorder); + print "\n"; + + foreach ($cronjobs as $cron) + { + print ''; + + print ''; + + print ''; + + print ''; + + print ''; + + print ''; + + print ''; + } + + print '
'; + print $cron['label']; + print ''; + if ($cron['jobtype']=='method') + { + $text=$langs->trans("CronClass"); + $texttoshow=$langs->trans('CronModule').': '.$module.'
'; + $texttoshow.=$langs->trans('CronClass').': '. $cron['class'].'
'; + $texttoshow.=$langs->trans('CronObject').': '. $cron['objectname'].'
'; + $texttoshow.=$langs->trans('CronMethod').': '. $cron['method']; + $texttoshow.='
'.$langs->trans('CronArgs').': '. $cron['parameters']; + $texttoshow.='
'.$langs->trans('Comment').': '. $langs->trans($cron['comment']); + } + elseif ($cron['jobtype']=='command') + { + $text=$langs->trans('CronCommand'); + $texttoshow=$langs->trans('CronCommand').': '.dol_trunc($cron['command']); + $texttoshow.='
'.$langs->trans('CronArgs').': '. $cron['parameters']; + $texttoshow.='
'.$langs->trans('Comment').': '. $langs->trans($cron['comment']); + } + print $form->textwithpicto($text, $texttoshow, 1); + print '
'; + if($cron['unitfrequency'] == "60") print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Minutes'); + if($cron['unitfrequency'] == "3600") print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Hours'); + if($cron['unitfrequency'] == "86400") print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Days'); + if($cron['unitfrequency'] == "604800") print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Weeks'); + print ''; + print $cron['status']; + print ''; + if (!empty($cron['comment'])) {print $cron['comment'];} + print '
'; + print '
'; + } + else + { + $fullpathoffile=dol_buildpath($file, 0); + + $content = file_get_contents($fullpathoffile); + + // New module + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + $doleditor=new DolEditor('editfilecontent', $content, '', '300', 'Full', 'In', true, false, 'ace', 0, '99%'); + print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format','aZ09')?GETPOST('format','aZ09'):'html')); + print '
'; + print '
'; + print ''; + print '   '; + print ''; + print '
'; + + print '
'; + } + } + if ($tab == 'buildpackage') { if (! class_exists('ZipArchive') && ! defined('ODTPHP_PATHTOPCLZIP')) diff --git a/htdocs/modulebuilder/template/class/api_myobject.class.php b/htdocs/modulebuilder/template/class/api_myobject.class.php index 44e2dd2fcc4..e3e38cefd38 100644 --- a/htdocs/modulebuilder/template/class/api_myobject.class.php +++ b/htdocs/modulebuilder/template/class/api_myobject.class.php @@ -19,7 +19,7 @@ use Luracast\Restler\RestException; /** - * \file htdocs/modulebuilder/template/class/myobject_api_class.class.php + * \file htdocs/modulebuilder/template/class/api_myobject.class.php * \ingroup mymodule * \brief File for API management of myobject. */ diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index f8882b68c56..85bc84f7458 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -55,20 +55,39 @@ class MyObject extends CommonObject /** * @var string String with name of icon for myobject */ - public $picto = 'myobject'; + public $picto = 'myobject@mymodule'; + /** + * 'type' if the field format, 'label' the translation key, 'enabled' is a condition when the filed must be managed, + * 'visible' says if field is visible in list (-1 means not shown by default but can be aded into list to be viewed) + * 'notnull' if not null in database + * 'index' if we want an index in database + * 'position' is the sort order of field + * 'searchall' is 1 if we want to search in this field when making a search from the quick search button + * 'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8). + * 'comment' is not used. You can store here any text of your choice. + */ + // BEGIN MODULEBUILDER PROPERTIES /** * @var array Array with all fields and their property */ public $fields=array( - 'ref' =>array('type'=>'varchar(64)', 'label'=>'Ref', 'position'=>10, 'notnull'=>true, 'index'=>true, 'searchall'=>1, 'comment'=>'Reference of object'), - 'entity'=>array('type'=>'integer', 'label'=>'Entity', 'notnull'=>true, 'index'=>true), - 'label' =>array('type'=>'varchar(255)', 'label'=>'Label', 'searchall'=>1), - 'datec' =>array('type'=>'datetime', 'label'=>'DateCreation', 'notnull'=>true, 'position'=>500), - 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'notnull'=>true, 'position'=>500), - 'status'=>array('type'=>'integer', 'label'=>'Status', 'index'=>true, 'position'=>1000), + 'rowid' =>array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-1, 'notnull'=>true, 'index'=>true, 'position'=>1, 'comment'=>'Id'), + 'ref' =>array('type'=>'varchar(64)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>1, 'notnull'=>true, 'index'=>true, 'position'=>10, 'searchall'=>1, 'comment'=>'Reference of object'), + 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'notnull'=>true, 'index'=>true, 'position'=>20), + 'label' =>array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>1, 'visible'=>1, 'position'=>30, 'searchall'=>1), + 'amount' =>array('type'=>'double(24,8)', 'label'=>'Amount', 'enabled'=>1, 'visible'=>1, 'position'=>40, 'searchall'=>0, 'isameasure'=>1), + 'status' =>array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>1, 'index'=>true, 'position'=>1000), + 'date_creation' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-1, 'notnull'=>true, 'position'=>500), + 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>true, 'position'=>500), + //'date_valid' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-1, 'position'=>500), + 'fk_user_creat' =>array('type'=>'integer', 'label'=>'UserAuthor', 'enabled'=>1, 'visible'=>-1, 'notnull'=>true, 'position'=>500), + 'fk_user_modif' =>array('type'=>'integer', 'label'=>'UserModif', 'enabled'=>1, 'visible'=>-1, 'position'=>500), + //'fk_user_valid' =>array('type'=>'integer', 'label'=>'UserValid', 'enabled'=>1, 'visible'=>-1, 'position'=>500), + 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>true, 'position'=>500), + 'import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-1, 'index'=>true, 'position'=>1000, 'nullifempty'=>1), ); // END MODULEBUILDER PROPERTIES @@ -109,18 +128,65 @@ class MyObject extends CommonObject $this->db = $db; } + /** + * Create object into database + * + * @param User $user User that creates + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, Id of created object if OK + */ + public function create(User $user, $notrigger = false) + { + return $this->createCommon($user, $notrigger); + } + + /** + * Load object in memory from the database + * + * @param int $id Id object + * @param string $ref Ref + * @return int <0 if KO, 0 if not found, >0 if OK + */ + public function fetch($id, $ref = null) + { + return $this->fetchCommon($id, $ref); + } + + /** + * Update object into database + * + * @param User $user User that modifies + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, >0 if OK + */ + public function update(User $user, $notrigger = false) + { + return $this->updateCommon($user, $notrigger); + } + + /** + * Delete object in database + * + * @param User $user User that deletes + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, >0 if OK + */ + public function delete(User $user, $notrigger = false) + { + return $this->deleteCommon($user, $trigger); + } /** * Return a link to the object card (with optionaly the picto) * - * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) - * @param string $option On what the link point to - * @param int $notooltip 1=Disable tooltip - * @param int $maxlen Max length of visible user name - * @param string $morecss Add more css on link - * @return string String with URL + * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) + * @param string $option On what the link point to + * @param int $notooltip 1=Disable tooltip + * @param string $morecss Add more css on link + * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking + * @return string String with URL */ - function getNomUrl($withpicto=0, $option='', $notooltip=0, $maxlen=24, $morecss='') + function getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1) { global $db, $conf, $langs; global $dolibarr_main_authentication, $dolibarr_main_demo; @@ -131,18 +197,27 @@ class MyObject extends CommonObject $result = ''; $companylink = ''; - $label = '' . $langs->trans("MyModule") . ''; + $label = '' . $langs->trans("MyObject") . ''; $label.= '
'; $label.= '' . $langs->trans('Ref') . ': ' . $this->ref; - $url = DOL_URL_ROOT.'/mymodule/'.$this->table_name.'_card.php?id='.$this->id; + $url=''; + if ($option != 'nolink') + { + $url = dol_buildpath('/mymodule/myobject_card.php',1).'?id='.$this->id; + + // Add param to save lastsearch_values or not + $add_save_lastsearch_values=($save_lastsearch_value == 1 ? 1 : 0); + if ($save_lastsearch_value == -1 && preg_match('/list\.php/',$_SERVER["PHP_SELF"])) $add_save_lastsearch_values=1; + if ($add_save_lastsearch_values) $url.='&save_lastsearch_values=1'; + } $linkclose=''; if (empty($notooltip)) { if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) { - $label=$langs->trans("ShowProject"); + $label=$langs->trans("ShowMyObject"); $linkclose.=' alt="'.dol_escape_htmltag($label, 1).'"'; } $linkclose.=' title="'.dol_escape_htmltag($label, 1).'"'; @@ -223,6 +298,59 @@ class MyObject extends CommonObject } } + /** + * Charge les informations d'ordre info dans l'objet commande + * + * @param int $id Id of order + * @return void + */ + function info($id) + { + $sql = 'SELECT rowid, date_creation as datec, tms as datem,'; + $sql.= ' fk_user_creat, fk_user_modif'; + $sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; + $sql.= ' WHERE t.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; + if ($obj->fk_user_author) + { + $cuser = new User($this->db); + $cuser->fetch($obj->fk_user_author); + $this->user_creation = $cuser; + } + + if ($obj->fk_user_valid) + { + $vuser = new User($this->db); + $vuser->fetch($obj->fk_user_valid); + $this->user_validation = $vuser; + } + + if ($obj->fk_user_cloture) + { + $cluser = new User($this->db); + $cluser->fetch($obj->fk_user_cloture); + $this->user_cloture = $cluser; + } + + $this->date_creation = $this->db->jdate($obj->datec); + $this->date_modification = $this->db->jdate($obj->datem); + $this->date_validation = $this->db->jdate($obj->datev); + } + + $this->db->free($result); + + } + else + { + dol_print_error($this->db); + } + } /** * Initialise object with example values diff --git a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php index 8c7da67b7ab..5ee59c10f90 100644 --- a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php +++ b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php @@ -129,6 +129,8 @@ class modMyModule extends DolibarrModules // Example: $this->tabs = array('objecttype:+tabname1:Title1:mylangfile@mymodule:$user->rights->mymodule->read:/mymodule/mynewtab1.php?id=__ID__', // To add a new tab identified by code tabname1 // 'objecttype:+tabname2:SUBSTITUTION_Title2:mylangfile@mymodule:$user->rights->othermodule->read:/mymodule/mynewtab2.php?id=__ID__', // To add another new tab identified by code tabname2. Label will be result of calling all substitution functions on 'Title2' key. // 'objecttype:-tabname:NU:conditiontoremove'); // To remove an existing tab identified by code tabname + // Can also be: $this->tabs = array('data'=>'...', 'entity'=>0); + // // where objecttype can be // 'categories_x' to add a tab in category view (replace 'x' by type of category (0=product, 1=supplier, 2=customer, 3=member) // 'contact' to add a tab in contact view @@ -184,12 +186,13 @@ class modMyModule extends DolibarrModules ); - // Cronjobs + // Cronjobs (List of cron jobs entries to add when module is enabled) + // unit_frequency must be 60 for minute, 3600 for hour, 86400 for day, 604800 for week $this->cronjobs = array( - 0=>array('label'=>'MyJob label', 'jobtype'=>'method', 'class'=>'/mymodule/class/mymodulemyjob.class.php', 'objectname'=>'MyModuleMyJob', 'method'=>'myMethod', 'parameters'=>'', 'comment'=>'Comment', 'frequency'=>2, 'unitfrequency'=>3600, 'test'=>true) - ); // List of cron jobs entries to add - // Example: $this->cronjobs=array(0=>array('label'=>'My label', 'jobtype'=>'method', 'class'=>'/dir/class/file.class.php', 'objectname'=>'MyClass', 'method'=>'myMethod', 'parameters'=>'', 'comment'=>'Comment', 'frequency'=>2, 'unitfrequency'=>3600, 'test'=>true), - // 1=>array('label'=>'My label', 'jobtype'=>'command', 'command'=>'', 'parameters'=>'', 'comment'=>'Comment', 'frequency'=>1, 'unitfrequency'=>3600*24, 'test'=>true) + 0=>array('label'=>'MyJob label', 'jobtype'=>'method', 'class'=>'/mymodule/class/mymodulemyjob.class.php', 'objectname'=>'MyModuleMyJob', 'method'=>'myMethod', 'parameters'=>'', 'comment'=>'Comment', 'frequency'=>2, 'unitfrequency'=>3600, 'status'=>0, 'test'=>true) + ); + // Example: $this->cronjobs=array(0=>array('label'=>'My label', 'jobtype'=>'method', 'class'=>'/dir/class/file.class.php', 'objectname'=>'MyClass', 'method'=>'myMethod', 'parameters'=>'param1, param2', 'comment'=>'Comment', 'frequency'=>2, 'unitfrequency'=>3600, 'status'=>0, 'test'=>true), + // 1=>array('label'=>'My label', 'jobtype'=>'command', 'command'=>'', 'parameters'=>'param1, param2', 'comment'=>'Comment', 'frequency'=>1, 'unitfrequency'=>3600*24, 'status'=>0, 'test'=>true) // ); @@ -226,7 +229,7 @@ class modMyModule extends DolibarrModules // Example to declare a new Top Menu entry and its Left menu entry: /* BEGIN MODULEBUILDER TOPMENU */ - $this->menu[$r]=array( 'fk_menu'=>'', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + $this->menu[$r++]=array('fk_menu'=>'', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode 'type'=>'top', // This is a Top menu entry 'titre'=>'MyModule', 'mainmenu'=>'mymodule', @@ -238,12 +241,12 @@ class modMyModule extends DolibarrModules 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules 'target'=>'', 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both - // $r++; + /* END MODULEBUILDER TOPMENU */ // Example to declare a Left Menu entry into an existing Top menu entry: /* BEGIN MODULEBUILDER LEFTMENU MYOBJECT - $this->menu[$r]=array( 'fk_menu'=>'fk_mainmenu=mymodule', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + $this->menu[$r++]=array( 'fk_menu'=>'fk_mainmenu=mymodule', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode 'type'=>'left', // This is a Left menu entry 'titre'=>'List MyObject', 'mainmenu'=>'mymodule', @@ -255,8 +258,7 @@ class modMyModule extends DolibarrModules 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules 'target'=>'', 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both - $r++; - $this->menu[$r]=array( 'fk_menu'=>'fk_mainmenu=mymodule&fk_leftmenu=mymodule', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + $this->menu[$r++]=array( 'fk_menu'=>'fk_mainmenu=mymodule,fk_leftmenu=mymodule', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode 'type'=>'left', // This is a Left menu entry 'titre'=>'New MyObject', 'mainmenu'=>'mymodule', @@ -268,7 +270,6 @@ class modMyModule extends DolibarrModules 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules 'target'=>'', 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both - $r++; END MODULEBUILDER LEFTMENU MYOBJECT */ diff --git a/htdocs/modulebuilder/template/lib/mymodule.lib.php b/htdocs/modulebuilder/template/lib/mymodule.lib.php index 3c88bcdea67..cec23bd3c11 100644 --- a/htdocs/modulebuilder/template/lib/mymodule.lib.php +++ b/htdocs/modulebuilder/template/lib/mymodule.lib.php @@ -16,11 +16,9 @@ */ /** - * \file lib/mymodule.lib.php + * \file htdocs/modulebuilder/template/lib/mymodule.lib.php * \ingroup mymodule - * \brief Example module library. - * - * Put detailed description here. + * \brief Library files with common functions for MyModule */ /** diff --git a/htdocs/modulebuilder/template/lib/myobject.lib.php b/htdocs/modulebuilder/template/lib/myobject.lib.php new file mode 100644 index 00000000000..25f85052133 --- /dev/null +++ b/htdocs/modulebuilder/template/lib/myobject.lib.php @@ -0,0 +1,70 @@ +. + */ + +/** + * \file htdocs/modulebuilder/template/lib/myobject.lib.php + * \ingroup mymodule + * \brief Library files with common functions for MyObject + */ + +/** + * Prepare array of tabs for MyObject + * + * @param MyObject $object MyObject + * @return array Array of tabs + */ +function myobjectPrepareHead($object) +{ + global $langs, $conf; + + $langs->load("mymodule@mymodule"); + + $h = 0; + $head = array(); + + $head[$h][0] = dol_buildpath("/mymodule/myobject_card.php", 1).'?id='.$object->id; + $head[$h][1] = $langs->trans("Card"); + $head[$h][2] = 'card'; + $h++; + if (isset($object->fields['note_public']) || isset($object->fields['note_pricate'])) + { + $head[$h][0] = dol_buildpath("/mymodule/myobject_note.php", 1).'?id='.$object->id; + $head[$h][1] = $langs->trans("Notes"); + $head[$h][2] = 'note'; + $h++; + } + $head[$h][0] = dol_buildpath("/mymodule/myobject_document.php", 1).'?id='.$object->id; + $head[$h][1] = $langs->trans("Documents"); + $head[$h][2] = 'document'; + $h++; + $head[$h][0] = dol_buildpath("/mymodule/myobject_agenda.php", 1).'?id='.$object->id; + $head[$h][1] = $langs->trans("Events"); + $head[$h][2] = 'agenda'; + $h++; + + // Show more tabs from modules + // Entries must be declared in modules descriptor with line + //$this->tabs = array( + // 'entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__' + //); // to add new tab + //$this->tabs = array( + // 'entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__' + //); // to remove a tab + complete_head_from_modules($conf, $langs, $object, $head, $h, 'myobject@mymodule'); + + return $head; +} diff --git a/htdocs/modulebuilder/template/mymoduleindex.php b/htdocs/modulebuilder/template/mymoduleindex.php index f1c92659f9b..c6f70b0ba85 100644 --- a/htdocs/modulebuilder/template/mymoduleindex.php +++ b/htdocs/modulebuilder/template/mymoduleindex.php @@ -41,13 +41,13 @@ if (! $res) die("Include of main fails"); require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; -if (! $user->rights->mymodule->read) accessforbidden(); - -$langs->load("mymodule@mymodule"); +$langs->loadLangs(array("mymodule@mymodule")); $action=GETPOST('action', 'alpha'); + // Securite acces client +if (! $user->rights->mymodule->read) accessforbidden(); $socid=GETPOST('socid','int'); if (isset($user->societe_id) && $user->societe_id > 0) { diff --git a/htdocs/modulebuilder/template/myobject_agenda.php b/htdocs/modulebuilder/template/myobject_agenda.php new file mode 100644 index 00000000000..8db9f0877c2 --- /dev/null +++ b/htdocs/modulebuilder/template/myobject_agenda.php @@ -0,0 +1,262 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * 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 htdocs/modulebuilder/template/myobject_agenda.php + * \ingroup mymodule + * \brief Page of MyObject events + */ + +// Load Dolibarr environment +$res=0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (! $res && ! empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res=@include($_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"); +// Try main.inc.php into web root detected using web root caluclated from SCRIPT_FILENAME +$tmp=empty($_SERVER['SCRIPT_FILENAME'])?'':$_SERVER['SCRIPT_FILENAME'];$tmp2=realpath(__FILE__); $i=strlen($tmp)-1; $j=strlen($tmp2)-1; +while($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i]==$tmp2[$j]) { $i--; $j--; } +if (! $res && $i > 0 && file_exists(substr($tmp, 0, ($i+1))."/main.inc.php")) $res=@include(substr($tmp, 0, ($i+1))."/main.inc.php"); +if (! $res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php")) $res=@include(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php"); +// Try main.inc.php using relative path +if (! $res && file_exists("../main.inc.php")) $res=@include("../main.inc.php"); +if (! $res && file_exists("../../main.inc.php")) $res=@include("../../main.inc.php"); +if (! $res && file_exists("../../../main.inc.php")) $res=@include("../../../main.inc.php"); +if (! $res) die("Include of main fails"); + +require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +dol_include_once('/mymodule/class/myobject.class.php'); +dol_include_once('/mymodule/lib/myobject.lib.php'); + + +// Load traductions files requiredby by page +$langs->loadLangs(array("mymodule@mymodule","other")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'alpha'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +if (GETPOST('actioncode','array')) +{ + $actioncode=GETPOST('actioncode','array',3); + if (! count($actioncode)) $actioncode='0'; +} +else +{ + $actioncode=GETPOST("actioncode","alpha",3)?GETPOST("actioncode","alpha",3):(GETPOST("actioncode")=='0'?'0':(empty($conf->global->AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT)?'':$conf->global->AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT)); +} +$search_agenda_label=GETPOST('search_agenda_label'); + +// Security check - Protection if external user +//if ($user->societe_id > 0) access_forbidden(); +//if ($user->societe_id > 0) $socid = $user->societe_id; +//$result = restrictedArea($user, 'mymodule', $id); + +$limit = GETPOST('limit','int')?GETPOST('limit','int'):$conf->liste_limit; +$sortfield = GETPOST("sortfield",'alpha'); +$sortorder = GETPOST("sortorder",'alpha'); +$page = GETPOST("page",'int'); +if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 +$offset = $limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; +if (! $sortfield) $sortfield='a.datep,a.id'; +if (! $sortorder) $sortorder='DESC'; + +// Initialize technical objects +$object=new MyObject($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction=$conf->mymodule->dir_output . '/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('myobjectagenda')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extralabels = $extrafields->fetch_name_optionals_label('myobject'); + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals +if ($id > 0 || ! empty($ref)) $upload_dir = $conf->mymodule->multidir_output[$object->entity] . "/" . $object->id; + + + +/* + * Actions + */ + +$parameters=array('id'=>$socid); +$reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + +if (empty($reshook)) +{ + // Cancel + if (GETPOST("cancel") && ! empty($backtopage)) + { + header("Location: ".$backtopage); + exit; + } + + // Purge search criteria + 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 + { + $actioncode=''; + $search_agenda_label=''; + } +} + + + +/* + * View + */ + +$contactstatic = new Contact($db); + +$form = new Form($db); + +if ($object->id > 0) +{ + $title=$langs->trans("Agenda"); + //if (! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/thirdpartynameonly/',$conf->global->MAIN_HTML_TITLE) && $object->name) $title=$object->name." - ".$title; + $help_url = ''; + llxHeader('', $title, $help_url); + + if (! empty($conf->notification->enabled)) $langs->load("mails"); + $head = myobjectPrepareHead($object); + + + dol_fiche_head($head, 'agenda', $langs->trans("MyObject"), -1, 'myobject@mymodule'); + + // Object card + // ------------------------------------------------------------ + $linkback = '' . $langs->trans("BackToList") . ''; + + $morehtmlref='
'; + /* + // Ref customer + $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1); + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref.='
'.$langs->trans('Project') . ' '; + if ($user->rights->mymodule->creer) + { + if ($action != 'classify') + //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; + $morehtmlref.=' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref.='
'; + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=''; + $morehtmlref.='
'; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref.=''; + $morehtmlref.=$proj->ref; + $morehtmlref.=''; + } else { + $morehtmlref.=''; + } + } + }*/ + $morehtmlref.='
'; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
'; + print '
'; + + $object->info($object->id); + print dol_print_object_info($object, 1); + + print '
'; + + dol_fiche_end(); + + + + // Actions buttons + + $objthirdparty=$object; + $objcon=new stdClass(); + + $out=''; + $permok=$user->rights->agenda->myactions->create; + if ((! empty($objthirdparty->id) || ! empty($objcon->id)) && $permok) + { + //$out.='trans("AddAnAction"),'filenew'); + //$out.=""; + } + + + print '
'; + + if (! empty($conf->agenda->enabled)) + { + if (! empty($user->rights->agenda->myactions->create) || ! empty($user->rights->agenda->allactions->create)) + { + print ''.$langs->trans("AddAction").''; + } + else + { + print ''.$langs->trans("AddAction").''; + } + } + + print '
'; + + if (! empty($conf->agenda->enabled) && (!empty($user->rights->agenda->myactions->read) || !empty($user->rights->agenda->allactions->read) )) + { + $param='&socid='.$socid; + if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.$contextpage; + if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.$limit; + + + print load_fiche_titre($langs->trans("ActionsOnMyObject"),'',''); + + // List of all actions + $filters=array(); + $filters['search_agenda_label']=$search_agenda_label; + + // TODO Replace this with same code than into listactions.php + //show_actions_done($conf,$langs,$db,$object,null,0,$actioncode, '', $filters, $sortfield, $sortorder); + } +} + + +llxFooter(); + +$db->close(); diff --git a/htdocs/modulebuilder/template/myobject_card.php b/htdocs/modulebuilder/template/myobject_card.php index 994aca35c88..40f9eeb747a 100644 --- a/htdocs/modulebuilder/template/myobject_card.php +++ b/htdocs/modulebuilder/template/myobject_card.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2017 Laurent Destailleur * Copyright (C) ---Put here your own copyright and developer email--- * * This program is free software; you can redistribute it and/or modify @@ -18,9 +18,8 @@ /** * \file htdocs/modulebuilder/template/myobject_card.php - * \ingroup mymodule othermodule1 othermodule2 - * \brief This file is an example of a php page - * Put here some comments + * \ingroup mymodule + * \brief Page to create/edit/view myobject */ //if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); @@ -53,13 +52,16 @@ if (! $res && file_exists("../../../main.inc.php")) $res=@include("../../../main if (! $res) die("Include of main fails"); include_once(DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'); +include_once(DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'); dol_include_once('/mymodule/class/myobject.class.php'); +dol_include_once('/mymodule/lib/myobject.lib.php'); // Load traductions files requiredby by page -$langs->loadLangs(array("mymodule","other")); +$langs->loadLangs(array("mymodule@mymodule","other")); // Get parameters $id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); $action = GETPOST('action', 'alpha'); $cancel = GETPOST('cancel', 'aZ09'); $backtopage = GETPOST('backtopage', 'alpha'); @@ -83,11 +85,9 @@ foreach($object->fields as $key => $val) if (empty($action) && empty($id) && empty($ref)) $action='view'; -// Protection if external user -if ($user->societe_id > 0) -{ - //accessforbidden(); -} +// Security check - Protection if external user +//if ($user->societe_id > 0) access_forbidden(); +//if ($user->societe_id > 0) $socid = $user->societe_id; //$result = restrictedArea($user, 'mymodule', $id); // fetch optionals attributes and labels @@ -110,6 +110,8 @@ if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'e if (empty($reshook)) { + $error=0; + if ($cancel) { if ($action != 'addlink') @@ -125,19 +127,11 @@ if (empty($reshook)) // Action to add record if ($action == 'add' && ! empty($user->rights->mymodule->create)) { - if ($cancel) - { - $urltogo=$backtopage?$backtopage:dol_buildpath('/mymodule/myobject_list.php',1); - header("Location: ".$urltogo); - exit; - } - - $error=0; - foreach ($object->fields as $key => $val) { + if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat', 'fk_user_modif', 'import_key'))) continue; // Ignore special fields + $object->$key=GETPOST($key,'alpha'); - if (in_array($key, array('entity', 'datec', 'tms'))) continue; if ($val['notnull'] && $object->$key == '') { $error++; @@ -172,20 +166,20 @@ if (empty($reshook)) // Action to update record if ($action == 'update' && ! empty($user->rights->mymodule->create)) { - $error=0; - - $object->prop1=GETPOST("field1"); - $object->prop2=GETPOST("field2"); - - if (empty($object->ref)) - { - $error++; - setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("Ref")), null, 'errors'); - } + foreach ($object->fields as $key => $val) + { + $object->$key=GETPOST($key,'alpha'); + if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat', 'fk_user_modif', 'import_key'))) continue; + if ($val['notnull'] && $object->$key == '') + { + $error++; + setEventMessages($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv($val['label'])), null, 'errors'); + } + } if (! $error) { - $result=$object->update($user); + $result=$object->updateCommon($user); if ($result > 0) { $action='view'; @@ -207,7 +201,7 @@ if (empty($reshook)) // Action to delete if ($action == 'confirm_delete' && ! empty($user->rights->mymodule->delete)) { - $result=$object->delete($user); + $result=$object->deleteCommon($user); if ($result > 0) { // Delete OK @@ -233,6 +227,7 @@ if (empty($reshook)) */ $form=new Form($db); +$formfile=new FormFile($db); llxHeader('','MyObject',''); @@ -267,12 +262,14 @@ if ($action == 'create') print ''."\n"; foreach($object->fields as $key => $val) { - if (in_array($key, array('rowid', 'entity', 'datec', 'tms'))) continue; - print ''.$langs->trans($val['label']).''; + print '>'.$langs->trans($val['label']).''; + print ''; + print ''; } print '
'."\n"; @@ -298,8 +295,17 @@ if (($id || $ref) && $action == 'edit') dol_fiche_head(); print ''."\n"; - // print ''; - // LIST_OF_TD_LABEL_FIELDS_EDIT + foreach($object->fields as $key => $val) + { + if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat', 'fk_user_modif', 'import_key'))) continue; + print ''.$langs->trans($val['label']).''; + print ''; + print ''; + } print '
'.$langs->trans("Label").'
'; dol_fiche_end(); @@ -318,14 +324,14 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea { $res = $object->fetch_optionals($object->id, $extralabels); - $head = mymodule_prepare_head($object); - dol_fiche_head($head, 'order', $langs->trans("CustomerOrder"), -1, 'order'); + $head = myobjectPrepareHead($object); + dol_fiche_head($head, 'card', $langs->trans("MyObject"), -1, 'myobject@mymodule'); $formconfirm = ''; // Confirmation to delete if ($action == 'delete') { - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('DeleteOrder'), $langs->trans('ConfirmDeleteOrder'), 'confirm_delete', '', 0, 1); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('DeleteMyObject'), $langs->trans('ConfirmDeleteMyObject'), 'confirm_delete', '', 0, 1); } // Confirmation of action xxxx @@ -353,12 +359,9 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print $formconfirm; - // Object card // ------------------------------------------------------------ - - $linkback = '' . $langs->trans("BackToList") . ''; - + $linkback = '' . $langs->trans("BackToList") . ''; $morehtmlref='
'; /* @@ -412,9 +415,18 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print '
'; print '
'; print ''."\n"; - // print ''; - // LIST_OF_TD_LABEL_FIELDS_VIEW + foreach($object->fields as $key => $val) + { + if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat', 'fk_user_modif', 'import_key'))) continue; + print ''.$langs->trans($val['label']).''; + print ''; + print ''; + } // Other attributes include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php'; @@ -426,7 +438,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print '
'; print '
'.$langs->trans("Label").''.$object->label.'
'; - + // ... print '
'; print '
'; @@ -484,7 +496,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea // Show links to link elements - $linktoelem = $form->showLinkToObjectBlock($object, null, array('order')); + $linktoelem = $form->showLinkToObjectBlock($object, null, array('myobject')); $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem); @@ -493,7 +505,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea // List of actions on element include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php'; $formactions = new FormActions($db); - $somethingshown = $formactions->showactions($object, 'order', $socid); + $somethingshown = $formactions->showactions($object, 'myobject', $socid); print '
'; } @@ -541,7 +553,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print '
'; print '
'; print '
'; - print load_fiche_titre($langs->trans('SendOrderByMail')); + print load_fiche_titre($langs->trans('SendMyObjectByMail')); dol_fiche_head(''); @@ -569,9 +581,9 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $formmail->withtocc = $liste; $formmail->withtoccc = $conf->global->MAIN_EMAIL_USECCC; if (empty($object->ref_client)) { - $formmail->withtopic = $outputlangs->trans('SendOrderRef', '__ORDERREF__'); + $formmail->withtopic = $outputlangs->trans('SendMyObjectRef', '__REF__'); } else if (! empty($object->ref_client)) { - $formmail->withtopic = $outputlangs->trans('SendOrderRef', '__ORDERREF__ (__REFCLIENT__)'); + $formmail->withtopic = $outputlangs->trans('SendMyObjectRef', '__REF__ (__REFCLIENT__)'); } $formmail->withfile = 2; $formmail->withbody = 1; @@ -579,7 +591,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $formmail->withcancel = 1; // Tableau des substitutions $formmail->setSubstitFromObject($object); - $formmail->substit ['__ORDERREF__'] = $object->ref; + $formmail->substit ['__REF__'] = $object->ref; $custcontact = ''; $contactarr = array(); @@ -603,9 +615,9 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea // Tableau des parametres complementaires $formmail->param['action'] = 'send'; - $formmail->param['models'] = 'order_send'; + $formmail->param['models'] = 'myobject_send'; $formmail->param['models_id']=GETPOST('modelmailselected','int'); - $formmail->param['orderid'] = $object->id; + $formmail->param['myobjectid'] = $object->id; $formmail->param['returnurl'] = $_SERVER["PHP_SELF"] . '?id=' . $object->id; // Init list of files diff --git a/htdocs/modulebuilder/template/myobject_document.php b/htdocs/modulebuilder/template/myobject_document.php new file mode 100644 index 00000000000..0f8ce367bb5 --- /dev/null +++ b/htdocs/modulebuilder/template/myobject_document.php @@ -0,0 +1,183 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * 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 htdocs/modulebuilder/template/myobject_document.php + * \ingroup mymodule + * \brief Tab for documents linked to MyObject + */ + +// Load Dolibarr environment +$res=0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (! $res && ! empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res=@include($_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"); +// Try main.inc.php into web root detected using web root caluclated from SCRIPT_FILENAME +$tmp=empty($_SERVER['SCRIPT_FILENAME'])?'':$_SERVER['SCRIPT_FILENAME'];$tmp2=realpath(__FILE__); $i=strlen($tmp)-1; $j=strlen($tmp2)-1; +while($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i]==$tmp2[$j]) { $i--; $j--; } +if (! $res && $i > 0 && file_exists(substr($tmp, 0, ($i+1))."/main.inc.php")) $res=@include(substr($tmp, 0, ($i+1))."/main.inc.php"); +if (! $res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php")) $res=@include(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php"); +// Try main.inc.php using relative path +if (! $res && file_exists("../main.inc.php")) $res=@include("../main.inc.php"); +if (! $res && file_exists("../../main.inc.php")) $res=@include("../../main.inc.php"); +if (! $res && file_exists("../../../main.inc.php")) $res=@include("../../../main.inc.php"); +if (! $res) die("Include of main fails"); + +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; +dol_include_once('/mymodule/class/myobject.class.php'); +dol_include_once('/mymodule/lib/myobject.lib.php'); + +// Load traductions files requiredby by page +$langs->loadLangs(array("mymodule@mymodule","companies","other")); + + +$action=GETPOST('action','aZ09'); +$confirm=GETPOST('confirm'); +$id=(GETPOST('socid','int') ? GETPOST('socid','int') : GETPOST('id','int')); +$ref = GETPOST('ref', 'alpha'); + +// Security check - Protection if external user +//if ($user->societe_id > 0) access_forbidden(); +//if ($user->societe_id > 0) $socid = $user->societe_id; +//$result = restrictedArea($user, 'mymodule', $id); + +// Get parameters +$sortfield = GETPOST("sortfield",'alpha'); +$sortorder = GETPOST("sortorder",'alpha'); +$page = GETPOST("page",'int'); +if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 +$offset = $conf->liste_limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; +if (! $sortorder) $sortorder="ASC"; +if (! $sortfield) $sortfield="name"; + +// Initialize technical objects +$object=new MyObject($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction=$conf->mymodule->dir_output . '/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('myobjectdocument')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extralabels = $extrafields->fetch_name_optionals_label('myobject'); + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals +if ($id > 0 || ! empty($ref)) $upload_dir = $conf->mymodule->multidir_output[$object->entity] . "/" . $object->id; + + + +/* + * Actions + */ + +include_once DOL_DOCUMENT_ROOT . '/core/actions_linkedfiles.inc.php'; + + +/* + * View + */ + +$form = new Form($db); + +$title=$langs->trans("MyObject").' - '.$langs->trans("Files"); +$help_url=''; +//$help_url='EN:Module_Third_Parties|FR:Module_Tiers|ES:Empresas'; +llxHeader('', $title, $help_url); + +if ($object->id) +{ + /* + * Show tabs + */ + if (! empty($conf->notification->enabled)) $langs->load("mails"); + $head = myobjectPrepareHead($object); + + dol_fiche_head($head, 'document', $langs->trans("MyObject"), -1, 'myobject@mymodule'); + + + // Construit liste des fichiers + $filearray=dol_dir_list($upload_dir,"files",0,'','(\.meta|_preview.*\.png)$',$sortfield,(strtolower($sortorder)=='desc'?SORT_DESC:SORT_ASC),1); + $totalsize=0; + foreach($filearray as $key => $file) + { + $totalsize+=$file['size']; + } + + // Object card + // ------------------------------------------------------------ + $linkback = '' . $langs->trans("BackToList") . ''; + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
'; + + print '
'; + print ''; + + // Prefix + if (! empty($conf->global->SOCIETE_USEPREFIX)) // Old not used prefix field + { + print ''; + } + + if ($object->client) + { + print ''; + } + + if ($object->fournisseur) + { + print ''; + } + + // Number of files + print ''; + + // Total size + print ''; + + print '
'.$langs->trans('Prefix').''.$object->prefix_comm.'
'; + print $langs->trans('CustomerCode').''; + print $object->code_client; + if ($object->check_codeclient() <> 0) print ' ('.$langs->trans("WrongCustomerCode").')'; + print '
'; + print $langs->trans('SupplierCode').''; + print $object->code_fournisseur; + if ($object->check_codefournisseur() <> 0) print ' ('.$langs->trans("WrongSupplierCode").')'; + print '
'.$langs->trans("NbOfAttachedFiles").''.count($filearray).'
'.$langs->trans("TotalSizeOfAttachedFiles").''.$totalsize.' '.$langs->trans("bytes").'
'; + + print '
'; + + dol_fiche_end(); + + $modulepart = 'societe'; + $permission = $user->rights->societe->creer; + $permtoedit = $user->rights->societe->creer; + $param = '&id=' . $object->id; + include_once DOL_DOCUMENT_ROOT . '/core/tpl/document_actions_post_headers.tpl.php'; +} +else +{ + accessforbidden('',0,0); +} + + +llxFooter(); +$db->close(); diff --git a/htdocs/modulebuilder/template/myobject_list.php b/htdocs/modulebuilder/template/myobject_list.php index 9d1019affee..81e0612cea5 100644 --- a/htdocs/modulebuilder/template/myobject_list.php +++ b/htdocs/modulebuilder/template/myobject_list.php @@ -18,9 +18,8 @@ /** * \file htdocs/modulebuilder/template/myobject_list.php - * \ingroup mymodule othermodule1 othermodule2 - * \brief This file is an example of a php page - * Put here some comments + * \ingroup mymodule + * \brief List page for myobject */ //if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); @@ -59,7 +58,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; dol_include_once('/mymodule/class/myobject.class.php'); // Load traductions files requiredby by page -$langs->loadLangs(array("mymodule","other")); +$langs->loadLangs(array("mymodule@mymodule","other")); $action = GETPOST('action','alpha'); $massaction = GETPOST('massaction','alpha'); @@ -123,7 +122,8 @@ foreach($object->fields as $key => $val) $arrayfields=array(); foreach($object->fields as $key => $val) { - $arrayfields['t.'.$key]=array('label'=>$val['label'], 'checked'=>1); + // If $val['visible']==0, then we never show the field + if (! empty($val['visible'])) $arrayfields['t.'.$key]=array('label'=>$val['label'], 'checked'=>(($val['visible']<0)?0:1), 'enabled'=>$val['enabled']); } // Extra fields if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) @@ -216,7 +216,8 @@ if (is_array($extrafields->attribute_label) && count($extrafields->attribute_lab $sql.= " WHERE t.entity IN (".getEntity('myobject').")"; foreach($search as $key => $val) { - if ($search[$key] != '') $sql.=natural_search($key, $search[$key], (($key == 'status')?2:($object->fields[$key]['type'] == 'integer'?1:0))); + $mode=(($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key]))?1:0); + if ($search[$key] != '') $sql.=natural_search($key, $search[$key], (($key == 'status')?2:$mode)); } if ($search_all) $sql.= natural_search(array_keys($fieldstosearchall), $search_all); // Add where from extra fields @@ -226,7 +227,7 @@ foreach ($search_array_options as $key => $val) $tmpkey=preg_replace('/search_options_/','',$key); $typ=$extrafields->attribute_type[$tmpkey]; $mode=0; - if (in_array($typ, array('int','double'))) $mode=1; // Search on a numeric + if (in_array($typ, array('int','double','real'))) $mode=1; // Search on a numeric if ($val && ( ($crit != '' && ! in_array($typ, array('select'))) || ! empty($crit))) { $sql .= natural_search('ef.'.$tmpkey, $crit, $mode); @@ -306,9 +307,10 @@ foreach ($search_array_options as $key => $val) if ($val != '') $param.='&search_options_'.$tmpkey.'='.urlencode($val); } +// List of mass actions available $arrayofmassactions = array( - 'presend'=>$langs->trans("SendByMail"), - 'builddoc'=>$langs->trans("PDFMerge"), + //'presend'=>$langs->trans("SendByMail"), + //'builddoc'=>$langs->trans("PDFMerge"), ); if ($user->rights->mymodule->delete) $arrayofmassactions['delete']=$langs->trans("Delete"); if ($massaction == 'presend') $arrayofmassactions=array(); @@ -324,7 +326,7 @@ print ''; print ''; print ''; -print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_companies', 0, '', '', $limit); +print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'title_companies', 0, '', '', $limit); if ($sall) { @@ -362,10 +364,11 @@ print ''; foreach($object->fields as $key => $val) { - if (in_array($key, array('datec','tms','status'))) continue; + if (in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; $align=''; if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; if (in_array($val['type'], array('timestamp'))) $align.=' nowrap'; + if ($key == 'status') $align.=($align?' ':'').'center'; if (! empty($arrayfields['t.'.$key]['checked'])) print ''; } // Extra fields @@ -398,10 +401,11 @@ print $hookmanager->resPrint; // Rest of fields search foreach($object->fields as $key => $val) { - if (! in_array($key, array('datec','tms','status'))) continue; + if (! in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; $align=''; if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; if (in_array($val['type'], array('timestamp'))) $align.=' nowrap'; + if ($key == 'status') $align.=($align?' ':'').'center'; if (! empty($arrayfields['t.'.$key]['checked'])) print ''; } // Action column @@ -417,10 +421,11 @@ print ''."\n"; print ''; foreach($object->fields as $key => $val) { - if (in_array($key, array('datec','tms','status'))) continue; + if (in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; $align=''; if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; if (in_array($val['type'], array('timestamp'))) $align.='nowrap'; + if ($key == 'status') $align.=($align?' ':'').'center'; if (! empty($arrayfields['t.'.$key]['checked'])) print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($align?'class="'.$align.'"':''), $sortfield, $sortorder, $align.' ')."\n"; } // Extra fields @@ -444,10 +449,11 @@ print $hookmanager->resPrint; // Rest of fields title foreach($object->fields as $key => $val) { - if (! in_array($key, array('datec','tms','status'))) continue; + if (! in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; $align=''; if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; if (in_array($val['type'], array('timestamp'))) $align.=' nowrap'; + if ($key == 'status') $align.=($align?' ':'').'center'; if (! empty($arrayfields['t.'.$key]['checked'])) print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($align?'class="'.$align.'"':''), $sortfield, $sortorder, $align.' ')."\n"; } print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"],"",'','','align="center"',$sortfield,$sortorder,'maxwidthsearch ')."\n"; @@ -471,22 +477,36 @@ while ($i < min($num, $limit)) $obj = $db->fetch_object($resql); if ($obj) { + // Store properties in $object + $object->id = $obj->rowid; + foreach($object->fields as $key => $val) + { + if (isset($obj->$key)) $object->$key = $obj->$key; + } + // Show here line of result print ''; foreach($object->fields as $key => $val) { - if (in_array($key, array('datec','tms','status'))) continue; + if (in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; $align=''; if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; if (in_array($val['type'], array('timestamp'))) $align.='nowrap'; + if ($key == 'status') $align.=($align?' ':'').'center'; if (! empty($arrayfields['t.'.$key]['checked'])) { print ''; if (in_array($val['type'], array('date','datetime','timestamp'))) print dol_print_date($db->jdate($obj->$key), 'dayhour'); - elseif ($key == 'status') print ''; + elseif ($key == 'ref') print $object->getNomUrl(1, '', 0, '', 1); + elseif ($key == 'status') print $object->getLibStatut(3); else print $obj->$key; print ''; if (! $i) $totalarray['nbfield']++; + if (! empty($val['isameasure'])) + { + if (! $i) $totalarray['pos'][$totalarray['nbfield']]='t.'.$key; + $totalarray['val']['t.'.$key] += $obj->$key; + } } } // Extra fields @@ -504,6 +524,11 @@ while ($i < min($num, $limit)) print $extrafields->showOutputField($key, $obj->$tmpkey, '', 1); print ''; if (! $i) $totalarray['nbfield']++; + if (! empty($val['isameasure'])) + { + if (! $i) $totalarray['pos'][$totalarray['nbfield']]='ef.'.$tmpkey; + $totalarray['val']['ef.'.$tmpkey] += $obj->$tmpkey; + } } } } @@ -514,18 +539,24 @@ while ($i < min($num, $limit)) // Rest of fields foreach($object->fields as $key => $val) { - if (! in_array($key, array('datec','tms','status'))) continue; + if (! in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; $align=''; - if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; - if (in_array($val['type'], array('timestamp'))) $align.='nowrap'; + if (in_array($val['type'], array('date','datetime','timestamp'))) $align.=($align?' ':'').'center'; + if (in_array($val['type'], array('timestamp'))) $align.=($align?' ':'').'nowrap'; + if ($key == 'status') $align.=($align?' ':'').'center'; if (! empty($arrayfields['t.'.$key]['checked'])) { print ''; if (in_array($val['type'], array('date','datetime','timestamp'))) print dol_print_date($db->jdate($obj->$key), 'dayhour'); - elseif ($key == 'status') print ''; + elseif ($key == 'status') print $object->getLibStatut(3); else print $obj->$key; print ''; if (! $i) $totalarray['nbfield']++; + if (! empty($val['isameasure'])) + { + if (! $i) $totalarray['pos'][$totalarray['nbfield']]='t.'.$key; + $totalarray['val']['t.'.$key] += $obj->$key; + } } } // Action column @@ -545,22 +576,23 @@ while ($i < min($num, $limit)) } // Show total line -if (isset($totalarray['totalhtfield'])) +if (isset($totalarray['pos'])) { print ''; $i=0; while ($i < $totalarray['nbfield']) { $i++; - if ($i == 1) + if (! empty($totalarray['pos'][$i])) print ''; + else { - if ($num < $limit) print ''; - else print ''; + if ($i == 1) + { + if ($num < $limit) print ''; + else print ''; + } + print ''; } - elseif ($totalarray['totalhtfield'] == $i) print ''; - elseif ($totalarray['totalvatfield'] == $i) print ''; - elseif ($totalarray['totalttcfield'] == $i) print ''; - else print ''; } print ''; } diff --git a/htdocs/modulebuilder/template/myobject_note.php b/htdocs/modulebuilder/template/myobject_note.php new file mode 100644 index 00000000000..782be1c5bb9 --- /dev/null +++ b/htdocs/modulebuilder/template/myobject_note.php @@ -0,0 +1,163 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * 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 htdocs/modulebuilder/template/myobject_note.php + * \ingroup mymodule + * \brief Car with notes on MyObject + */ + +// Load Dolibarr environment +$res=0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (! $res && ! empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res=@include($_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"); +// Try main.inc.php into web root detected using web root caluclated from SCRIPT_FILENAME +$tmp=empty($_SERVER['SCRIPT_FILENAME'])?'':$_SERVER['SCRIPT_FILENAME'];$tmp2=realpath(__FILE__); $i=strlen($tmp)-1; $j=strlen($tmp2)-1; +while($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i]==$tmp2[$j]) { $i--; $j--; } +if (! $res && $i > 0 && file_exists(substr($tmp, 0, ($i+1))."/main.inc.php")) $res=@include(substr($tmp, 0, ($i+1))."/main.inc.php"); +if (! $res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php")) $res=@include(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php"); +// Try main.inc.php using relative path +if (! $res && file_exists("../main.inc.php")) $res=@include("../main.inc.php"); +if (! $res && file_exists("../../main.inc.php")) $res=@include("../../main.inc.php"); +if (! $res && file_exists("../../../main.inc.php")) $res=@include("../../../main.inc.php"); +if (! $res) die("Include of main fails"); + +dol_include_once('/mymodule/class/myobject.class.php'); +dol_include_once('/mymodule/lib/myobject.lib.php'); + +// Load traductions files requiredby by page +$langs->loadLangs(array("mymodule@mymodule","companies")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'alpha'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +// Initialize technical objects +$object=new MyObject($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction=$conf->mymodule->dir_output . '/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('myobjectnote')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extralabels = $extrafields->fetch_name_optionals_label('myobject'); + +// Security check - Protection if external user +//if ($user->societe_id > 0) access_forbidden(); +//if ($user->societe_id > 0) $socid = $user->societe_id; +//$result = restrictedArea($user, 'mymodule', $id); + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals +if ($id > 0 || ! empty($ref)) $upload_dir = $conf->mymodule->multidir_output[$object->entity] . "/" . $object->id; + +$permissionnote=1; +//$permissionnote=$user->rights->mymodule->creer; // Used by the include of actions_setnotes.inc.php + + +/* + * Actions + */ + +include DOL_DOCUMENT_ROOT.'/core/actions_setnotes.inc.php'; // Must be include, not include_once + + +/* + * View + */ + +$form = new Form($db); + +//$help_url='EN:Customers_Orders|FR:Commandes_Clients|ES:Pedidos de clientes'; +$help_url=''; +llxHeader('',$langs->trans('MyObject'),$help_url); + +if ($id > 0 || ! empty($ref)) +{ + $object->fetch_thirdparty(); + + $head = myobjectPrepareHead($object); + + dol_fiche_head($head, 'note', $langs->trans("MyObject"), -1, 'myobject@mymodule'); + + // Object card + // ------------------------------------------------------------ + $linkback = '' . $langs->trans("BackToList") . ''; + + $morehtmlref='
'; + /* + // Ref customer + $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1); + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref.='
'.$langs->trans('Project') . ' '; + if ($user->rights->mymodule->creer) + { + if ($action != 'classify') + //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; + $morehtmlref.=' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref.='
'; + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=''; + $morehtmlref.=''; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref.=''; + $morehtmlref.=$proj->ref; + $morehtmlref.=''; + } else { + $morehtmlref.=''; + } + } + }*/ + $morehtmlref.='
'; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + + print '
'; + print '
'; + + + $cssclass="titlefield"; + include DOL_DOCUMENT_ROOT.'/core/tpl/notes.tpl.php'; + + print '
'; + + dol_fiche_end(); +} + + +llxFooter(); +$db->close(); diff --git a/htdocs/modulebuilder/template/sql/llx_myobject.sql b/htdocs/modulebuilder/template/sql/llx_myobject.sql index b5810f0f227..1c47004f4e7 100644 --- a/htdocs/modulebuilder/template/sql/llx_myobject.sql +++ b/htdocs/modulebuilder/template/sql/llx_myobject.sql @@ -19,8 +19,10 @@ CREATE TABLE llx_myobject( -- BEGIN MODULEBUILDER FIELDS entity INTEGER DEFAULT 1 NOT NULL, label VARCHAR(255), - datec DATETIME NOT NULL, + qty INTEGER, + status INTEGER, + date_creation DATETIME NOT NULL, tms TIMESTAMP NOT NULL, - status INTEGER + import_key VARCHAR(14) -- END MODULEBUILDER FIELDS ) ENGINE=innodb; \ No newline at end of file diff --git a/htdocs/modulebuilder/template/sql/llx_myobject_extrafields.sql b/htdocs/modulebuilder/template/sql/llx_myobject_extrafields.sql new file mode 100644 index 00000000000..72c672a92f8 --- /dev/null +++ b/htdocs/modulebuilder/template/sql/llx_myobject_extrafields.sql @@ -0,0 +1,23 @@ +-- Copyright (C) ---Put here your own copyright and developer email--- +-- +-- 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 . + +create table llx_myobject_extrafields +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + tms timestamp, + fk_object integer NOT NULL, + import_key varchar(14) -- import key +) ENGINE=innodb; + diff --git a/htdocs/product/card.php b/htdocs/product/card.php index 0a6c9052b91..318d19e10b3 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -990,11 +990,11 @@ else // Stock min level if ($type != 1 && ! empty($conf->stock->enabled)) { - print '
'; // Stock desired level - print ''; } diff --git a/htdocs/product/inventory/card.php b/htdocs/product/inventory/card.php index e47891a6d08..5506bad0fbb 100644 --- a/htdocs/product/inventory/card.php +++ b/htdocs/product/inventory/card.php @@ -1,5 +1,6 @@ +/* Copyright (C) 2007-2017 Laurent Destailleur + * Copyright (C) ---Put here your own copyright and developer email--- * * 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 @@ -16,48 +17,78 @@ */ /** - * \file htdocs/inventory/card.php - * \ingroup product - * \brief File of class to manage inventory + * \file product/inventory/card.php + * \ingroup inventory + * \brief This file is an example of a php page + * Put here some comments */ - -require_once '../../main.inc.php'; -require_once DOL_DOCUMENT_ROOT.'/product/inventory/listview.class.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; -include_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; -require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; -require_once DOL_DOCUMENT_ROOT.'/product/inventory/class/inventory.class.php'; -require_once DOL_DOCUMENT_ROOT.'/product/inventory/lib/inventory.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB','1'); +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1'); +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION','1'); // Do not check anti CSRF attack test +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION','1'); // Do not check anti CSRF attack test +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK','1'); // Do not check anti CSRF attack test +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK','1'); // Do not check style html tag into posted data +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL','1'); // Do not check anti POST attack test +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN",'1'); // If this page is public (can be called outside logged session) +// Load Dolibarr environment +$res=0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (! $res && ! empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res=@include($_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"); +// Try main.inc.php into web root detected using web root caluclated from SCRIPT_FILENAME +$tmp=empty($_SERVER['SCRIPT_FILENAME'])?'':$_SERVER['SCRIPT_FILENAME'];$tmp2=realpath(__FILE__); $i=strlen($tmp)-1; $j=strlen($tmp2)-1; +while($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i]==$tmp2[$j]) { $i--; $j--; } +if (! $res && $i > 0 && file_exists(substr($tmp, 0, ($i+1))."/main.inc.php")) $res=@include(substr($tmp, 0, ($i+1))."/main.inc.php"); +if (! $res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php")) $res=@include(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php"); +// Try main.inc.php using relative path +if (! $res && file_exists("../main.inc.php")) $res=@include("../main.inc.php"); +if (! $res && file_exists("../../main.inc.php")) $res=@include("../../main.inc.php"); +if (! $res && file_exists("../../../main.inc.php")) $res=@include("../../../main.inc.php"); +if (! $res) die("Include of main fails"); -$langs->load('stock'); -$langs->load('inventory'); +include_once(DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'); +dol_include_once('/inventory/class/inventory.class.php'); -$id=GETPOST('id', 'int'); -$ref=GETPOST('ref', 'alpha'); -$action=(GETPOST('action','alpha') ? GETPOST('action','alpha') : 'view'); -$cancel=GETPOST('cancel'); -$confirm=GETPOST('confirm','alpha'); -$socid=GETPOST('socid','int'); -if (! empty($user->societe_id)) $socid=$user->societe_id; +// Load traductions files requiredby by page +$langs->loadLangs(array("inventory","other")); + +// Get parameters +$id = GETPOST('id', 'int'); +$action = GETPOST('action', 'alpha'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +// Initialize technical objects +$object=new Inventory($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction=$conf->inventory->dir_output . '/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('inventorycard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extralabels = $extrafields->fetch_name_optionals_label('inventory'); +$search_array_options=$extrafields->getOptionalsFromPost($extralabels,'','search_'); + +// Initialize array of search criterias +$search_all=trim(GETPOST("search_all",'alpha')); +$search=array(); +foreach($object->fields as $key => $val) +{ + if (GETPOST('search_'.$key,'alpha')) $search[$key]=GETPOST('search_'.$key,'alpha'); +} if (empty($action) && empty($id) && empty($ref)) $action='view'; // Protection if external user if ($user->societe_id > 0) { - //accessforbidden(); + //accessforbidden(); } -$result = restrictedArea($user, 'stock', $id); - - -$object = new Inventory($db); -$extrafields = new ExtraFields($db); +//$result = restrictedArea($user, 'inventory', $id); // fetch optionals attributes and labels $extralabels = $extrafields->fetch_name_optionals_label($object->table_element); @@ -65,623 +96,526 @@ $extralabels = $extrafields->fetch_name_optionals_label($object->table_element); // Load object include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals -// Initialize technical object to manage hooks of modules. Note that conf->hooks_modules contains array array -$hookmanager->initHooks(array('inventorycard')); - /* - * Actions + * ACTIONS + * + * Put here all code to do according to value of "action" parameter */ -$parameters=array('id'=>$id, 'ref'=>$ref, 'objcanvas'=>$objcanvas); +$parameters=array(); $reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); if (empty($reshook)) { - if ($cancel) - { - if ($action != 'addlink') - { - $urltogo=$backtopage?$backtopage:dol_buildpath('/product/inventory/list.php',1); - header("Location: ".$urltogo); - exit; - } - if ($id > 0 || ! empty($ref)) $ret = $object->fetch($id,$ref); - $action=''; - } - - if ($action == 'confirmCreate') - { - if (empty($user->rights->stock->creer)) accessforbidden(); - - if ($cancel) + $error=0; + + if ($cancel) + { + if ($action != 'addlink') { - $urltogo=$backtopage?$backtopage:dol_buildpath('/product/inventory/list.php',1); - header("Location: ".$urltogo); - exit; + $urltogo=$backtopage?$backtopage:dol_buildpath('/inventory/inventory_list.php',1); + header("Location: ".$urltogo); + exit; } - - $error=0; - - $object->setValues($_POST); - - $fk_inventory = $object->create($user); - if ($fk_inventory>0) - { - $fk_category = (int) GETPOST('fk_category'); - $fk_supplier = (int) GETPOST('fk_supplier'); - $fk_warehouse = (int) GETPOST('fk_warehouse'); - $only_prods_in_stock = (int) GETPOST('OnlyProdsInStock'); - - $object->addProductsFor($fk_warehouse,$fk_category,$fk_supplier,$only_prods_in_stock); - $object->update($user); - - header('Location: '.dol_buildpath('/product/inventory/card.php?id='.$object->id.'&action=edit', 1)); - exit; - } - else + if ($id > 0 || ! empty($ref)) $ret = $object->fetch($id,$ref); + $action=''; + } + + // Action to add record + if ($action == 'add' && ! empty($user->rights->inventory->create)) + { + foreach ($object->fields as $key => $val) { - setEventMessage($object->error,'errors'); - header('Location: '.dol_buildpath('/product/inventory/card.php?action=create', 1)); - exit; + if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'import_key'))) continue; // Ignore special fields + + $object->$key=GETPOST($key,'alpha'); + if ($val['notnull'] && $object->$key == '') + { + $error++; + setEventMessages($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv($val['label'])), null, 'errors'); + } } - } - - switch($action) { - case 'save': - if (!$user->rights->stock->creer) accessforbidden(); - - - $id = GETPOST('id'); - - $object = new Inventory($db); - $object->fetch($id); - - $object->setValues($_REQUEST); - - if ($object->errors) - { - setEventMessage($object->errors, 'errors'); - $action = 'edit'; - } - else - { - $object->udpate($user); - header('Location: '.dol_buildpath('/product/inventory/card.php?id='.$object->getId().'&action=view', 1)); - exit; - } - - break; - - case 'confirm_regulate': - if (!$user->rights->stock->creer) accessforbidden(); - $id = GETPOST('id'); - - $object = new Inventory($db); - $object->fetch($id); - - if($object->status == 0) { - $object->status = 1; - $object->update($user); - - $action='view'; + + if (! $error) + { + $result=$object->createCommon($user); + if ($result > 0) + { + // Creation OK + $urltogo=$backtopage?$backtopage:dol_buildpath('/inventory/inventory_list.php',1); + header("Location: ".$urltogo); + exit; + } + else + { + // Creation KO + if (! empty($object->errors)) setEventMessages(null, $object->errors, 'errors'); + else setEventMessages($object->error, null, 'errors'); + $action='create'; + } + } + else + { + $action='create'; + } + } + + // Action to update record + if ($action == 'update' && ! empty($user->rights->inventory->create)) + { + foreach ($object->fields as $key => $val) + { + $object->$key=GETPOST($key,'alpha'); + if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'import_key'))) continue; + if ($val['notnull'] && $object->$key == '') + { + $error++; + setEventMessages($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv($val['label'])), null, 'errors'); } - else { - $action='view'; - } - - break; - - case 'confirm_changePMP': - - $id = GETPOST('id'); - - $object = new Inventory($db); - $object->fetch( $id ); - - $object->changePMP($user); - - $action='view'; - - break; - - case 'add_line': - if (!$user->rights->stock->creer) accessforbidden(); - - $id = GETPOST('id'); - $fk_warehouse = GETPOST('fk_warehouse'); - - $object = new Inventory($db); - $object->fetch( $id ); - - $fk_product = GETPOST('fk_product'); - if ($fk_product>0) - { - $product = new Product($db); - if($product->fetch($fk_product)<=0 || $product->type != 0) { - setEventMessage($langs->trans('ThisIsNotAProduct'),'errors'); - } - else{ - - //Check product not already exists - $alreadyExists = false; - if(!empty($object->Inventorydet)) { - foreach ($object->Inventorydet as $invdet) - { - if ($invdet->fk_product == $product->id - && $invdet->fk_warehouse == $fk_warehouse) - { - $alreadyExists = true; - break; - } - } - } - if (!$alreadyExists) - { - if($object->addProduct($product->id, $fk_warehouse)) { - setEventMessage($langs->trans('ProductAdded')); - } - } - else - { - setEventMessage($langs->trans('inventoryWarningProductAlreadyExists'), 'warnings'); - } - - } - - $object->update($user); - $object->sortDet(); - } - - $action='edit'; - - break; - - case 'confirm_delete_line': - if (!$user->rights->stock->creer) accessforbidden(); - - - //Cette action devrais se faire uniquement si le status de l'inventaire est à 0 mais aucune vérif - $rowid = GETPOST('rowid'); - $objectdet = new Inventorydet($db); - if($objectdet->fetch($rowid)>0) { - $objectdet->delete($user); - setEventMessage("ProductDeletedFromInventory"); - } - $id = GETPOST('id'); - $object = new Inventory($db); - $object->fetch( $id); - - $action='edit'; - - break; - case 'confirm_flush': - if (!$user->rights->stock->creer) accessforbidden(); - - - $id = GETPOST('id'); - - $object = new Inventory($db); - $object->fetch($id); - - $object->deleteAllLine($user); - - setEventMessage($langs->trans('InventoryFlushed')); - - $action='edit'; - - break; - case 'confirm_delete': - if (!$user->rights->stock->supprimer) accessforbidden(); - - $id = GETPOST('id'); - - $object = new Inventory($db); - $object->fetch($id); - - $object->delete($user); - - setEventMessage($langs->trans('InventoryDeleted')); - - header('Location: '.dol_buildpath('/inventory/list.php', 1)); - exit; - - break; - /*case 'exportCSV': - - $id = GETPOST('id'); - - $object = new Inventory($db); - $object->fetch($id); - - _exportCSV($object); - - exit; - break; - */ - } + } + + if (! $error) + { + $result=$object->updateCommon($user); + if ($result > 0) + { + $action='view'; + } + else + { + // Creation KO + if (! empty($object->errors)) setEventMessages(null, $object->errors, 'errors'); + else setEventMessages($object->error, null, 'errors'); + $action='edit'; + } + } + else + { + $action='edit'; + } + } + + // Action to delete + if ($action == 'confirm_delete' && ! empty($user->rights->inventory->delete)) + { + $result=$object->deleteCommon($user); + if ($result > 0) + { + // Delete OK + setEventMessages("RecordDeleted", null, 'mesgs'); + header("Location: ".dol_buildpath('/inventory/inventory_list.php',1)); + exit; + } + else + { + if (! empty($object->errors)) setEventMessages(null, $object->errors, 'errors'); + else setEventMessages($object->error, null, 'errors'); + } + } } + + /* - * Views + * VIEW + * + * Put here all code to build page */ $form=new Form($db); -llxHeader('',$langs->trans('Inventory'),'',''); - +llxHeader('','Inventory',''); + +// Example : Adding jquery code +print ''; + + +// Part to create if ($action == 'create') { - if (empty($user->rights->stock->creer)) accessforbidden(); + print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("Inventory"))); - print load_fiche_titre($langs->trans("NewInventory")); - - echo '
'; - echo ''; - - dol_fiche_head(); - - $formproduct = new FormProduct($db); - - ?> -
'.$object->getLibStatut(3).''.$object->getLibStatut(3).'
'.price($totalarray['val'][$totalarray['pos'][$i]]).''.$langs->trans("Total").''.$langs->trans("Totalforthispage").''.$langs->trans("Total").''.$langs->trans("Totalforthispage").''.price($totalarray['totalht']).''.price($totalarray['totalvat']).''.price($totalarray['totalttc']).'
'.$langs->trans("StockLimit").''; + print '
'.$form->textwithpicto($langs->trans("StockLimit"), $langs->trans("StockLimitDesc"), 1).''; print ''; print ''.$langs->trans("DesiredStock").''; + print ''.$form->textwithpicto($langs->trans("DesiredStock"), $langs->trans("DesiredStockDesc"), 1).''; print ''; print '
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
trans('Title') ?>
trans('Date') ?>select_date(time(),'date_inventory'); ?>
trans('inventorySelectWarehouse') ?>selectWarehouses('', 'fk_warehouse') ?>
trans('SelectCategory') ?>select_all_categories(0,'', 'fk_category') ?>
trans('SelectFournisseur') ?>select_thirdparty('','fk_supplier','s.fournisseur = 1') ?>
trans('OnlyProdsInStock') ?>
- '; - print ''; - print '     '; - print ''; - print ''; - - echo ''; - + print '
'; + print ''; + print ''; + print ''; + + dol_fiche_head(array(), ''); + + print ''."\n"; + foreach($object->fields as $key => $val) + { + if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'import_key'))) continue; + print ''.$langs->trans($val['label']).''; + } + print '
'."\n"; + + dol_fiche_end(); + + print '
 
'; + + print '
'; } -if ($action == 'view' || $action == 'edit' || empty($action)) + + +// Part to edit record +if (($id || $ref) && $action == 'edit') { - $object = new Inventory($db); - $result = $object->fetch($id); - if ($result < 0) dol_print_error($db, $object->error, $object->errors); - - $warehouse = new Entrepot($db); - $warehouse->fetch($object->fk_warehouse); - - - - if($action == 'changePMP') - { - print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ApplyNewPMP'), $langs->trans('ConfirmApplyNewPMP', $object->getTitle()), 'confirm_changePMP', array(),'no',1); - } - else if($action == 'flush') - { - print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id,$langs->trans('FlushInventory'),$langs->trans('ConfirmFlushInventory',$object->getTitle()),'confirm_flush',array(),'no',1); - } - else if($action == 'delete') - { - print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id,$langs->trans('Delete'),$langs->trans('ConfirmDelete',$object->getTitle()),'confirm_delete',array(),'no',1); - } - else if($action == 'delete_line') - { - print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&rowid='.GETPOST('rowid'),$langs->trans('DeleteLine'),$langs->trans('ConfirmDeleteLine',$object->getTitle()),'confirm_delete_line',array(),'no',1); - } - else if($action == 'regulate') - { - print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id,$langs->trans('RegulateStock'),$langs->trans('ConfirmRegulateStock',$object->getTitle()),'confirm_regulate',array(),'no',1); - } - - print dol_get_fiche_head(inventoryPrepareHead($object, $langs->trans('inventoryOfWarehouse', $warehouse->libelle), empty($action) ? '': '&action='.$action)); - - $lines = array(); - card_line($object, $lines, $action); - - print $langs->trans('Ref')." ".$object->ref.'
'; - print $langs->trans('Date')." ".$object->getDate('date_inventory').'

'; - - $objectTPL = array( - 'id'=> $object->id - ,'ref'=> $object->ref - ,'date_cre' => $object->getDate('date_cre', 'd/m/Y') - ,'date_maj' => $object->getDate('date_maj', 'd/m/Y H:i') - ,'fk_warehouse' => $object->fk_warehouse - ,'status' => $object->status - ,'entity' => $object->entity - ,'amount' => price( round($object->amount,2) ) - ,'amount_actual'=>price (round($object->amount_actual,2)) - - ); - - $can_validate = !empty($user->rights->stock->validate); - $view_url = dol_buildpath('/product/inventory/card.php', 1); - - $view = array( - 'mode' => $action - ,'url' => dol_buildpath('/product/inventory/card.php', 1) - ,'can_validate' => (int) $user->rights->stock->validate - ,'is_already_validate' => (int) $object->status - ,'token'=>$_SESSION['newtoken'] - ); - - include './tpl/inventory.tpl.php'; + print load_fiche_titre($langs->trans("Inventory")); + + print '
'; + print ''; + print ''; + print ''; + + dol_fiche_head(); + + print ''."\n"; + // print ''; + // LIST_OF_TD_LABEL_FIELDS_EDIT + print '
'.$langs->trans("Label").'
'; + + dol_fiche_end(); + + print '
'; + print '   '; + print '
'; + + print '
'; } + + +// Part to show record +if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) +{ + $res = $object->fetch_optionals($object->id, $extralabels); + + $head = inventory_prepare_head($object); + dol_fiche_head($head, 'order', $langs->trans("CustomerOrder"), -1, 'order'); + + $formconfirm = ''; + + // Confirmation to delete + if ($action == 'delete') { + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('DeleteOrder'), $langs->trans('ConfirmDeleteOrder'), 'confirm_delete', '', 0, 1); + } + + // Confirmation of action xxxx + if ($action == 'xxx') + { + $formquestion=array(); + /* + $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' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockDecrease"), 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse')?GETPOST('idwarehouse'):'ifone', 'idwarehouse', '', 1))); + }*/ + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('XXX'), $text, 'confirm_xxx', $formquestion, 0, 1, 220); + } + + if (! $formconfirm) { + $parameters = array('lineid' => $lineid); + $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if (empty($reshook)) $formconfirm.=$hookmanager->resPrint; + elseif ($reshook > 0) $formconfirm=$hookmanager->resPrint; + } + + // Print form confirm + print $formconfirm; + + + + // Object card + // ------------------------------------------------------------ + + $linkback = '' . $langs->trans("BackToList") . ''; + + + $morehtmlref='
'; + /* + // Ref bis + $morehtmlref.=$form->editfieldkey("RefBis", 'ref_client', $object->ref_client, $object, $user->rights->inventory->creer, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefBis", 'ref_client', $object->ref_client, $object, $user->rights->inventory->creer, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
'.$langs->trans('ThirdParty') . ' : ' . $soc->getNomUrl(1); + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref.='
'.$langs->trans('Project') . ' '; + if ($user->rights->inventory->creer) + { + if ($action != 'classify') + { + $morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref.='
'; + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=''; + $morehtmlref.='
'; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref.=''; + $morehtmlref.=$proj->ref; + $morehtmlref.=''; + } else { + $morehtmlref.=''; + } + } + } + */ + $morehtmlref.='
'; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + + print '
'; + print '
'; + print '
'; + print ''."\n"; + // print ''; + // LIST_OF_TD_LABEL_FIELDS_VIEW + + + // Other attributes + include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php'; + + print '
'.$langs->trans("Label").''.$object->label.'
'; + print '
'; + print '
'; + print '
'; + print '
'; + print ''; + + + + print '
'; + print '
'; + print '
'; + print '
'; + + print '

'; + + dol_fiche_end(); + + + // Buttons for actions + if ($action != 'presend' && $action != 'editline') { + print '
'."\n"; + $parameters=array(); + $reshook=$hookmanager->executeHooks('addMoreActionsButtons',$parameters,$object,$action); // Note that $action and $object may have been modified by hook + if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + + if (empty($reshook)) + { + // Send + print ''."\n"; + + if ($user->rights->inventory->write) + { + print ''."\n"; + } + + if ($user->rights->inventory->delete) + { + print ''."\n"; + } + } + print '
'."\n"; + } + + + // Select mail models is same action as presend + if (GETPOST('modelselected')) { + $action = 'presend'; + } + + if ($action != 'presend') + { + print '
'; + print ''; // ancre + // Documents + $comref = dol_sanitizeFileName($object->ref); + $relativepath = $comref . '/' . $comref . '.pdf'; + $filedir = $conf->inventory->dir_output . '/' . $comref; + $urlsource = $_SERVER["PHP_SELF"] . "?id=" . $object->id; + $genallowed = $user->rights->inventory->creer; + $delallowed = $user->rights->inventory->supprimer; + print $formfile->showdocuments('inventory', $comref, $filedir, $urlsource, $genallowed, $delallowed, $object->modelpdf, 1, 0, 0, 28, 0, '', '', '', $soc->default_lang); + + + // Show links to link elements + $linktoelem = $form->showLinkToObjectBlock($object, null, array('order')); + $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem); + + + print '
'; + + // List of actions on element + include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php'; + $formactions = new FormActions($db); + $somethingshown = $formactions->showactions($object, 'order', $socid); + + print '
'; + } + + + /* + * Action presend + */ + /* + if ($action == 'presend') + { + $object->fetch_projet(); + + $ref = dol_sanitizeFileName($object->ref); + include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php'; + $fileparams = dol_most_recent_file($conf->commande->dir_output . '/' . $ref, preg_quote($ref, '/').'[^\-]+'); + $file = $fileparams['fullname']; + + // Define output language + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && ! empty($_REQUEST['lang_id'])) + $newlang = $_REQUEST['lang_id']; + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) + $newlang = $object->thirdparty->default_lang; + + if (!empty($newlang)) + { + $outputlangs = new Translate('', $conf); + $outputlangs->setDefaultLang($newlang); + $outputlangs->load('commercial'); + } + + // Build document if it not exists + if (! $file || ! is_readable($file)) { + $result = $object->generateDocument(GETPOST('model') ? GETPOST('model') : $object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref); + if ($result <= 0) { + dol_print_error($db, $object->error, $object->errors); + exit(); + } + $fileparams = dol_most_recent_file($conf->commande->dir_output . '/' . $ref, preg_quote($ref, '/').'[^\-]+'); + $file = $fileparams['fullname']; + } + + print '
'; + print '
'; + print '
'; + print load_fiche_titre($langs->trans('SendOrderByMail')); + + dol_fiche_head(''); + + // Cree l'objet formulaire mail + include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php'; + $formmail = new FormMail($db); + $formmail->param['langsmodels']=(empty($newlang)?$langs->defaultlang:$newlang); + $formmail->fromtype = (GETPOST('fromtype')?GETPOST('fromtype'):(!empty($conf->global->MAIN_MAIL_DEFAULT_FROMTYPE)?$conf->global->MAIN_MAIL_DEFAULT_FROMTYPE:'user')); + + if($formmail->fromtype === 'user'){ + $formmail->fromid = $user->id; + + } + $formmail->trackid='ord'.$object->id; + if (! empty($conf->global->MAIN_EMAIL_ADD_TRACK_ID) && ($conf->global->MAIN_EMAIL_ADD_TRACK_ID & 2)) // If bit 2 is set + { + include DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + $formmail->frommail=dolAddEmailTrackId($formmail->frommail, 'ord'.$object->id); + } + $formmail->withfrom = 1; + $liste = array(); + foreach ($object->thirdparty->thirdparty_and_contact_email_array(1) as $key => $value) + $liste [$key] = $value; + $formmail->withto = GETPOST('sendto') ? GETPOST('sendto') : $liste; + $formmail->withtocc = $liste; + $formmail->withtoccc = $conf->global->MAIN_EMAIL_USECCC; + if (empty($object->ref_client)) { + $formmail->withtopic = $outputlangs->trans('SendOrderRef', '__ORDERREF__'); + } else if (! empty($object->ref_client)) { + $formmail->withtopic = $outputlangs->trans('SendOrderRef', '__ORDERREF__ (__REFCLIENT__)'); + } + $formmail->withfile = 2; + $formmail->withbody = 1; + $formmail->withdeliveryreceipt = 1; + $formmail->withcancel = 1; + // Tableau des substitutions + $formmail->setSubstitFromObject($object); + $formmail->substit ['__ORDERREF__'] = $object->ref; + + $custcontact = ''; + $contactarr = array(); + $contactarr = $object->liste_contact(- 1, 'external'); + + if (is_array($contactarr) && count($contactarr) > 0) + { + foreach ($contactarr as $contact) + { + if ($contact['libelle'] == $langs->trans('TypeContact_commande_external_CUSTOMER')) { // TODO Use code and not label + $contactstatic = new Contact($db); + $contactstatic->fetch($contact ['id']); + $custcontact = $contactstatic->getFullName($langs, 1); + } + } + + if (! empty($custcontact)) { + $formmail->substit['__CONTACTCIVNAME__'] = $custcontact; + } + } + + // Tableau des parametres complementaires + $formmail->param['action'] = 'send'; + $formmail->param['models'] = 'order_send'; + $formmail->param['models_id']=GETPOST('modelmailselected','int'); + $formmail->param['orderid'] = $object->id; + $formmail->param['returnurl'] = $_SERVER["PHP_SELF"] . '?id=' . $object->id; + + // Init list of files + if (GETPOST("mode") == 'init') { + $formmail->clear_attached_files(); + $formmail->add_attached_files($file, basename($file), dol_mimetype($file)); + } + + // Show form + print $formmail->get_form(); + + dol_fiche_end(); + }*/ +} + + // End of page llxFooter(); $db->close(); - - - -function card_line(&$inventory, &$lines, $mode) -{ - global $db,$langs,$user,$conf; - $inventory->amount_actual = 0; - - $TCacheEntrepot = array(); - - foreach ($inventory->Inventorydet as $k => $Inventorydet) - { - $product = & $Inventorydet->product; - $stock = $Inventorydet->qty_stock; - - $pmp = $Inventorydet->pmp; - $pmp_actual = $pmp * $stock; - $inventory->amount_actual+=$pmp_actual; - - $last_pa = $Inventorydet->pa; - $current_pa = $Inventorydet->current_pa; - - $e = new Entrepot($db); - if(!empty($TCacheEntrepot[$Inventorydet->fk_warehouse])) $e = $TCacheEntrepot[$Inventorydet->fk_warehouse]; - elseif($e->fetch($Inventorydet->fk_warehouse) > 0) $TCacheEntrepot[$e->id] = $e; - - $qtytoadd = GETPOST('qty_to_add', 'array'); - $qty = (float) $qtytoadd[$k]; - - $lines[]=array( - 'produit' => $product->getNomUrl(1).' - '.$product->label, - 'entrepot'=>$e->getNomUrl(1), - 'barcode' => $product->barcode, - 'qty' =>($mode == 'edit' ? ' '.img_picto($langs->trans('Add'), 'edit_add').'' : '' ), - 'qty_view' => ($Inventorydet->qty_view ? $Inventorydet->qty_view : 0), - 'qty_stock' => $stock, - 'qty_regulated' => ($Inventorydet->qty_regulated ? $Inventorydet->qty_regulated : 0), - 'action' => ($user->rights->stock->write && $mode=='edit' ? ''.img_picto($langs->trans('inventoryDeleteLine'), 'delete').'' : ''), - 'pmp_stock'=>round($pmp_actual,2), - 'pmp_actual'=> round($pmp * $Inventorydet->qty_view,2), - 'pmp_new'=>(!empty($user->rights->stock->changePMP) && $mode == 'edit' ? ' '.img_picto($langs->trans('Save'), 'bt-save.png@inventory').'' : price($Inventorydet->new_pmp)), - 'pa_stock'=>round($last_pa * $stock,2), - 'pa_actual'=>round($last_pa * $Inventorydet->qty_view,2), - 'current_pa_stock'=>round($current_pa * $stock,2), - 'current_pa_actual'=>round($current_pa * $Inventorydet->qty_view,2), - 'k'=>$k, - 'id'=>$Inventorydet->id - ); - } - -} - - -/* -function _exportCSV(&$inventory) -{ - global $conf; - - header('Content-Type: application/octet-stream'); - header('Content-disposition: attachment; filename=inventory-'. $inventory->getId().'-'.date('Ymd-His').'.csv'); - header('Pragma: no-cache'); - header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0'); - header('Expires: 0'); - - echo 'Ref;Label;barcode;qty theorique;PMP;dernier PA;'; - if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) echo 'PA courant;'; - echo 'qty réelle;PMP;dernier PA;'; - if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) echo 'PA courant;'; - echo 'qty regulée;'."\r\n"; - - foreach ($inventory->Inventorydet as $k => $Inventorydet) - { - $product = & $Inventorydet->product; - $stock = $Inventorydet->qty_stock; - - $pmp = $Inventorydet->pmp; - $pmp_actual = $pmp * $stock; - $inventory->amount_actual+=$pmp_actual; - - $last_pa = $Inventorydet->pa; - $current_pa = $Inventorydet->current_pa; - - if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) { - $row=array( - 'produit' => $product->ref - ,'label'=>$product->label - ,'barcode' => $product->barcode - ,'qty_stock' => $stock - ,'pmp_stock'=>round($pmp_actual,2) - ,'pa_stock'=>round($last_pa * $stock,2) - ,'current_pa_stock'=>round($current_pa * $stock,2) - ,'qty_view' => $Inventorydet->qty_view ? $Inventorydet->qty_view : 0 - ,'pmp_actual'=>round($pmp * $Inventorydet->qty_view,2) - ,'pa_actual'=>round($last_pa * $Inventorydet->qty_view,2) - ,'current_pa_actual'=>round($current_pa * $Inventorydet->qty_view,2) - ,'qty_regulated' => $Inventorydet->qty_regulated ? $Inventorydet->qty_regulated : 0 - - ); - - } - else{ - $row=array( - 'produit' => $product->ref - ,'label'=>$product->label - ,'barcode' => $product->barcode - ,'qty_stock' => $stock - ,'pmp_stock'=>round($pmp_actual,2) - ,'pa_stock'=>round($last_pa * $stock,2) - ,'qty_view' => $Inventorydet->qty_view ? $Inventorydet->qty_view : 0 - ,'pmp_actual'=>round($pmp * $Inventorydet->qty_view,2) - ,'pa_actual'=>round($last_pa * $Inventorydet->qty_view,2) - - ,'qty_regulated' => $Inventorydet->qty_regulated ? $Inventorydet->qty_regulated : 0 - - ); - - } - - - echo '"'.implode('";"', $row).'"'."\r\n"; - - } - - exit; -} -*/ - -function _footerList($view,$total_pmp,$total_pmp_actual,$total_pa,$total_pa_actual, $total_current_pa,$total_current_pa_actual) -{ - global $conf,$user,$langs; - - if ($view['can_validate'] == 1) { ?> - -   - barcode->enabled)) { ?> -   - - - - global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ - echo ''.price($total_current_pa).''; - } - ?> -   - - rights->stock->changePMP)) { - echo ' '; - } - ?> - - global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ - echo ''.price($total_current_pa_actual).''; - } - ?> - -   - -   - - - - - trans('Product'); ?> - trans('Warehouse'); ?> - barcode->enabled)) { ?> - trans('Barcode'); ?> - - - trans('TheoricalQty'); ?> - global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ - echo ''.$langs->trans('TheoricalValue').''; - } - else { - echo ''.$langs->trans('TheoricalValue').''; - } - - ?> - - - trans('RealQty'); ?> - - - global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) $colspan++; - if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) $colspan++; - - echo ''.$langs->trans('RealValue').''; - - ?> - - trans('RegulatedQty'); ?> - - - # - - - - - -   - trans('PMP'); ?> - trans('LastPA'); ?> - global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ - echo ''.$langs->trans('CurrentPA').''; - } - - ?> -   - trans('PMP'); ?> - rights->stock->changePMP)) { - echo ''.$langs->trans('ColumnNewPMP').''; - } - ?> - trans('LastPA'); ?> - global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ - echo ''.$langs->trans('CurrentPA').''; - } - - ?> -   - -   - - - +/* Copyright (C) 2007-2017 Laurent Destailleur + * Copyright (C) 2014-2016 Juanjo Menent + * Copyright (C) 2015 Florian Henry + * Copyright (C) 2015 Raphaël Doursenaud + * Copyright (C) ---Put here your own copyright and developer email--- * * 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 @@ -16,698 +20,271 @@ */ /** - * \file htdocs/inventory/class/product.class.php - * \ingroup product - * \brief File of class to manage predefined products stock + * \file product/inventory/class/inventory.class.php + * \ingroup inventory + * \brief This file is a CRUD class file for Inventory (Create/Read/Update/Delete) */ - -require_once DOL_DOCUMENT_ROOT.'/core/class/coreobject.class.php'; -require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; + +// Put here all includes required by your class file +require_once DOL_DOCUMENT_ROOT . '/core/class/commonobject.class.php'; +//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; +//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; /** - * Class to manage inventories + * Class for Inventory */ -class Inventory extends CoreObject +class Inventory extends CommonObject { - public $element='inventory'; - public $table_element='inventory'; - public $fk_element='fk_inventory'; - protected $childtables=array('inventorydet'); // To test if we can delete object - protected $isnolinkedbythird = 1; // No field fk_soc - protected $ismultientitymanaged = 1; // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe - /** - * Warehouse Id - * @var int + * @var string ID to identify managed object */ - public $fk_warehouse; + public $element = 'inventory'; /** - * Entity Id - * @var int + * @var string Name of table without prefix where object is stored */ + public $table_element = 'inventory'; + + /** + * @var array Does this field is linked to a thirdparty ? + */ + protected $isnolinkedbythird = 1; + /** + * @var array Does inventory support multicompany module ? 0=No test on entity, 1=Test with field entity, 2=Test with link by societe + */ + protected $ismultientitymanaged = 1; + /** + * @var string String with name of icon for inventory + */ + public $picto = 'inventory'; + + + /** + * 'type' if the field format, 'label' the translation key, 'enabled' is a condition when the filed must be managed, + * 'visible' says if field is visible in list (-1 means not shown by default but can be aded into list to be viewed) + * 'notnull' if not null in database + * 'index' if we want an index in database + * 'position' is the sort order of field + * 'searchall' is 1 if we want to search in this field when making a search from the quick search button + * 'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8). + * 'comment' is not used. You can store here any text of your choice. + */ + + // BEGIN MODULEBUILDER PROPERTIES + /** + * @var array Array with all fields and their property + */ + public $fields=array( + 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'visible'=>-1, 'enabled'=>1, 'position'=>1, 'notnull'=>1, 'index'=>1, 'comment'=>'Id',), + 'ref' => array('type'=>'varchar(64)', 'label'=>'Ref', 'visible'=>1, 'enabled'=>1, 'position'=>10, 'notnull'=>1, 'index'=>1, 'searchall'=>1, 'comment'=>'Reference of object',), + 'entity' => array('type'=>'integer', 'label'=>'Entity', 'visible'=>0, 'enabled'=>1, 'position'=>20, 'notnull'=>1, 'index'=>1,), + 'fk_warehouse' => array('type'=>'integer', 'label'=>'', 'visible'=>1, 'enabled'=>1, 'index'=>1,), + 'date_inventory' => array('type'=>'date', 'label'=>'', 'visible'=>1, 'enabled'=>1,), + 'title' => array('type'=>'varchar(255)', 'label'=>'', 'visible'=>1, 'enabled'=>1,), + 'status' => array('type'=>'integer', 'label'=>'Status', 'visible'=>1, 'enabled'=>1, 'position'=>1000, 'index'=>1,), + 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'visible'=>-1, 'enabled'=>1, 'position'=>500,), + 'date_validation' => array('type'=>'datetime', 'label'=>'DateValidation', 'visible'=>-1, 'enabled'=>1, 'position'=>500,), + 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'visible'=>-1, 'enabled'=>1, 'position'=>500, 'notnull'=>1,), + 'fk_user_creat' => array('type'=>'integer', 'label'=>'UserAuthor', 'visible'=>-1, 'enabled'=>1, 'position'=>500,), + 'fk_user_modif' => array('type'=>'integer', 'label'=>'UserModif', 'visible'=>-1, 'enabled'=>1, 'position'=>500,), + 'fk_user_valid' => array('type'=>'integer', 'label'=>'UserValid', 'visible'=>-1, 'enabled'=>1, 'position'=>500,), + 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'visible'=>-1, 'enabled'=>1, 'position'=>1000, 'index'=>1,), + ); + + public $rowid; + public $ref; public $entity; - - /** - * Status - * @var int - */ - public $status; - /** - * Inventory Date - * @var date - */ + public $fk_warehouse; public $date_inventory; - /** - * Inventory Title - * @var string - */ public $title; + public $status; + public $date_creation; + public $date_validation; + public $tms; + public $fk_user_creat; + public $fk_user_modif; + public $fk_user_valid; + public $import_key; + // END MODULEBUILDER PROPERTIES - /** - * Attribute object linked with database - * @var array - */ - protected $fields=array( - 'fk_warehouse'=>array('type'=>'integer','index'=>true) - ,'ref'=>array('type'=>'string','index'=>true) - ,'entity'=>array('type'=>'integer','index'=>true) - ,'status'=>array('type'=>'integer','index'=>true) - ,'date_inventory'=>array('type'=>'date') - ,'title'=>array('type'=>'string') - ); - /** - * Constructor - * - * @param DoliDB $db Database handler - */ - public function __construct(DoliDB &$db) + + // If this object has a subtable with lines + + /** + * @var int Name of subtable line + */ + //public $table_element_line = 'inventorydet'; + /** + * @var int Field with ID of parent key if this field has a parent + */ + //public $fk_element = 'fk_inventory'; + /** + * @var int Name of subtable class that manage subtable lines + */ + //public $class_element_line = 'Inventoryline'; + /** + * @var array Array of child tables (child tables to delete before deleting a record) + */ + //protected $childtables=array('inventorydet'); + /** + * @var InventoryLine[] Array of subtable lines + */ + //public $lines = array(); + + + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) { - global $conf; - - parent::__construct($db); - parent::init(); - - $this->status = 0; - $this->entity = $conf->entity; - $this->errors = array(); - $this->amount = 0; + $this->db = $db; } - /** - * Function to sort children object - */ - public function sortDet() + + /** + * Return a link to the object card (with optionaly the picto) + * + * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) + * @param string $option On what the link point to + * @param int $notooltip 1=Disable tooltip + * @param string $morecss Add more css on link + * @return string String with URL + */ + function getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='') { - if(!empty($this->Inventorydet)) usort($this->Inventorydet, array('Inventory', 'customSort')); - } + global $db, $conf, $langs; + global $dolibarr_main_authentication, $dolibarr_main_demo; + global $menumanager; - /** - * Get object and children from database - * - * @param int $id Id of object to load - * @param bool $loadChild used to load children from database - * @return int >0 if OK, <0 if KO, 0 if not found - */ - public function fetch($id, $loadChild = true) - { - if(!$loadChild) $this->withChild = false; - - $res = parent::fetch($id, $loadChild); + if (! empty($conf->dol_no_mouse_hover)) $notooltip=1; // Force disable tooltips - if ($res > 0) - { - $this->sortDet(); - $this->amount = 0; - if(!empty($this->Inventorydet )) - { - foreach($this->Inventorydet as &$det) - { - $this->amount += $det->qty_view * $det->pmp; - } - } - } - - return $res; - } + $result = ''; + $companylink = ''; - /** - * Custom function call by usort - * - * @param Inventorydet $objA first Inventorydet object - * @param Inventorydet $objB second Inventorydet object - * @return int - */ - private function customSort(&$objA, &$objB) - { - $r = strcmp(strtoupper(trim($objA->product->ref)), strtoupper(trim($objB->product->ref))); - - if ($r < 0) $r = -1; - elseif ($r > 0) $r = 1; - else $r = 0; - - return $r; - } + $label = '' . $langs->trans("Inventory") . ''; + $label.= '
'; + $label.= '' . $langs->trans('Ref') . ': ' . $this->ref; - /** - * @param User $user user object - * @return int - */ - public function changePMP(User &$user) - { - $error = 0; - $this->db->begin(); + $url = $url = dol_buildpath('/inventory/m_card.php',1).'?id='.$this->id; - if(!empty($this->Inventorydet)) - { - foreach ($this->Inventorydet as $k => &$Inventorydet) - { - if($Inventorydet->new_pmp>0) - { - $Inventorydet->pmp = $Inventorydet->new_pmp; - $Inventorydet->new_pmp = 0; - - $res = $this->db->query('UPDATE '.MAIN_DB_PREFIX.'product as p SET pmp = '.$Inventorydet->pmp.' WHERE rowid = '.$Inventorydet->fk_product ); - if (!$res) - { - $error++; - $this->error = $this->db->lasterror(); - $this->errors[] = $this->db->lasterror(); - } - } - } - } - - $res = parent::update($user); - if (!$res) + $linkclose=''; + if (empty($notooltip)) { - $error++; - $this->error = $this->db->lasterror(); - $this->errors[] = $this->db->lasterror(); - } - - - if (!$error) - { - $this->db->commit(); - return 1; - } - else - { - $this->db->rollback(); - return -1; - } - } - - /** - * Function to update object or create or delete if needed - * - * @param User $user user object - * @return < 0 if ko, > 0 if ok - */ - public function update(User &$user) - { - $error = 0; - $this->db->begin(); - - // if we valid the inventory we save the stock at the same time - if ($this->status) - { - $res = $this->regulate(); - if ($res < 0) + if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) { - $error++; - $this->error = $this->db->lasterror(); - $this->errors[] = $this->db->lasterror(); + $label=$langs->trans("ShowInventory"); + $linkclose.=' alt="'.dol_escape_htmltag($label, 1).'"'; } + $linkclose.=' title="'.dol_escape_htmltag($label, 1).'"'; + $linkclose.=' class="classfortooltip'.($morecss?' '.$morecss:'').'"'; + } + else $linkclose = ($morecss?' class="'.$morecss.'"':''); + + $linkstart = ''; + $linkend=''; + + if ($withpicto) + { + $result.=($linkstart.img_object(($notooltip?'':$label), 'label', ($notooltip?'':'class="classfortooltip"')).$linkend); + if ($withpicto != 2) $result.=' '; } - - $res = parent::update($user); - if (!$res) - { - $error++; - $this->error = $this->db->lasterror(); - $this->errors[] = $this->db->lasterror(); - } - - if (!$error) - { - $this->db->commit(); - return $this->id; - } - else - { - $this->db->rollback(); - return -1; - } + $result.= $linkstart . $this->ref . $linkend; + return $result; } - /** - * Function to update current object - * - * @param array $Tab Array of values - * @return int - */ - public function setValues(&$Tab) + /** + * Retourne le libelle du status d'un user (actif, inactif) + * + * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto + * @return string Label of status + */ + function getLibStatut($mode=0) + { + return $this->LibStatut($this->status,$mode); + } + + /** + * Return the status + * + * @param int $status Id status + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 5=Long label + Picto + * @return string Label of status + */ + static function LibStatut($status,$mode=0) { global $langs; - - if (isset($Tab['qty_to_add'])) + + if ($mode == 0) { - foreach ($Tab['qty_to_add'] as $k => $qty) - { - $qty = (float) price2num($qty); - - if ($qty < 0) - { - $this->errors[] = $langs->trans('inventoryErrorQtyAdd'); - return -1; - } - - $product = new Product($this->db); - $product->fetch($this->Inventorydet[$k]->fk_product); - - $this->Inventorydet[$k]->pmp = $product->pmp; - $this->Inventorydet[$k]->qty_view += $qty; - } + $prefix=''; + if ($status == 1) return $langs->trans('Enabled'); + if ($status == 0) return $langs->trans('Disabled'); + } + if ($mode == 1) + { + if ($status == 1) return $langs->trans('Enabled'); + if ($status == 0) return $langs->trans('Disabled'); + } + if ($mode == 2) + { + if ($status == 1) return img_picto($langs->trans('Enabled'),'statut4').' '.$langs->trans('Enabled'); + if ($status == 0) return img_picto($langs->trans('Disabled'),'statut5').' '.$langs->trans('Disabled'); + } + if ($mode == 3) + { + if ($status == 1) return img_picto($langs->trans('Enabled'),'statut4'); + if ($status == 0) return img_picto($langs->trans('Disabled'),'statut5'); + } + if ($mode == 4) + { + if ($status == 1) return img_picto($langs->trans('Enabled'),'statut4').' '.$langs->trans('Enabled'); + if ($status == 0) return img_picto($langs->trans('Disabled'),'statut5').' '.$langs->trans('Disabled'); + } + if ($mode == 5) + { + if ($status == 1) return $langs->trans('Enabled').' '.img_picto($langs->trans('Enabled'),'statut4'); + if ($status == 0) return $langs->trans('Disabled').' '.img_picto($langs->trans('Disabled'),'statut5'); + } + if ($mode == 6) + { + if ($status == 1) return $langs->trans('Enabled').' '.img_picto($langs->trans('Enabled'),'statut4'); + if ($status == 0) return $langs->trans('Disabled').' '.img_picto($langs->trans('Disabled'),'statut5'); } - - return parent::setValues($Tab); } - /** - * Function to delete all Inventorydet - * - * @param User $user user object - * @return < 0 if ko, > 0 if ok - */ - public function deleteAllLine(User &$user) - { - foreach($this->Inventorydet as &$det) - { - $det->to_delete = true; - } - - $res = $this->update($user); - if ($res > 0) $this->Inventorydet = array(); - else return -1; - } - - /** - * Function to add Inventorydet - * - * @param int $fk_product fk_product of Inventorydet - * @param int $fk_warehouse fk_warehouse target - * @return bool - */ - public function addProduct($fk_product, $fk_warehouse=0) - { - $k = $this->addChild('Inventorydet'); - $det = &$this->Inventorydet[$k]; - - $det->fk_inventory = $this->id; - $det->fk_product = $fk_product; - $det->fk_warehouse = empty($fk_warehouse) ? $this->fk_warehouse : $fk_warehouse; - - $det->load_product(); - - $date = $this->getDate('date_inventory', 'Y-m-d'); - if(empty($date)) $date = $this->getDate('datec', 'Y-m-d'); - $det->setStockDate($date, $fk_warehouse); - - return true; - } - - /** - * Duplication method product to add datem - * Adjust stock in a warehouse for product - * - * @param int $fk_product id of product - * @param int $fk_warehouse id of warehouse - * @param double $nbpiece nb of units - * @param int $movement 0 = add, 1 = remove - * @param string $label Label of stock movement - * @param double $price Unit price HT of product, used to calculate average weighted price (PMP in french). If 0, average weighted price is not changed. - * @param string $inventorycode Inventory code - * @return int <0 if KO, >0 if OK - */ - public function correctStock($fk_product, $fk_warehouse, $nbpiece, $movement, $label='', $price=0, $inventorycode='') + /** + * Initialise object with example values + * Id must be 0 if object instance is a specimen + * + * @return void + */ + public function initAsSpecimen() { - global $conf, $user; - - if ($fk_warehouse) - { - $this->db->begin(); - - require_once DOL_DOCUMENT_ROOT .'/product/stock/class/mouvementstock.class.php'; - - $op[0] = "+".trim($nbpiece); - $op[1] = "-".trim($nbpiece); - - $datem = empty($conf->global->INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT) ? dol_now() : $this->date_inventory; - - $movementstock=new MouvementStock($this->db); - $movementstock->origin = new stdClass(); - $movementstock->origin->element = 'inventory'; - $movementstock->origin->id = $this->id; - $result=$movementstock->_create($user,$fk_product,$fk_warehouse,$op[$movement],$movement,$price,$label,$inventorycode, $datem); - - if ($result >= 0) - { - $this->db->commit(); - return 1; - } - else - { - $this->error=$movementstock->error; - $this->errors=$movementstock->errors; - - $this->db->rollback(); - return -1; - } - } + $this->initAsSpecimenCommon(); } - /** - * Function to regulate stock - * - * @return int - */ - public function regulate() - { - global $langs,$conf; - - if($conf->global->INVENTORY_DISABLE_VIRTUAL) - { - $pdt_virtuel = false; - // Test if virtual product is enabled - if($conf->global->PRODUIT_SOUSPRODUITS) - { - $pdt_virtuel = true; - $conf->global->PRODUIT_SOUSPRODUITS = 0; - } - } - - foreach ($this->Inventorydet as $k => $Inventorydet) - { - $product = new Product($this->db); - $product->fetch($Inventorydet->fk_product); - - if ($Inventorydet->qty_view != $Inventorydet->qty_stock) - { - $Inventorydet->qty_regulated = $Inventorydet->qty_view - $Inventorydet->qty_stock; - $nbpiece = abs($Inventorydet->qty_regulated); - $movement = (int) ($Inventorydet->qty_view < $Inventorydet->qty_stock); // 0 = add ; 1 = remove - - //$href = dol_buildpath('/inventory/inventory.php?id='.$this->id.'&action=view', 1); - - $res = $this->correctStock($product->id, $Inventorydet->fk_warehouse, $nbpiece, $movement, $langs->trans('inventoryMvtStock')); - if ($res < 0) return -1; - } - } - - if($conf->global->INVENTORY_DISABLE_VIRTUAL) - { - // Test if virtual product was enabled before regulate - if($pdt_virtuel) $conf->global->PRODUIT_SOUSPRODUITS = 1; - } - - return 1; - } - - /** - * Get the title - * @return string - */ - public function getTitle() - { - global $langs; - - return !empty($this->title) ? $this->title : $langs->trans('inventoryTitle').' '.$this->id; - } - - - /** - * Return clicable link of object (with eventually picto) - * - * @param int $withpicto Add picto into link - * @return string - */ - public function getNomUrl($withpicto = 1) - { - return ''.($withpicto ? img_picto('','object_list.png','',0).' ' : '').$this->getTitle().''; - } - - /** - * Function to add products by default from warehouse and children - * - * @param int $fk_warehouse id of warehouse - * @param int $fk_category id of category - * @param int $fk_supplier id of supplier - * @param int $only_prods_in_stock only product with stock - * - * @return int - */ - public function addProductsFor($fk_warehouse,$fk_category=0,$fk_supplier=0,$only_prods_in_stock=0) - { - $warehouse = new Entrepot($this->db); - $warehouse->fetch($fk_warehouse); - $TChildWarehouses = array($fk_warehouse); - $warehouse->get_children_warehouses($fk_warehouse, $TChildWarehouses); - - $sql = 'SELECT ps.fk_product, ps.fk_entrepot'; - $sql.= ' FROM '.MAIN_DB_PREFIX.'product_stock ps'; - $sql.= ' INNER JOIN '.MAIN_DB_PREFIX.'product p ON (p.rowid = ps.fk_product)'; - $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_product cp ON (cp.fk_product = p.rowid)'; - $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_fournisseur_price pfp ON (pfp.fk_product = p.rowid)'; - $sql.= ' WHERE ps.fk_entrepot IN ('.implode(', ', $TChildWarehouses).')'; - - if ($fk_category>0) $sql.= ' AND cp.fk_categorie='.$fk_category; - if ($fk_supplier>0) $sql.= ' AND pfp.fk_soc = '.$fk_supplier; - if (!empty($only_prods_in_stock)) $sql.= ' AND ps.reel > 0'; - - $sql.=' GROUP BY ps.fk_product, ps.fk_entrepot ORDER BY p.ref ASC,p.label ASC'; - - $res = $this->db->query($sql); - if($res) - { - while($obj = $this->db->fetch_object($res)) - { - $this->addProduct($obj->fk_product, $obj->fk_entrepot); - } - - return 1; - } - else - { - $this->error = $this->db->lasterror(); - $this->errors[] = $this->db->lasterror(); - return -1; - } - } - - /** - * Return clicable link of inventory object - * - * @param int $id id of inventory - * @param int $withpicto Add picto into link - * @return string - */ - static function getLink($id, $withpicto=1) - { - global $langs,$db; - - $inventory = new Inventory($db); - if($inventory->fetch($id, false) > 0) return $inventory->getNomUrl($withpicto); - else return $langs->trans('InventoryUnableToFetchObject'); - } - - /** - * Function to get the sql select of inventory - * - * @param string $type 'All' to get all data - * @return string - */ - static function getSQL($type) - { - global $conf; - - $sql = ''; - if($type == 'All') - { - $sql = 'SELECT i.rowid,i.title, e.label, i.date_inventory, i.fk_warehouse, i.datec, i.tms, i.status'; - $sql.= ' FROM '.MAIN_DB_PREFIX.'inventory i'; - $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'entrepot e ON (e.rowid = i.fk_warehouse)'; - $sql.= ' WHERE i.entity IN ('.getEntity('inventory').')'; - } - - return $sql; - } } -class Inventorydet extends CoreObject +/** + * Class InventoryObjectLine + */ +class InventoryObjectLine { - public $element='inventorydet'; - public $table_element='inventorydet'; - protected $isnolinkedbythird = 1; // No field fk_soc - protected $ismultientitymanaged = 0; // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe - - public $fk_inventory; - public $fk_warehouse; - public $fk_product; - public $entity; - public $qty_view; - public $qty_stock; - public $qty_regulated; - public $pmp; - public $pa; - public $new_pmp; - - protected $fields=array( - 'fk_inventory'=>array('type'=>'int') - ,'fk_warehouse'=>array('type'=>'int') - ,'fk_product'=>array('type'=>'int') - ,'entity'=>array('type'=>'int') - ,'qty_view'=>array('type'=>'float') - ,'qty_stock'=>array('type'=>'float') - ,'qty_regulated'=>array('type'=>'float') - ,'pmp'=>array('type'=>'float') - ,'pa'=>array('type'=>'float') - ,'new_pmp'=>array('type'=>'float') - ); - - /** - * Constructor - * - * @param DoliDB $db Database handler - */ - function __construct(DoliDB &$db) - { - global $conf; - - parent::__construct($db); - parent::init(); - - $this->entity = $conf->entity; - $this->errors = array(); - - $this->product = null; - $this->current_pa = 0; - } - - /** - * Get object and children from database - * - * @param int $id id of inventorydet object - * @param bool $loadChild load children - * @return int - */ - function fetch($id, $loadChild = true) - { - $res = parent::fetch($id); - $this->load_product(); - $this->fetch_current_pa(); - - return $res; - } - - /** - * Function to get the unit buy price - * - * @return bool - */ - function fetch_current_pa() - { - global $db,$conf; - - if(empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) return false; - - if($this->pa > 0) - { - $this->current_pa = $this->pa; - } - else - { - dol_include_once('/fourn/class/fournisseur.product.class.php'); - $p= new ProductFournisseur($db); - $p->find_min_price_product_fournisseur($this->fk_product); - - if($p->fourn_qty>0) $this->current_pa = $p->fourn_price / $p->fourn_qty; - } - - return true; - } - - /** - * Function to set pa attribute from date en fk_warehouse - * - * @param date $date date value - * @param int $fk_warehouse fk_warehouse target - */ - function setStockDate($date, $fk_warehouse) - { - list($pmp, $stock) = $this->getPmpStockFromDate($date, $fk_warehouse); - - $this->qty_stock = $stock; - $this->pmp = $pmp; - - $last_pa = 0; - $sql = 'SELECT price FROM '.MAIN_DB_PREFIX.'stock_mouvement'; - $sql.= ' WHERE fk_entrepot = '.$fk_warehouse; - $sql.= ' AND fk_product = '.$this->fk_product; - $sql.= ' AND (origintype=\'order_supplier\' || origintype=\'invoice_supplier\')'; - $sql.= ' AND price > 0'; - $sql.= ' AND datem <= \''.$date.' 23:59:59\''; - $sql.= ' ORDER BY datem DESC LIMIT 1'; - - $res = $this->db->query($sql); - if($res && $obj = $this->db->fetch_object($res)) - { - $last_pa = $obj->price; - } - - $this->pa = $last_pa; - } - - - /** - * Get the last pmp and last stock from date and warehouse - * - * @param date $date date to check - * @param int $fk_warehouse id of warehouse - * @return array - */ - function getPmpStockFromDate($date, $fk_warehouse) - { - $res = $this->product->load_stock(); - - if($res>0) - { - $stock = isset($this->product->stock_warehouse[$fk_warehouse]->real) ? $this->product->stock_warehouse[$fk_warehouse]->real : 0; - $pmp = $this->product->pmp; - } - - //All Stock mouvement between now and inventory date - $sql = 'SELECT value, price'; - $sql.= ' FROM '.MAIN_DB_PREFIX.'stock_mouvement'; - $sql.= ' WHERE fk_product = '.$this->product->id; - $sql.= ' AND fk_entrepot = '.$fk_warehouse; - $sql.= ' AND datem > \''.date('Y-m-d 23:59:59', strtotime($date)).'\''; - $sql.= ' ORDER BY datem DESC'; - - $res = $this->db->query($sql); - - $laststock = $stock; - $lastpmp = $pmp; - - if($res) - { - while($mouvement = $this->db->fetch_object($res)) - { - $price = ($mouvement->price > 0 && $mouvement->value > 0) ? $mouvement->price : $lastpmp; - $stock_value = $laststock * $lastpmp; - $laststock -= $mouvement->value; - $last_stock_value = $stock_value - ($mouvement->value * $price); - $lastpmp = ($laststock != 0) ? $last_stock_value / $laststock : $lastpmp; - } - } - - return array($lastpmp, $laststock); - } - - /** - * Fetch the product linked with the line - * @return void - */ - function load_product() - { - global $db; - - if($this->fk_product>0) - { - $this->product = new Product($db); - $this->product->fetch($this->fk_product); - } - } + /** + * @var int ID + */ + public $id; + /** + * @var mixed Sample line property 1 + */ + public $prop1; + /** + * @var mixed Sample line property 2 + */ + public $prop2; } diff --git a/htdocs/product/inventory/list.php b/htdocs/product/inventory/list.php index c8d570a6fd7..2a8d9861e5a 100644 --- a/htdocs/product/inventory/list.php +++ b/htdocs/product/inventory/list.php @@ -1,5 +1,6 @@ +/* Copyright (C) 2007-2017 Laurent Destailleur + * Copyright (C) ---Put here your own copyright and developer email--- * * 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 @@ -16,119 +17,623 @@ */ /** - * \file htdocs/inventory/list.php - * \ingroup product - * \brief File of class to manage inventory + * \file product/inventory/list.php + * \ingroup inventory + * \brief List page for monmodule */ - -require_once '../../main.inc.php'; -require_once DOL_DOCUMENT_ROOT.'/product/inventory/listview.class.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; -include_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; -require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; -require_once DOL_DOCUMENT_ROOT.'/product/inventory/class/inventory.class.php'; -require_once DOL_DOCUMENT_ROOT.'/product/inventory/lib/inventory.lib.php'; +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB','1'); +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1'); +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION','1'); // Do not check anti CSRF attack test +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION','1'); // Do not check anti CSRF attack test +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK','1'); // Do not check anti CSRF attack test +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK','1'); // Do not check style html tag into posted data +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL','1'); // Do not check anti POST attack test +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN",'1'); // If this page is public (can be called outside logged session) -$langs->load("stock"); -$langs->load("inventory"); +// Load Dolibarr environment +$res=0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (! $res && ! empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res=@include($_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"); +// Try main.inc.php into web root detected using web root caluclated from SCRIPT_FILENAME +$tmp=empty($_SERVER['SCRIPT_FILENAME'])?'':$_SERVER['SCRIPT_FILENAME'];$tmp2=realpath(__FILE__); $i=strlen($tmp)-1; $j=strlen($tmp2)-1; +while($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i]==$tmp2[$j]) { $i--; $j--; } +if (! $res && $i > 0 && file_exists(substr($tmp, 0, ($i+1))."/main.inc.php")) $res=@include(substr($tmp, 0, ($i+1))."/main.inc.php"); +if (! $res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php")) $res=@include(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php"); +// Try main.inc.php using relative path +if (! $res && file_exists("../main.inc.php")) $res=@include("../main.inc.php"); +if (! $res && file_exists("../../main.inc.php")) $res=@include("../../main.inc.php"); +if (! $res && file_exists("../../../main.inc.php")) $res=@include("../../../main.inc.php"); +if (! $res) die("Include of main fails"); + +require_once(DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'); +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +dol_include_once('/inventory/class/inventory.class.php'); + +// Load traductions files requiredby by page +$langs->loadLangs(array("inventory","other")); + +$action = GETPOST('action','alpha'); +$massaction = GETPOST('massaction','alpha'); +$show_files = GETPOST('show_files','int'); +$confirm = GETPOST('confirm','alpha'); +$cancel = GETPOST('cancel', 'alpha'); +$toselect = GETPOST('toselect', 'array'); +$contextpage= GETPOST('contextpage','aZ')?GETPOST('contextpage','aZ'):'inventorylist'; // To manage different context of search + +$id = GETPOST('id','int'); +$backtopage = GETPOST('backtopage'); +$optioncss = GETPOST('optioncss','alpha'); + +// Load variable for pagination $limit = GETPOST('limit','int')?GETPOST('limit','int'):$conf->liste_limit; -$sortfield = GETPOST("sortfield",'alpha'); -$sortorder = GETPOST("sortorder",'alpha'); -$page = (GETPOST("page",'int')?GETPOST("page", 'int'):0); +$sortfield = GETPOST('sortfield','alpha'); +$sortorder = GETPOST('sortorder','alpha'); +$page = GETPOST('page','int'); if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 $offset = $limit * $page; $pageprev = $page - 1; $pagenext = $page + 1; -if (! $sortfield) $sortfield="i.title"; + +// Initialize technical objects +$object=new Inventory($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction=$conf->inventory->dir_output . '/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('inventorylist')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extralabels = $extrafields->fetch_name_optionals_label('inventory'); +$search_array_options=$extrafields->getOptionalsFromPost($extralabels,'','search_'); + +// Default sort order (if not yet defined by previous GETPOST) +if (! $sortfield) $sortfield="t.".key($object->fields); // Set here default search field. By default 1st field in definition. if (! $sortorder) $sortorder="ASC"; -if (empty($user->rights->stock->lire)) accessforbidden(); - - -/* - * Actions - */ - -// None - - -/* - * View - */ - -llxHeader('',$langs->trans('inventoryListTitle'),'',''); - -echo '
'; - -$inventory = new Inventory($db); -$list = new ListView($db, 'listInventory'); - -$THide = array('label','title'); - -echo $list->render(Inventory::getSQL('All'), array( - 'param' => array( - 'limit' => $limit, - 'offset' => $offset, - 'sortfield' => $sortfield, - 'sortorder'=> $sortorder, - 'page'=>$page - ), - 'limit' => array( - 'nbLine' => $limit, - ), - 'allow-field-select' => true, - 'link'=>array( - 'fk_warehouse'=>''.img_picto('','object_stock.png','',0).' @label@' - ), - 'translate'=>array(), - 'hide'=>$THide, - 'type'=>array( - 'datec'=>'date', - 'tms'=>'datetime', - 'date_inventory'=>'date' - ), - 'list'=>array( - 'title'=>$langs->trans('inventoryListTitle'), - 'messageNothing'=>$langs->trans('inventoryListEmpty'), - 'image' => 'title_products.png' - ), - 'title'=>array( - 'rowid'=>$langs->trans('Title'), - 'date_inventory'=>$langs->trans('InventoryDate'), - 'fk_warehouse'=>$langs->trans('Warehouse'), - 'datec'=>$langs->trans('DateCreation'), - 'tms'=>$langs->trans('DateModification'), - 'status'=>$langs->trans('Status') - ), - 'eval'=>array( - 'status' => '(@val@ ? img_picto("'.$langs->trans("inventoryValidate").'", "statut4") : img_picto("'.$langs->trans("inventoryDraft").'", "statut3"))', - 'rowid'=>'Inventory::getLink(@val@)' - ), - 'position' => array( - 'text-align' => array('status' => 'right') - - ), - 'search'=>array( - 'rowid' => array('search_type' => true, 'table' => array('i'), 'field' => array('title')), - 'date_inventory'=>array('search_type' => 'calendars', 'table' => array('i'), 'field' => array('date_inventory')), - 'status'=>array('search_type' => array(1=>$langs->trans("inventoryValidate"), 0=>$langs->trans("inventoryDraft"))) - ) -)); - - -/*if (!empty($user->rights->stock->create)) +// Protection if external user +$socid=0; +if ($user->societe_id > 0) { - print '
'; - print ''.$langs->trans('inventoryCreate').''; + //$socid = $user->societe_id; + accessforbidden(); +} + +// Initialize array of search criterias +$search_all=trim(GETPOST("search_all",'alpha')); +$search=array(); +foreach($object->fields as $key => $val) +{ + if (GETPOST('search_'.$key,'alpha')) $search[$key]=GETPOST('search_'.$key,'alpha'); +} + +// List of fields to search into when doing a "search in all" +$fieldstosearchall = array(); +foreach($object->fields as $key => $val) +{ + if ($val['searchall']) $fieldstosearchall['t.'.$key]=$val['label']; +} + +// Definition of fields for list +$arrayfields=array(); +foreach($object->fields as $key => $val) +{ + // If $val['visible']==0, then we never show the field + if (! empty($val['visible'])) $arrayfields['t.'.$key]=array('label'=>$val['label'], 'checked'=>(($val['visible']<0)?0:1), 'enabled'=>$val['enabled']); +} +// Extra fields +if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) +{ + foreach($extrafields->attribute_label as $key => $val) + { + $arrayfields["ef.".$key]=array('label'=>$extrafields->attribute_label[$key], 'checked'=>$extrafields->attribute_list[$key], 'position'=>$extrafields->attribute_pos[$key], 'enabled'=>$extrafields->attribute_perms[$key]); + } +} + + + + +/* + * ACTIONS + * + * Put here all code to do according to value of "$action" parameter + */ + +if (GETPOST('cancel')) { $action='list'; $massaction=''; } +if (! GETPOST('confirmmassaction') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction=''; } + +$parameters=array(); +$reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + +if (empty($reshook)) +{ + // Selection of new fields + include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; + + // Purge search criteria + 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 + { + foreach($object->fields as $key => $val) + { + $search[$key]=''; + } + $toselect=''; + $search_array_options=array(); + } + if (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha') + || GETPOST('button_search_x','alpha') || GETPOST('button_search.x','alpha') || GETPOST('button_search','alpha')) + { + $massaction=''; // Protection to avoid mass action if we force a new search during a mass action confirmation + } + + // Mass actions + $objectclass='Inventory'; + $objectlabel='Inventory'; + $permtoread = $user->rights->inventory->read; + $permtodelete = $user->rights->inventory->delete; + $uploaddir = $conf->inventory->dir_output; + include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; +} + + + +/* + * VIEW + * + * Put here all code to build page + */ + +$form=new Form($db); + +$now=dol_now(); + +//$help_url="EN:Module_Inventory|FR:Module_Inventory_FR|ES:Módulo_Inventory"; +$help_url=''; +$title = $langs->trans('ListOf', $langs->transnoentitiesnoconv("Inventorys")); + + +// Build and execute select +// -------------------------------------------------------------------- +$sql = 'SELECT '; +foreach($object->fields as $key => $val) +{ + $sql.='t.'.$key.', '; +} +// Add fields from extrafields +foreach ($extrafields->attribute_label as $key => $val) $sql.=($extrafields->attribute_type[$key] != 'separate' ? ", ef.".$key.' as options_'.$key : ''); +// Add fields from hooks +$parameters=array(); +$reshook=$hookmanager->executeHooks('printFieldListSelect',$parameters); // Note that $action and $object may have been modified by hook +$sql.=$hookmanager->resPrint; +$sql=preg_replace('/, $/','', $sql); +$sql.= " FROM ".MAIN_DB_PREFIX."inventory as t"; +if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."inventory_extrafields as ef on (t.rowid = ef.fk_object)"; +$sql.= " WHERE t.entity IN (".getEntity('inventory').")"; +foreach($search as $key => $val) +{ + if ($search[$key] != '') $sql.=natural_search($key, $search[$key], (($key == 'status')?2:($object->fields[$key]['type'] == 'integer'?1:0))); +} +if ($search_all) $sql.= natural_search(array_keys($fieldstosearchall), $search_all); +// Add where from extra fields +foreach ($search_array_options as $key => $val) +{ + $crit=$val; + $tmpkey=preg_replace('/search_options_/','',$key); + $typ=$extrafields->attribute_type[$tmpkey]; + $mode=0; + if (in_array($typ, array('int','double','real'))) $mode=1; // Search on a numeric + if ($val && ( ($crit != '' && ! in_array($typ, array('select'))) || ! empty($crit))) + { + $sql .= natural_search('ef.'.$tmpkey, $crit, $mode); + } +} +// Add where from hooks +$parameters=array(); +$reshook=$hookmanager->executeHooks('printFieldListWhere',$parameters); // Note that $action and $object may have been modified by hook +$sql.=$hookmanager->resPrint; +$sql.=$db->order($sortfield,$sortorder); + +// Count total nb of records +$nbtotalofrecords = ''; +if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) +{ + $result = $db->query($sql); + $nbtotalofrecords = $db->num_rows($result); +} + +$sql.= $db->plimit($limit+1, $offset); + +dol_syslog($script_file, LOG_DEBUG); +$resql=$db->query($sql); +if (! $resql) +{ + dol_print_error($db); + exit; +} + +$num = $db->num_rows($resql); + +// Direct jump if only one record found +if ($num == 1 && ! empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $search_all) +{ + $obj = $db->fetch_object($resql); + $id = $obj->rowid; + header("Location: ".DOL_URL_ROOT.'/inventory/inventory_card.php?id='.$id); + exit; +} + + +// Output page +// -------------------------------------------------------------------- + +llxHeader('', $title, $help_url); + +// Example : Adding jquery code +print ''; + +$arrayofselected=is_array($toselect)?$toselect:array(); + +$param=''; +if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.$contextpage; +if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.$limit; +foreach($search as $key => $val) +{ + $param.= '&search_'.$key.'='.urlencode($search[$key]); +} +if ($optioncss != '') $param.='&optioncss='.$optioncss; +// Add $param from extra fields +foreach ($search_array_options as $key => $val) +{ + $crit=$val; + $tmpkey=preg_replace('/search_options_/','',$key); + if ($val != '') $param.='&search_options_'.$tmpkey.'='.urlencode($val); +} + +$arrayofmassactions = array( + 'presend'=>$langs->trans("SendByMail"), + 'builddoc'=>$langs->trans("PDFMerge"), +); +if ($user->rights->inventory->delete) $arrayofmassactions['delete']=$langs->trans("Delete"); +if ($massaction == 'presend') $arrayofmassactions=array(); +$massactionbutton=$form->selectMassAction('', $arrayofmassactions); + +print ''; +if ($optioncss != '') print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_companies', 0, '', '', $limit); + +if ($sall) +{ + foreach($fieldstosearchall as $key => $val) $fieldstosearchall[$key]=$langs->trans($val); + print $langs->trans("FilterOnInto", $sall) . join(', ',$fieldstosearchall); +} + +$moreforfilter = ''; +$moreforfilter.='
'; +$moreforfilter.= $langs->trans('MyFilter') . ': '; +$moreforfilter.= '
'; + +$parameters=array(); +$reshook=$hookmanager->executeHooks('printFieldPreListTitle',$parameters); // Note that $action and $object may have been modified by hook +if (empty($reshook)) $moreforfilter .= $hookmanager->resPrint; +else $moreforfilter = $hookmanager->resPrint; + +if (! empty($moreforfilter)) +{ + print '
'; + print $moreforfilter; print '
'; -}*/ +} -echo ''; +$varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage; +$selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields.=$form->showCheckAddButtons('checkforselect', 1); -llxFooter(''); -$db->close(); \ No newline at end of file +print '
'; +print ''."\n"; + + +// Fields title search +// -------------------------------------------------------------------- +print ''; +foreach($object->fields as $key => $val) +{ + if (in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; + $align=''; + if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; + if (in_array($val['type'], array('timestamp'))) $align.=' nowrap'; + if (! empty($arrayfields['t.'.$key]['checked'])) print ''; +} +// Extra fields +if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) +{ + foreach($extrafields->attribute_label as $key => $val) + { + if (! empty($arrayfields["ef.".$key]['checked'])) + { + $align=$extrafields->getAlignFlag($key); + $typeofextrafield=$extrafields->attribute_type[$key]; + print ''; + } + } +} +// Fields from hook +$parameters=array('arrayfields'=>$arrayfields); +$reshook=$hookmanager->executeHooks('printFieldListOption',$parameters); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +// Rest of fields search +foreach($object->fields as $key => $val) +{ + if (! in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; + $align=''; + if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; + if (in_array($val['type'], array('timestamp'))) $align.=' nowrap'; + if (! empty($arrayfields['t.'.$key]['checked'])) print ''; +} +// Action column +print ''; +print ''."\n"; + + +// Fields title label +// -------------------------------------------------------------------- +print ''; +foreach($object->fields as $key => $val) +{ + if (in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; + $align=''; + if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; + if (in_array($val['type'], array('timestamp'))) $align.='nowrap'; + if (! empty($arrayfields['t.'.$key]['checked'])) print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($align?'class="'.$align.'"':''), $sortfield, $sortorder, $align.' ')."\n"; +} +// Extra fields +if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) +{ + foreach($extrafields->attribute_label as $key => $val) + { + if (! empty($arrayfields["ef.".$key]['checked'])) + { + $align=$extrafields->getAlignFlag($key); + $sortonfield = "ef.".$key; + if (! empty($extrafields->attribute_computed[$key])) $sortonfield=''; + print getTitleFieldOfList($langs->trans($extralabels[$key]), 0, $_SERVER["PHP_SELF"], $sortonfield, "", $param, ($align?'align="'.$align.'"':''), $sortfield, $sortorder)."\n"; + } + } +} +// Hook fields +$parameters=array('arrayfields'=>$arrayfields); +$reshook=$hookmanager->executeHooks('printFieldListTitle',$parameters); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +// Rest of fields title +foreach($object->fields as $key => $val) +{ + if (! in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; + $align=''; + if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; + if (in_array($val['type'], array('timestamp'))) $align.=' nowrap'; + if (! empty($arrayfields['t.'.$key]['checked'])) print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($align?'class="'.$align.'"':''), $sortfield, $sortorder, $align.' ')."\n"; +} +print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"],"",'','','align="center"',$sortfield,$sortorder,'maxwidthsearch ')."\n"; +print ''."\n"; + + +// Detect if we need a fetch on each output line +$needToFetchEachLine=0; +foreach ($extrafields->attribute_computed as $key => $val) +{ + if (preg_match('/\$object/',$val)) $needToFetchEachLine++; // There is at least one compute field that use $object +} + + +// Loop on record +// -------------------------------------------------------------------- +$i=0; +$totalarray=array(); +while ($i < min($num, $limit)) +{ + $obj = $db->fetch_object($resql); + if ($obj) + { + // Store properties in $object + $object->id = $obj->rowid; + foreach($object->fields as $key => $val) + { + if (isset($obj->$key)) $object->$key = $obj->$key; + } + + // Show here line of result + print ''; + foreach($object->fields as $key => $val) + { + if (in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; + $align=''; + if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; + if (in_array($val['type'], array('timestamp'))) $align.='nowrap'; + if ($key == 'status') $align.=($align?' ':'').'center'; + if (! empty($arrayfields['t.'.$key]['checked'])) + { + print ''; + if (in_array($val['type'], array('date','datetime','timestamp'))) print dol_print_date($db->jdate($obj->$key), 'dayhour'); + elseif ($key == 'ref') print $object->getNomUrl(1); + elseif ($key == 'status') print $object->getLibStatut(3); + else print $obj->$key; + print ''; + if (! $i) $totalarray['nbfield']++; + if (! empty($val['isameasure'])) + { + if (! $i) $totalarray['pos'][$totalarray['nbfield']]='t.'.$key; + $totalarray['val']['t.'.$key] += $obj->$key; + } + } + } + // Extra fields + if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) + { + foreach($extrafields->attribute_label as $key => $val) + { + if (! empty($arrayfields["ef.".$key]['checked'])) + { + print 'getAlignFlag($key); + if ($align) print ' align="'.$align.'"'; + print '>'; + $tmpkey='options_'.$key; + print $extrafields->showOutputField($key, $obj->$tmpkey, '', 1); + print ''; + if (! $i) $totalarray['nbfield']++; + if (! empty($val['isameasure'])) + { + if (! $i) $totalarray['pos'][$totalarray['nbfield']]='ef.'.$tmpkey; + $totalarray['val']['ef.'.$tmpkey] += $obj->$tmpkey; + } + } + } + } + // Fields from hook + $parameters=array('arrayfields'=>$arrayfields, 'obj'=>$obj); + $reshook=$hookmanager->executeHooks('printFieldListValue',$parameters); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + // Rest of fields + foreach($object->fields as $key => $val) + { + if (! in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; + $align=''; + if (in_array($val['type'], array('date','datetime','timestamp'))) $align.=($align?' ':'').'center'; + if (in_array($val['type'], array('timestamp'))) $align.=($align?' ':'').'nowrap'; + if ($key == 'status') $align.=($align?' ':'').'center'; + if (! empty($arrayfields['t.'.$key]['checked'])) + { + print ''; + if (in_array($val['type'], array('date','datetime','timestamp'))) print dol_print_date($db->jdate($obj->$key), 'dayhour'); + elseif ($key == 'status') print $object->getLibStatut(3); + else print $obj->$key; + print ''; + if (! $i) $totalarray['nbfield']++; + if (! empty($val['isameasure'])) + { + if (! $i) $totalarray['pos'][$totalarray['nbfield']]='t.'.$key; + $totalarray['val']['t.'.$key] += $obj->$key; + } + } + } + // Action column + print ''; + if (! $i) $totalarray['nbfield']++; + + print ''; + } + $i++; +} + +// Show total line +if (isset($totalarray['pos'])) +{ + print ''; + $i=0; + while ($i < $totalarray['nbfield']) + { + $i++; + if (! empty($totalarray['pos'][$i])) print ''; + else + { + if ($i == 1) + { + if ($num < $limit) print ''; + else print ''; + } + print ''; + } + } + print ''; +} + +// If no record found +if ($num == 0) +{ + $colspan=1; + foreach($arrayfields as $key => $val) { if (! empty($val['checked'])) $colspan++; } + print ''; +} + + +$db->free($resql); + +$parameters=array('arrayfields'=>$arrayfields, 'sql'=>$sql); +$reshook=$hookmanager->executeHooks('printFieldListFooter',$parameters); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + +print '
'; + if (in_array($typeofextrafield, array('varchar', 'int', 'double', 'select')) && empty($extrafields->attribute_computed[$key])) + { + $crit=$val; + $tmpkey=preg_replace('/search_options_/','',$key); + $searchclass=''; + if (in_array($typeofextrafield, array('varchar', 'select'))) $searchclass='searchstring'; + if (in_array($typeofextrafield, array('int', 'double'))) $searchclass='searchnum'; + print ''; + } + print ''; +$searchpicto=$form->showFilterButtons(); +print $searchpicto; +print '
'; + if ($massactionbutton || $massaction) // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + { + $selected=0; + if (in_array($obj->rowid, $arrayofselected)) $selected=1; + print ''; + } + print '
'.price($totalarray['val'][$totalarray['pos'][$i]]).''.$langs->trans("Total").''.$langs->trans("Totalforthispage").'
'.$langs->trans("NoRecordFound").'
'."\n"; +print '
'."\n"; + +print ''."\n"; + +if ($nbtotalofrecords === '' || $nbtotalofrecords) +{ + if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) + { + require_once(DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'); + $formfile = new FormFile($db); + + // Show list of available documents + $urlsource=$_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder; + $urlsource.=str_replace('&','&',$param); + + $filedir=$diroutputmassaction; + $genallowed=$user->rights->inventory->read; + $delallowed=$user->rights->inventory->read; + + print $formfile->showdocuments('massfilesarea_inventory','',$filedir,$urlsource,0,$delallowed,'',1,1,0,48,1,$param,$title,''); + } + else + { + print '
'.$langs->trans("ShowTempMassFilesArea").''; + } +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/product/inventory/listview.class.php b/htdocs/product/inventory/listview.class.php deleted file mode 100644 index 3dddac44516..00000000000 --- a/htdocs/product/inventory/listview.class.php +++ /dev/null @@ -1,1083 +0,0 @@ - - - This program and all files within this directory and sub directory - 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 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 . - */ - -/** - * Class to manage the lists view - */ -class Listview -{ - /** - * Constructor - * - * @param DoliDB $db Database handler - * @param string $id html id - */ - function __construct(&$db, $id) - { - $this->db = &$db; - $this->id = $id; - $this->TTotalTmp=array(); - $this->sql = ''; - $this->form = null; - $this->totalRowToShow=0; - $this->totalRow=0; - - $this->TField=array(); - - require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; - $this->extrafields = new ExtraFields($this->db); - $this->extralabels = $this->extrafields->fetch_name_optionals_label('product'); - $this->search_array_options=$this->extrafields->getOptionalsFromPost($this->extralabels,'','search_'); - } - - /** - * Function to init fields - * - * @param array $TParam array of configuration of list - * @return bool - */ - private function init(&$TParam) - { - global $conf, $langs, $user; - - if(!isset($TParam['hide'])) $TParam['hide']=array(); - if(!isset($TParam['link'])) $TParam['link']=array(); - if(!isset($TParam['type'])) $TParam['type']=array(); - if(!isset($TParam['orderby']['noOrder'])) $TParam['orderby']['noOrder']=array(); - if(!isset($TParam['allow-fields-select'])) $TParam['allow-fields-select'] = 0; - - if(!isset($TParam['list']))$TParam['list']=array(); - $TParam['list'] = array_merge(array( - 'messageNothing'=>$langs->trans('ListMessageNothingToShow') - ,'noheader'=>0 - ,'useBottomPagination'=>0 - ,'image'=>'' - ,'title'=>$langs->trans('List') - ,'orderDown'=>'' - ,'orderUp'=>'' - ,'id'=>$this->id - ,'head_search'=>'' - ,'export'=>array() - ,'view_type'=>'' - ,'massactions'=>array() - ),$TParam['list']); - - if (empty($TParam['limit'])) $TParam['limit'] = array(); - - $page = GETPOST('page'); - if (!empty($page)) $TParam['limit']['page'] = $page; - - $TParam['limit'] = array_merge(array('page'=>0, 'nbLine' => $conf->liste_limit, 'global'=>0), $TParam['limit']); - - if (GETPOST('sortfield')) - { - $TParam['sortfield'] = GETPOST('sortfield'); - $TParam['sortorder'] = GETPOST('sortorder'); - } - - include_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; - $this->form = new Form($this->db); - } - - - /** - * Function to know if we can search on null value - * @param string $key field name - * @param array $TParam array of configuration - * @return bool - */ - private function getSearchNull($key, &$TParam) - { - return !empty($TParam['search'][$key]['allow_is_null']); - } - - /** - * @param string $key field name - * @param string $TParam array of configuration - * @return array - */ - private function getSearchKey($key, &$TParam) - { - $TPrefixe = array(); - if(!empty($TParam['search'][$key]['table'])) - { - if (!is_array($TParam['search'][$key]['table'])) $TParam['search'][$key]['table'] = array($TParam['search'][$key]['table']); - - foreach ($TParam['search'][$key]['table'] as $prefix_table) - { - $TPrefixe[] = $prefix_table.'.'; - } - } - - $TKey=array(); - if(!empty($TParam['search'][$key]['field'])) - { - if (!is_array($TParam['search'][$key]['field'])) $TParam['search'][$key]['field'] = array($TParam['search'][$key]['field']); - - foreach ($TParam['search'][$key]['field'] as $i => $field) - { - $prefixe = !empty($TPrefixe[$i]) ? $TPrefixe[$i] : $TPrefixe[0]; - $TKey[] = $prefixe. $field ; - } - } - else - { - $TKey[] = $TPrefixe[0].$key; - } - - return $TKey; - } - /** - * @param string $TSQLMore contain some additional sql instructions - * @param string $value date with read format - * @param string $sKey field name - */ - private function addSqlFromTypeDate(&$TSQLMore, &$value, $sKey) - { - if(is_array($value)) - { - $TSQLDate=array(); - if(!empty($value['start'])) - { - $TSQLDate[]=$sKey." >= '".$value['start']."'" ; - } - - if(!empty($value['end'])) - { - $TSQLDate[]=$sKey." <= '".$value['end']."'" ; - } - - if(!empty($TSQLDate)) $TSQLMore[] = implode(' AND ', $TSQLDate); - } - else - { - $TSQLMore[]=$sKey." LIKE '".$value."%'" ; - } - } - - - /** - * @param string $TSQLMore contain some additional sql instructions - * @param string $value value to filter - * @param string $TParam array of configuration - * @param string $sKey field name - * @param string $key reference of sKey to find value into TParam - * @return bool - */ - private function addSqlFromOther(&$TSQLMore, &$value, &$TParam, $sKey, $key) - { - // Do not use empty() function, statut 0 exist - if ($value == '') return false; - elseif($value==-1) return false; - - if(isset($TParam['operator'][$key])) - { - if($TParam['operator'][$key] == '<' || $TParam['operator'][$key] == '>' || $TParam['operator'][$key]=='=') - { - $TSQLMore[] = $sKey . ' ' . $TParam['operator'][$key] . ' "' . $value . '"'; - } - elseif ($TParam['operator'][$key]=='IN') - { - $TSQLMore[] = $sKey . ' ' . $TParam['operator'][$key] . ' (' . $value . ')'; - } - else - { - if(strpos($value,'%')===false) $value = '%'.$value.'%'; - $TSQLMore[]=$sKey." LIKE '".addslashes($value)."'" ; - } - } - else - { - if(strpos($value,'%')===false) $value = '%'.$value.'%'; - $TSQLMore[]=$sKey." LIKE '".addslashes($value)."'" ; - } - - return true; - } - - - /** - * @param string $sql standard select sql - * @param string $TParam array of configuration - * @return string - */ - private function search($sql, &$TParam) - { - if (empty($TParam['no-auto-sql-search']) && !GETPOST('button_removefilter_x','alpha') && !GETPOST('button_removefilter.x','alpha') && !GETPOST('button_removefilter','alpha')) - { - foreach ($TParam['search'] as $field => $info) - { - $TsKey = $this->getSearchKey($field, $TParam); - $TSQLMore = array(); - $allow_is_null = $this->getSearchNull($field,$TParam); - - $fieldname = !empty($info['fieldname']) ? $info['fieldname'] : 'Listview_'.$this->id.'_search_'.$field; - - foreach ($TsKey as $i => &$sKey) - { - $value = GETPOST($fieldname); - $value_null = GETPOST('Listview_'.$this->id.'_search_on_null_'.$field); - - if ($allow_is_null && !empty($value_null)) - { - $TSQLMore[] = $sKey.' IS NULL '; - $value = ''; - } - - if (isset($TParam['type'][$field]) && ($TParam['type'][$field]==='date' || $TParam['type'][$field]==='datetime')) - { - $k = $fieldname; - if ($info['search_type'] === 'calendars') - { - $value = array(); - - $timestart = dol_mktime(0, 0, 0, GETPOST($k.'_startmonth'), GETPOST($k.'_startday'), GETPOST($k.'_startyear')); - if ($timestart) $value['start'] = date('Y-m-d', $timestart); - - $timeend = dol_mktime(23, 59, 59, GETPOST($k.'_endmonth'), GETPOST($k.'_endday'), GETPOST($k.'_endyear')); - if ($timeend) $value['end'] = date('Y-m-d', $timeend); - } - else - { - $time = dol_mktime(12, 0, 0, GETPOST($k.'month'), GETPOST($k.'day'), GETPOST($k.'year')); - if ($time) $value = date('Y-m-d', $time); - } - - if (!empty($value)) $this->addSqlFromTypeDate($TSQLMore, $value, $sKey); - } - else - { - $this->addSqlFromOther($TSQLMore, $value, $TParam, $sKey, $field); - } - } - - if (!empty($TSQLMore)) - { - $sql.=' AND ( '.implode(' OR ',$TSQLMore).' ) '; - } - } - } - - if ($sqlGROUPBY!='') $sql.=' GROUP BY '.$sqlGROUPBY; - - return $sql; - } - - /** - * @param string $sql standard select sql - * @param string $TParam array of configuration - * @return string - */ - public function render($sql, $TParam=array()) - { - global $conf; - - $TField= & $this->TField; - - $this->init($TParam); - - $THeader = $this->initHeader($TParam); - - $sql = $this->search($sql,$TParam); - $sql.= $this->db->order($TParam['sortfield'], $TParam['sortorder']); - - if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) - { - $result = $this->db->query($sql); - $this->totalRow = $this->db->num_rows($result); - } - - $this->parse_sql($THeader, $TField, $TParam, $sql); - list($TTotal, $TTotalGroup)=$this->get_total($TField, $TParam); - - return $this->renderList($THeader, $TField, $TTotal, $TTotalGroup, $TParam); - } - - /** - * @param string $THeader the configuration of header - * @param string $TParam array of configuration - * @return array - */ - private function setSearch(&$THeader, &$TParam) - { - global $langs, $form; - - if(empty($TParam['search'])) return array(); - - $TSearch=array(); - - $nb_search_in_bar = 0; - - foreach($THeader as $key => $libelle) - { - if(empty($TSearch[$key]))$TSearch[$key]=''; - } - - $removeFilter = (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha')); - foreach($TParam['search'] as $key => $param_search) - { - if ($removeFilter) $value = ''; - - $typeRecherche = (is_array($param_search) && isset($param_search['search_type'])) ? $param_search['search_type'] : $param_search; - - $fieldname = !empty($param_search['fieldname']) ? $param_search['fieldname'] : 'Listview_'.$this->id.'_search_'.$key; - $value = $removeFilter ? '' : GETPOST($fieldname); - - if(is_array($typeRecherche)) - { - $fsearch=$form->selectarray($fieldname, $typeRecherche,$value,1); - } - else if($typeRecherche==='calendar') - { - if (!$removeFilter) $value = GETPOST($fieldname) ? mktime(0,0,0, (int) GETPOST($fieldname.'month'), (int) GETPOST($fieldname.$key.'day'), (int) GETPOST($fieldname.'year') ) : ''; - - $fsearch = $form->select_date($value, $fieldname,0, 0, 1, "", 1, 0, 1); - } - else if($typeRecherche==='calendars') - { - $value_start = $value_end = ''; - if (!$removeFilter) - { - $value_start = GETPOST($fieldname.'_start') ? mktime(0,0,0, (int) GETPOST($fieldname.'_startmonth'), (int) GETPOST($fieldname.'_startday'), (int) GETPOST($fieldname.'_startyear') ) : ''; - $value_end = GETPOST($fieldname.'_end') ? mktime(0,0,0, (int) GETPOST($fieldname.'_endmonth'), (int) GETPOST($fieldname.'_endday'), (int) GETPOST($fieldname.'_endyear') ) : ''; - } - - $fsearch = $form->select_date($value_start,$fieldname.'_start',0, 0, 1, "", 1, 0, 1) - . $form->select_date($value_end, $fieldname.'_end',0, 0, 1, "", 1, 0, 1); - - } - else if(is_string($typeRecherche)) - { - $fsearch=$TParam['search'][$key]; - } - else - { - $fsearch=''; - } - - if(!empty($param_search['allow_is_null'])) - { - $valueNull = GETPOST($fieldname.'search_on_null_'.$key) ? 1 : 0; - $fsearch.=' '.$form->checkbox1('', $fieldname.'search_on_null_'.$key,1, $valueNull,' onclick=" if($(this).is(\':checked\')){ $(this).prev().val(\'\'); }" ').img_help(1, $langs->trans('SearchOnNUllValue')); - } - - if(!empty($THeader[$key])) - { - $TSearch[$key] = $fsearch; - $nb_search_in_bar++; - } - } - - $search_button = ' '.img_search().''; - $search_button .= ' '.img_searchclear().''; - - if($nb_search_in_bar>0) - { - end($TSearch); - list($key,$v) = each($TSearch); - $TSearch[$key].=$search_button; - } - else - { - $TSearch=array(); - } - - return $TSearch; - } - - /** - * Function to analyse and calculate the total from a column - * - * @param string $TField TField - * @param string $TParam TParam - * @return array - */ - private function get_total(&$TField, &$TParam) - { - $TTotal=$TTotalGroup=array(); - - if(!empty($TParam['math']) && !empty($TField[0])) - { - foreach($TField[0] as $field=>$value) - { - $TTotal[$field]=''; - $TTotalGroup[$field] = ''; - } - - foreach($TParam['math'] as $field=>$typeMath) - { - if(is_array($typeMath)) - { - $targetField = $typeMath[1]; - $typeMath = $typeMath[0]; - } - else - { - $targetField = $field; - } - - if($typeMath == 'groupsum') - { - $TTotalGroup[$field] = array('target'=>$targetField, 'values'=> $this->TTotalTmp['@groupsum'][$targetField]); - } - else if($typeMath=='average') - { - $TTotal[$field]=array_sum($this->TTotalTmp[$targetField]) / count($this->TTotalTmp[$targetField]); - } - elseif($typeMath=='count') - { - $TTotal[$field]=count($this->TTotalTmp[$targetField]); - } - else - { - $TTotal[$field]=array_sum($this->TTotalTmp[$targetField]); - } - } - } - - return array($TTotal,$TTotalGroup); - } - - /** - * @return string - */ - /* - private function getJS() - { - $javaScript = ''; - - return $javaScript; - } - */ - - /** - * @param string $TParam TParam - * @param string $TField TField - * @param string $THeader THeader - * @return array - */ - private function setExport(&$TParam, $TField, $THeader) - { - global $langs; - - $Tab=array(); - if(!empty($TParam['export'])) - { - $token = GETPOST('token'); - if(empty($token)) $token = md5($this->id.time().rand(1,9999)); - - $_SESSION['token_list_'.$token] = gzdeflate( serialize( array( - 'title'=>$this->title, - 'sql'=>$this->sql, - 'TBind'=>$this->TBind, - 'TChamps'=>$TField, - 'TEntete'=>$THeader - ))); - - foreach($TParam['export'] as $mode_export) - { - $Tab[] = array( - 'label'=>$langs->trans('Export'.$mode_export), - 'url'=>dol_buildpath('/abricot/downlist.php',1), - 'mode'=>$mode_export, - 'token'=>$token, - 'session_name'=>session_name() - ); - } - - } - - return $Tab; - } - - /** - * @param string $TField TField - * @param string $TTotalGroup TTotalGroup - * @return array - */ - private function addTotalGroup($TField, $TTotalGroup) - { - global $langs; - - $Tab=array(); - $proto_total_line = array(); - $tagbase = $old_tagbase = null; - $addGroupLine = false; - - foreach($TField as $k=>&$line) - { - if(empty($proto_total_line)) - { - foreach($line as $field=>$value) - { - $proto_total_line[$field] = ''; - } - $group_line = $proto_total_line; - } - - $addGroupLine = false; - - $tagbase = ''; - foreach($line as $field=>$value) - { - if(!empty($TTotalGroup[$field])) - { - $tagbase.=$value.'|'; - $group_line[$field] = '
'.(empty($value) ? $langs->trans('Empty') : $value ).' :
'; - $group_line[$TTotalGroup[$field]['target']] = '
'.price($TTotalGroup[$field]['values'][$value]).'
'; - $addGroupLine = true; - } - } - - if(!is_null($old_tagbase) && $old_tagbase!=$tagbase && $addGroupLine) - { - $Tab[] = $previous_group_line; - } - - $old_tagbase = $tagbase; - $previous_group_line = $group_line; - $group_line = $proto_total_line; - - $Tab[] = $line; - } - - if($addGroupLine) - { - $Tab[] = $previous_group_line; - } - - return $Tab; - } - - /** - * @param string $THeader THeader - * @param string $TField TField - * @param string $TTotal TTotal - * @param string $TTotalGroup TTotalGroup - * @param string $TParam TParam - * @return string - */ - private function renderList(&$THeader, &$TField, &$TTotal, &$TTotalGroup, &$TParam) - { - global $bc,$form; - - $TSearch = $this->setSearch($THeader, $TParam); - $TExport = $this->setExport($TParam, $TField, $THeader); - $TField = $this->addTotalGroup($TField,$TTotalGroup); - - //$out = $this->getJS(); - - $massactionbutton= empty($TParam['list']['massactions']) ? '' : $form->selectMassAction('', $TParam['list']['massactions']); - - $dolibarr_decalage = $this->totalRow > $this->totalRowToShow ? 1 : 0; - ob_start(); - print_barre_liste($TParam['list']['title'], $TParam['limit']['page'], $_SERVER["PHP_SELF"], '&'.$TParam['list']['param_url'], $TParam['sortfield'], $TParam['sortorder'], $massactionbutton, $this->totalRowToShow+$dolibarr_decalage, $this->totalRow, $TParam['list']['image'], 0, '', '', $TParam['limit']['nbLine']); - $out .= ob_get_clean(); - - $classliste='liste'; - if(!empty($TParam['head_search'])) { - $out.='
'; - $out.=$TParam['head_search']; - $out.='
'; - - $classliste.=' listwithfilterbefore'; - } - - $out.= '
'; - $out.= ''; - - if(count($TSearch)>0) - { - $out.=''; - - foreach ($THeader as $field => $head) - { - if ($field === 'selectedfields') - { - $out.= ''; - } - else - { - $moreattrib = 'style="width:'.$head['width'].';text-align:'.$head['text-align'].'"'; - $out .= ''; - } - } - - $out.=''; - } - - $out.= ''; - foreach($THeader as $field => $head) - { - $moreattrib = ''; - $search = ''; - $prefix = ''; - - $label = $head['label']; - - if ($field === 'selectedfields') - { - $moreattrib = 'align="right" '; - $prefix = 'maxwidthsearch '; - - if(!empty($TParam['list']['massactions'])) { - $label.=$form->showCheckAddButtons('checkforselect', 1); - } - - } - - if (empty($head['width'])) $head['width'] = 'auto'; - if (!empty($head['width']) && !empty($head['text-align'])) $moreattrib .= 'style="width:'.$head['width'].';text-align:'.$head['text-align'].'"'; - - if (isset($TParam['search'][$field]['search_type']) && $TParam['search'][$field]['search_type'] !== false) - { - $TsKey = $this->getSearchKey($field, $TParam); - if (!empty($TsKey)) $search = implode(',', $TsKey); - else $search = $field; - } - - $out .= getTitleFieldOfList($label, 0, $_SERVER["PHP_SELF"], $search, '', $moreparam, $moreattrib, $TParam['sortfield'], $TParam['sortorder'], $prefix); - $out .= $head['more']; - } - - //$out .= ''; - $out .= ''; - - $out.=''; - - if(empty($TField)) - { - if (!empty($TParam['list']['messageNothing'])) $out .= ''; - } - else - { - $line_number = 0; - foreach($TField as $fields) - { - if($this->in_view($TParam, $line_number)) - { - $out.=''; - - foreach ($THeader as $field => $head) - { - $value_aff =(isset($fields[$field]) ? $fields[$field] : ' '); - - if ($field === 'selectedfields') - { - $head['text-align']='center'; - if(!empty($TParam['list']['massactions'])) { - $arrayofselected=array(); // TODO get in param - $selected=0; - if (in_array($obj->rowid, $arrayofselected)) $selected=1; - $value_aff.=''; - } - } - - $moreattrib = 'style="width:'.$head['width'].';text-align:'.$head['text-align'].'"'; - $out.=''; - } - - $out.=''; - } - - $line_number++; - } - - $out.=''; - - if (!empty($TParam['list']['haveTotal'])) - { - $out.=''; - - foreach ($THeader as $field => $head) - { - if (isset($TTotal[$field])) - { - $moreattrib = 'style="width:'.$head['width'].';text-align:'.$head['text-align'].'"'; - $out.=''; - } - } - - $out.=''; - } - } - - $out .= '
--
'.$TParam['list']['messageNothing'].'
'.$value_aff.'
'.price($TTotal[$field]).'
'; - $out .= '
'; - - return $out; - } - - /** - * @param string $db Db - * @param string $TField TField - * @param string $TParam TParam - */ - public function renderArray(&$db, $TField, $TParam=array()) - { - $this->typeRender = 'array'; - - $TField=array(); - - $this->init($TParam); - $THeader = $this->initHeader($TParam); - - $this->parse_array($THeader, $TField, $TParam); - list($TTotal, $TTotalGroup)=$this->get_total($TField, $TParam); - - $this->renderList($THeader, $TField, $TTotal, $TTotalGroup, $TParam); - } - - - /** - * @param string $THeader THeader - * @param string $TField TField - * @param string $TParam TParam - * @return bool - */ - private function parse_array(&$THeader, &$TField, &$TParam) - { - $this->totalRow = count($TField); - - $this->THideFlip = array_flip($TParam['hide']); - $this->TTotalTmp=array(); - - if (empty($TField)) return false; - - foreach($TField as $row) - { - $this->set_line($THeader, $TField, $TParam, $row); - } - } - - - private function initHeader(&$TParam) - { - global $user,$conf; - - $THeader = array(); - - $TField=$TFieldVisibility=array(); - foreach ($TParam['title'] as $field => $value) - { - $TField[$field]=true; - } - - $contextpage=md5($_SERVER['PHP_SELF']); - if(!empty($TParam['allow-fields-select'])) - { - $selectedfields = GETPOST('Listview'.$this->id.'_selectedfields'); - - if(!empty($selectedfields)) - { - include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; - $tabparam['MAIN_SELECTEDFIELDS_'.$contextpage] = $selectedfields; - $result=dol_set_user_param($this->db, $conf, $user, $tabparam); - } - - $tmpvar='MAIN_SELECTEDFIELDS_'.$contextpage; - if (! empty($user->conf->{$tmpvar})) - { - $tmparray = explode(',', $user->conf->{$tmpvar}); - $TParam['hide'] = array(); - foreach($TField as $field => $dummy) - { - $label = $TParam['title'][$field]; - if(!in_array($field, $tmparray)) - { - $TParam['hide'][] = $field; - $visible = 0; - } - else - { - // Overrive search from extrafields - // for the type as 'checkbox', 'chkbxlst', 'sellist' we should use code instead of id (example: I declare a 'chkbxlst' to have a link with dictionnairy, I have to extend it with the 'code' instead 'rowid') - if (isset($this->extralabels[$field])) $TParam['search'][$field] = $this->extrafields->showInputField($field, $this->search_array_options['search_options_'.$field], '', '', 'search_'); - $visible = 1; - } - - $TFieldVisibility[$field] = array( - 'label'=>$label - ,'checked'=>$visible - ); - } - } - else - { - foreach($TField as $field=>$dummy) - { - $label = isset($TParam['title'][$field]) ? $TParam['title'][$field] : $field; - $visible = (!in_array($field, $TParam['hide'])) ? 1 : 0; - $TFieldVisibility[$field]=array( - 'label'=>$label, - 'checked'=>$visible - ); - } - } - - $selectedfields = $this->form->multiSelectArrayWithCheckbox('Listview'.$this->id.'_selectedfields', $TFieldVisibility, $contextpage); // This also change content of $arrayfields_0 - } - - foreach ($TParam['title'] as $field => $label) - { - $visible = (!in_array($field, $TParam['hide'])) ? 1 : 0; - if($visible) - { - $THeader[$field] = array( - 'label'=>$label, - 'order'=>(in_array($field, $TParam['orderby']['noOrder']) ? 0 : 1), - 'width'=>(!empty($TParam['size']['width'][$field]) ? $TParam['size']['width'][$field] : 'auto'), - 'text-align'=>(!empty($TParam['position']['text-align'][$field]) ? $TParam['position']['text-align'][$field] : 'auto'), - 'rank'=>(!empty($TParam['position']['rank'][$field]) ? $TParam['position']['rank'][$field] : 0), - 'more'=>'' - ); - } - } - - uasort($THeader,array('Listview','sortHeaderRank')); - - $THeader['selectedfields']['label']=$selectedfields; - - return $THeader; - } - - public function sortHeaderRank(&$a, &$b) { - if($a['rank']>$b['rank']) return 1; - else if($a['rank']<$b['rank']) return -1; - else return 0; - - } - - /** - * @param string $TParam TParam - * @param string $line_number aaa - * @return bool - */ - private function in_view(&$TParam, $line_number) - { - global $conf; - - if(!empty($_REQUEST['get-all-for-export'])) return true; - - $page_number = !empty($TParam['limit']['page']) ? $TParam['limit']['page'] : 1; - $line_per_page = !empty($TParam['limit']['nbLine']) ? $TParam['limit']['nbLine'] : $conf->liste_limit; - - $start = ($page_number-1) * $line_per_page; - $end = ($page_number* $line_per_page) -1; - - if($line_number>=$start && $line_number<=$end) return true; - else return false; - } - - /** - * Apply function to result and set fields array - * - * @param string $THeader array of headers - * @param string $TField array of fields - * @param string $TParam array of parameters - * @param string $currentLine object containing current sql result - */ - private function set_line(&$THeader, &$TField, &$TParam, $currentLine) - { - global $conf; - - $line_number = count($TField); - - if($this->in_view($TParam,$line_number)) - { - $this->totalRowToShow++; - $row=array(); - $trans = array(); - foreach($currentLine as $kF=>$vF)$trans['@'.$kF.'@'] = addslashes($vF); - - foreach($THeader as $field=>$dummy) - { - $value = isset($currentLine->{$field}) ? $currentLine->{$field}: ''; - - if(is_object($value)) - { - if(get_class($value)=='stdClass') {$value=print_r($value, true);} - else $value=(string) $value; - } - - $trans['@'.$field.'@'] = addslashes($value); - - if(!empty($TParam['math'][$field])) - { - $float_value = (double) strip_tags($value); - $this->TTotalTmp[$field][] = $float_value; - } - - if(!in_array($field,$TParam['hide'])) - { - $row[$field]=$value; - - if(isset($TParam['eval'][$field]) && in_array($field,array_keys($row))) - { - $strToEval = 'return '.strtr( $TParam['eval'][$field], array_merge( $trans, array('@val@'=>addslashes( $row[$field] )) )).';'; - $row[$field] = eval($strToEval); - - } - - if(isset($TParam['type'][$field]) && !isset($TParam['eval'][$field])) - { - if($TParam['type'][$field]=='date' || $TParam['type'][$field]=='datetime' ) - { - - if($row[$field] != '0000-00-00 00:00:00' && $row[$field] != '1000-01-01 00:00:00' && $row[$field] != '0000-00-00' && !empty($row[$field])) - { - if($TParam['type'][$field]=='datetime')$row[$field] = dol_print_date(strtotime($row[$field]),'dayhour'); - else $row[$field] = dol_print_date(strtotime($row[$field]),'day'); - } - else - { - $row[$field] = ''; - } - } - - if($TParam['type'][$field]=='hour') { $row[$field] = date('H:i', strtotime($row[$field])); } - if($TParam['type'][$field]=='money') { $row[$field] = '
'.price($row[$field],0,'',1,-1,2).'
'; } - if($TParam['type'][$field]=='number') { $row[$field] = '
'.price($row[$field]).'
'; } - if($TParam['type'][$field]=='integer') { $row[$field] = '
'.((int) $row[$field]).'
'; } - } - - if(isset($TParam['link'][$field])) - { - if(empty($row[$field]) && $row[$field]!==0 && $row[$field]!=='0')$row[$field]='(vide)'; - $row[$field]= strtr( $TParam['link'][$field], array_merge( $trans, array('@val@'=>$row[$field]))) ; - } - - if(isset($TParam['translate'][$field])) - { - if(isset($TParam['translate'][$field][''])) unset($TParam['translate'][$field]['']); - - $row[$field] = strtr( $row[$field], $TParam['translate'][$field]); - } - } - } - } - else - { - $row = array(); - - foreach($currentLine as $field=>&$value) - { - if(!isset($this->THideFlip[$field])) - { - if(isset($TParam['math'][$field]) && !empty($TParam['math'][$field])) - { - $float_value = (double) strip_tags($value); - $this->TTotalTmp[$field][] = $float_value; - } - - $row[$field] = $value; - } - } - } - - if(!empty($TParam['math'][$field])) - { - foreach($row as $field=>$value) - { - if(!empty($TParam['math'][$field]) && is_array($TParam['math'][$field])) - { - $toField = $TParam['math'][$field][1]; - $float_value = (double) strip_tags($row[$toField]); - $this->TTotalTmp['@groupsum'][$toField][ $row[$field] ] += $float_value; - } - } - } - - $TField[] = $row; - } - - /** - * @param string $sql sql - * @param string $TParam TParam - * @return string - */ - private function limitSQL($sql, &$TParam) - { - if(!empty($TParam['limit']['global']) && strpos($sql,'LIMIT ')===false ) - { - $sql.=' LIMIT '.(int) $TParam['limit']['global']; - } - else if(!empty($TParam['limit'])) $sql.= $this->db->plimit($TParam['limit']['nbLine']+1, $TParam['limit']['page'] * $TParam['limit']['nbLine']); - - - return $sql; - } - - /** - * @param string $THeader THeader - * @param string $TField TField - * @param string $TParam TParam - * @param string $sql sql - */ - private function parse_sql(&$THeader, &$TField, &$TParam, $sql) - { - $this->sql = $this->limitSQL($sql, $TParam); - - $this->TTotalTmp=array(); - $this->THideFlip = array_flip($TParam['hide']); - - $res = $this->db->query($this->sql); - if($res!==false) - { - dol_syslog(get_class($this)."::parse_sql id=".$this->id." sql=".$this->sql, LOG_DEBUG); - - if(empty($this->totalRow))$this->totalRow = $this->db->num_rows($res); - - while($currentLine = $this->db->fetch_object($res)) - { - $this->set_line($THeader, $TField, $TParam, $currentLine); - } - } - else - { - dol_syslog(get_class($this)."::parse_sql id=".$this->id." sql=".$this->sql, LOG_ERR); - } - } - - static function getCachedOjbect($class_name, $fk_object) { - global $db, $TCacheListObject; - - if(!class_exists($class_name)) return false; - - if(empty($TCacheListObject)) $TCacheListObject = array(); - if(empty($TCacheListObject[$class_name])) $TCacheListObject[$class_name] =array(); - - if(empty($TCacheListObject[$class_name][$fk_object])) { - $TCacheListObject[$class_name][$fk_object]= new $class_name($db); - if( $TCacheListObject[$class_name][$fk_object]->fetch($fk_object)<0) { - return false; - } - } - - return $TCacheListObject[$class_name][$fk_object]; - } - -} diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 13793438a7b..0c8e4deca0b 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -609,7 +609,26 @@ else { foreach($extrafields->attribute_label as $key => $val) { - if (! empty($arrayfields["ef.".$key]['checked'])) print ''; + if (! empty($arrayfields["ef.".$key]['checked'])) { + $align=$extrafields->getAlignFlag($key); + $typeofextrafield=$extrafields->attribute_type[$key]; + print ''; + if (in_array($typeofextrafield, array('varchar', 'int', 'double', 'select')) && empty($extrafields->attribute_computed[$key])) + { + $crit=$val; + $tmpkey=preg_replace('/search_options_/','',$key); + $searchclass=''; + if (in_array($typeofextrafield, array('varchar', 'select'))) $searchclass='searchstring'; + if (in_array($typeofextrafield, array('int', 'double'))) $searchclass='searchnum'; + print ''; + } + else + { + // for the type as 'checkbox', 'chkbxlst', 'sellist' we should use code instead of id (example: I declare a 'chkbxlst' to have a link with dictionnairy, I have to extend it with the 'code' instead 'rowid') + echo $extrafields->showInputField($key, $search_array_options['search_options_'.$key], '', '', 'search_'); + } + print ''; + } } } // Fields from hook diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php index 1daff124764..db462411fe7 100644 --- a/htdocs/product/stock/product.php +++ b/htdocs/product/stock/product.php @@ -614,7 +614,7 @@ if ($id > 0 || $ref) } // Stock alert threshold - print ''.$form->editfieldkey("StockLimit",'seuil_stock_alerte',$object->seuil_stock_alerte,$object,$user->rights->produit->creer).''; + print ''.$form->editfieldkey($form->textwithpicto($langs->trans("StockLimit"), $langs->trans("StockLimitDesc"), 1),'seuil_stock_alerte',$object->seuil_stock_alerte,$object,$user->rights->produit->creer).''; print $form->editfieldval("StockLimit",'seuil_stock_alerte',$object->seuil_stock_alerte,$object,$user->rights->produit->creer,'string'); print ''; diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index 84050012a5a..af55063c66a 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -971,6 +971,7 @@ class Project extends CommonObject $label .= ($label?'
':'').'' . $langs->trans('DateEnd') . ': ' . dol_print_date($this->datee, 'day'); // The space must be after the : to not being explode when showing the title in img_picto if ($moreinpopup) $label.='
'.$moreinpopup; + $url=''; if ($option != 'nolink') { if (preg_match('/\.php$/',$option)) { @@ -1000,6 +1001,17 @@ class Project extends CommonObject } $linkclose.=' title="'.dol_escape_htmltag($label, 1).'"'; $linkclose.=' class="classfortooltip"'; + + if (! is_object($hookmanager)) { + include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; + $hookmanager=new HookManager($this->db); + } + $hookmanager->initHooks(array('projectdao')); + $parameters=array('id'=>$this->id); + // Note that $action and $object may have been modified by some hooks + $reshook=$hookmanager->executeHooks('getnomurltooltip',$parameters,$this,$action); + if ($reshook > 0) + $linkclose = $hookmanager->resPrint; } $picto = 'projectpub'; diff --git a/htdocs/public/websites/index.php b/htdocs/public/websites/index.php index 0bc85dce463..84e0a72f9fd 100644 --- a/htdocs/public/websites/index.php +++ b/htdocs/public/websites/index.php @@ -47,8 +47,9 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; $error=0; -$website=GETPOST('website', 'alpha'); +$websitekey=GETPOST('website', 'alpha'); $pageid=GETPOST('page', 'alpha')?GETPOST('page', 'alpha'):GETPOST('pageid', 'alpha'); +$pageref=GETPOST('pageref', 'aZ09')?GETPOST('pageref', 'aZ09'):''; $accessallowed = 1; $type=''; @@ -69,8 +70,9 @@ if (empty($pageid)) require_once DOL_DOCUMENT_ROOT.'/websites/class/websitepage.class.php'; $object=new Website($db); - $object->fetch(0, $website); - if (empty($object->id)) + $object->fetch(0, $websitekey); + + if (empty($object->id)) { if (empty($pageid)) { @@ -84,23 +86,34 @@ if (empty($pageid)) $objectpage=new WebsitePage($db); - if ($object->fk_default_home > 0) + if ($pageref) { - $result=$objectpage->fetch($object->fk_default_home); + $result=$objectpage->fetch(0, $object->id, $pageref); if ($result > 0) - { - $pageid = $objectpage->id; - } + { + $pageid = $objectpage->id; + } } - - if (empty($pageid)) + else { - $array=$objectpage->fetchAll($object->id); - if (is_array($array) && count($array) > 0) - { - $firstrep=reset($array); - $pageid=$firstrep->id; - } + if ($object->fk_default_home > 0) + { + $result=$objectpage->fetch($object->fk_default_home); + if ($result > 0) + { + $pageid = $objectpage->id; + } + } + + if (empty($pageid)) + { + $array=$objectpage->fetchAll($object->id); + if (is_array($array) && count($array) > 0) + { + $firstrep=reset($array); + $pageid=$firstrep->id; + } + } } } if (empty($pageid)) @@ -125,11 +138,11 @@ if ($pageid == 'css') // No more used ? //if (empty($dolibarr_nocache)) header('Cache-Control: max-age=3600, public, must-revalidate'); //else header('Cache-Control: no-cache'); - $original_file=$dolibarr_main_data_root.'/websites/'.$website.'/styles.css.php'; + $original_file=$dolibarr_main_data_root.'/websites/'.$websitekey.'/styles.css.php'; } else { - $original_file=$dolibarr_main_data_root.'/websites/'.$website.'/page'.$pageid.'.tpl.php'; + $original_file=$dolibarr_main_data_root.'/websites/'.$websitekey.'/page'.$pageid.'.tpl.php'; } // Find the subdirectory name as the reference @@ -177,7 +190,7 @@ if (! file_exists($original_file_osencoded)) // Output page content define('USEDOLIBARRSERVER', 1); -print "\n".''."\n"; +print ''."\n"; include_once $original_file_osencoded; diff --git a/htdocs/societe/rib.php b/htdocs/societe/rib.php index 7385b466e34..97ae92e4044 100644 --- a/htdocs/societe/rib.php +++ b/htdocs/societe/rib.php @@ -204,7 +204,8 @@ if (empty($reshook)) $account->proprio = GETPOST('proprio','alpha'); $account->owner_address = GETPOST('owner_address','alpha'); $account->frstrecur = GETPOST('frstrecur'); - + $account->rum = GETPOST('rum','alpha'); + // This test can be done only once properties were set if ($account->needIBAN() == 1) { @@ -868,7 +869,7 @@ if ($socid && $action == 'create' && $user->rights->societe->creer) // RUM print ''.$langs->trans("RUM").''; - print ''.$langs->trans("RUMWillBeGenerated").''; + print '
'.$langs->trans("RUMWillBeGenerated").''; print ''.$langs->trans("WithdrawMode").''; $tblArraychoice = array("FRST" => $langs->trans("FRST"), "RECUR" => $langs->trans("RECUR")); diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index a42ed7bf6a0..06015d69a2b 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -3353,6 +3353,11 @@ a.websitebuttonsitepreview img { a.websitebuttonsitepreviewdisabled img { opacity: 0.2; } +.websitehelp { + vertical-align: middle; + float: right; + padding-top: 8px; +} /* ============================================================================== */ diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 4a396fadc7b..11fd6b9650a 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -3428,10 +3428,17 @@ a.websitebuttonsitepreview img { width: 26px; display: inline-block; } +a.websitebuttonsitepreviewdisabled img { + opacity: 0.2; +} .websiteiframenoborder { border: 0px; } - +.websitehelp { + vertical-align: middle; + float: right; + padding-top: 8px; +} /* ============================================================================== */ /* Module agenda */ diff --git a/htdocs/user/logout.php b/htdocs/user/logout.php index 37ff691fdcc..4421c6d6298 100644 --- a/htdocs/user/logout.php +++ b/htdocs/user/logout.php @@ -50,13 +50,6 @@ if ($result < 0) { $error++; } // Define url to go after disconnect $urlfrom=empty($_SESSION["urlfrom"])?'':$_SESSION["urlfrom"]; -// Destroy some cookies -// TODO external module -if (! empty($conf->phenix->enabled) && ! empty($conf->phenix->cookie)) -{ - setcookie($conf->phenix->cookie, '', 1, "/"); -} - // Define url to go $url=DOL_URL_ROOT."/index.php"; // By default go to login page if ($urlfrom) $url=DOL_URL_ROOT.$urlfrom; diff --git a/htdocs/websites/class/website.class.php b/htdocs/websites/class/website.class.php index 167e186e124..d7cb1559982 100644 --- a/htdocs/websites/class/website.class.php +++ b/htdocs/websites/class/website.class.php @@ -48,11 +48,6 @@ class Website extends CommonObject */ public $table_element = 'website'; - /** - * @var WebsitePage[] Lines of all pages - */ - public $lines = array(); - /** * @var int */ @@ -87,12 +82,6 @@ class Website extends CommonObject public $virtualhost; - public $records; - - /** - */ - - /** * Constructor * @@ -146,8 +135,8 @@ class Website extends CommonObject $sql.= 'status,'; $sql.= 'fk_default_home,'; $sql.= 'virtualhost,'; - $sql.= 'fk_user_create'; - $sql.= 'date_creation'; + $sql.= 'fk_user_create,'; + $sql.= 'date_creation,'; $sql.= 'tmps'; $sql .= ') VALUES ('; $sql .= ' '.(! isset($this->entity)?'NULL':$this->entity).','; @@ -219,10 +208,10 @@ class Website extends CommonObject $sql .= " t.fk_user_create,"; $sql .= " t.fk_user_modif,"; $sql .= " t.date_creation,"; - $sql .= " t.tms"; + $sql .= " t.tms as date_modification"; $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t'; if (null !== $ref) { - $sql .= ' WHERE t.ref = ' . '\'' . $ref . '\''; + $sql .= " WHERE t.ref = '" . $this->db->escape($ref) . "'"; } else { $sql .= ' WHERE t.rowid = ' . $id; } @@ -244,7 +233,7 @@ class Website extends CommonObject $this->fk_user_create = $obj->fk_user_create; $this->fk_user_modif = $obj->fk_user_modif; $this->date_creation = $this->db->jdate($obj->date_creation); - $this->tms = $this->db->jdate($obj->tms); + $this->date_modification = $this->db->jdate($obj->date_modification); } $this->db->free($resql); @@ -288,7 +277,7 @@ class Website extends CommonObject $sql .= " t.fk_user_create,"; $sql .= " t.fk_user_modif,"; $sql .= " t.date_creation,"; - $sql .= " t.tms"; + $sql .= " t.tms as date_modification"; $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element. ' as t'; // Manage filter @@ -328,7 +317,7 @@ class Website extends CommonObject $this->fk_user_create = $obj->fk_user_create; $this->fk_user_modif = $obj->fk_user_modif; $line->date_creation = $this->db->jdate($obj->date_creation); - $line->tms = $this->db->jdate($obj->tms); + $line->date_modification = $this->db->jdate($obj->date_modification); $this->records[$line->id] = $line; } @@ -384,8 +373,8 @@ class Website extends CommonObject $sql .= ' fk_default_home = '.(($this->fk_default_home > 0)?$this->fk_default_home:"null").','; $sql .= ' virtualhost = '.(($this->virtualhost != '')?"'".$this->db->escape($this->virtualhost)."'":"null").','; $sql .= ' fk_user_modif = '.(! isset($this->fk_user_modif) ? $user->id : $this->fk_user_modif).','; - $sql .= ' date_creation = '.(! isset($this->date_creation) || dol_strlen($this->date_creation) != 0 ? "'".$this->db->idate($this->date_creation)."'" : 'null').','; - $sql .= ' tms = '.(dol_strlen($this->tms) != 0 ? "'".$this->db->idate($this->tms)."'" : "'".$this->db->idate(dol_now())."'"); + $sql .= ' date_creation = '.(! isset($this->date_creation) || dol_strlen($this->date_creation) != 0 ? "'".$this->db->idate($this->date_creation)."'" : 'null'); + $sql .= ', tms = '.(dol_strlen($this->date_modification) != 0 ? "'".$this->db->idate($this->date_modification)."'" : "'".$this->db->idate(dol_now())."'"); $sql .= ' WHERE rowid=' . $this->id; $this->db->begin(); diff --git a/htdocs/websites/class/websitepage.class.php b/htdocs/websites/class/websitepage.class.php index 77e5d5862ec..7d5e59830e1 100644 --- a/htdocs/websites/class/websitepage.class.php +++ b/htdocs/websites/class/websitepage.class.php @@ -127,6 +127,8 @@ class WebsitePage extends CommonObject $sql.= 'description,'; $sql.= 'keywords,'; $sql.= 'content,'; + $sql.= 'lang,'; + $sql.= 'fk_page,'; $sql.= 'status,'; $sql.= 'date_creation,'; $sql.= 'tms'; @@ -137,6 +139,8 @@ class WebsitePage extends CommonObject $sql .= ' '.(! isset($this->description)?'NULL':"'".$this->db->escape($this->description)."'").','; $sql .= ' '.(! isset($this->keywords)?'NULL':"'".$this->db->escape($this->keywords)."'").','; $sql .= ' '.(! isset($this->content)?'NULL':"'".$this->db->escape($this->content)."'").','; + $sql .= ' '.(! isset($this->lang)?'NULL':"'".$this->db->escape($this->lang)."'").','; + $sql .= ' '.(empty($this->fk_page)?'NULL':$this->db->escape($this->fk_page)).','; $sql .= ' '.(! isset($this->status)?'NULL':$this->status).','; $sql .= ' '.(! isset($this->date_creation) || dol_strlen($this->date_creation)==0?'NULL':"'".$this->db->idate($this->date_creation)."'").','; $sql .= ' '.(! isset($this->date_modification) || dol_strlen($this->date_modification)==0?'NULL':"'".$this->db->idate($this->date_modification)."'"); @@ -181,9 +185,9 @@ class WebsitePage extends CommonObject /** * Load object in memory from the database * - * @param int $id Id object. If this is 0, the default page of website_id will be used, if not defined, the first one. found - * @param string $website_id Web site id - * @param string $page Page name + * @param int $id Id object. If this is 0, the default page of website_id will be used, if not defined, the first one found. + * @param string $website_id Web site id (page name must also be filled if this parameter is used) + * @param string $page Page name (website id must also be filled if this parameter is used) * * @return int <0 if KO, 0 if not found, >0 if OK */ @@ -199,18 +203,25 @@ class WebsitePage extends CommonObject $sql .= " t.description,"; $sql .= " t.keywords,"; $sql .= " t.content,"; + $sql .= " t.lang,"; + $sql .= " t.fk_page,"; $sql .= " t.status,"; $sql .= " t.date_creation,"; $sql .= " t.tms as date_modification"; $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t'; //$sql .= ' WHERE entity IN ('.getEntity('website').')'; // entity is on website level $sql .= ' WHERE 1 = 1'; - if (null !== $website_id) { - $sql .= " AND t.fk_website = '" . $this->db->escape($website_id) . "'"; - if ($page) $sql .= " AND t.pageurl = '" . $this->db->escape($page) . "'"; - } else { + if ($id > 0) + { $sql .= ' AND t.rowid = ' . $id; } + else + { + if (null !== $website_id) { + $sql .= " AND t.fk_website = '" . $this->db->escape($website_id) . "'"; + if ($page) $sql .= " AND t.pageurl = '" . $this->db->escape($page) . "'"; + } + } $sql .= $this->db->plimit(1); $resql = $this->db->query($sql); @@ -227,6 +238,8 @@ class WebsitePage extends CommonObject $this->description = $obj->description; $this->keywords = $obj->keywords; $this->content = $obj->content; + $this->lang = $obj->lang; + $this->fk_page = $obj->fk_page; $this->status = $obj->status; $this->date_creation = $this->db->jdate($obj->date_creation); $this->date_modification = $this->db->jdate($obj->date_modification); @@ -272,6 +285,8 @@ class WebsitePage extends CommonObject $sql .= " t.description,"; $sql .= " t.keywords,"; $sql .= " t.content,"; + $sql .= " t.lang,"; + $sql .= " t.fk_page,"; $sql .= " t.status,"; $sql .= " t.date_creation,"; $sql .= " t.tms as date_modification"; @@ -314,6 +329,8 @@ class WebsitePage extends CommonObject $record->description = $obj->description; $record->keywords = $obj->keywords; $record->content = $obj->content; + $record->lang = $obj->lang; + $record->fk_page = $obj->fk_page; $record->status = $obj->status; $record->date_creation = $this->db->jdate($obj->date_creation); $record->date_modification = $this->db->jdate($obj->date_modification); @@ -380,9 +397,11 @@ class WebsitePage extends CommonObject $sql .= ' description = '.(isset($this->description)?"'".$this->db->escape($this->description)."'":"null").','; $sql .= ' keywords = '.(isset($this->keywords)?"'".$this->db->escape($this->keywords)."'":"null").','; $sql .= ' content = '.(isset($this->content)?"'".$this->db->escape($this->content)."'":"null").','; + $sql .= ' lang = '.(isset($this->lang)?"'".$this->db->escape($this->lang)."'":"null").','; + $sql .= ' fk_page = '.(empty($this->fk_page)?"null":$this->db->escape($this->fk_page)).','; $sql .= ' status = '.(isset($this->status)?$this->status:"null").','; - $sql .= ' date_creation = '.(! isset($this->date_creation) || dol_strlen($this->date_creation) != 0 ? "'".$this->db->idate($this->date_creation)."'" : 'null').','; - //$sql .= ' tms = '.(dol_strlen($this->date_modification) != 0 ? "'".$this->db->idate($this->date_modification)."'" : "'".$this->db->idate(dol_now())."'"); + $sql .= ' date_creation = '.(! isset($this->date_creation) || dol_strlen($this->date_creation) != 0 ? "'".$this->db->idate($this->date_creation)."'" : 'null'); + $sql .= ', tms = '.(dol_strlen($this->date_modification) != 0 ? "'".$this->db->idate($this->date_modification)."'" : "'".$this->db->idate(dol_now())."'"); $sql .= ' WHERE rowid=' . $this->id; $this->db->begin(); @@ -477,17 +496,21 @@ class WebsitePage extends CommonObject /** * Load an object from its id and create a new one in database * - * @param int $fromid Id of object to clone - * - * @return int New id of clone + * @param int $fromid Id of object to clone + * @param string $newref New ref/alias of page + * @param string $newlang New language + * @param int $istranslation 1=New page is a translation of the cloned page. + * @param int $newwebsite 0=Same web site, 1=New web site + * @return int New id of clone */ - public function createFromClone($fromid) + public function createFromClone($fromid, $newref, $newlang='', $istranslation=0, $newwebsite=0) { + global $user, $langs; + dol_syslog(__METHOD__, LOG_DEBUG); - global $user; $error = 0; - $object = new Websitepage($this->db); + $object = new self($this->db); $this->db->begin(); @@ -497,14 +520,21 @@ class WebsitePage extends CommonObject $object->id = 0; // Clear fields - // ... + $object->ref = $newref; + $object->pageurl = $newref; + $object->title = $langs->trans("CopyOf").' '.$object->title; + if (! empty($newlang)) $object->lang=$newlang; + if ($istranslation) $object->fk_page = $fromid; + else $object->fk_page = 0; + if (! empty($newwebsite)) $object->fk_website=$newwebsite; // Create clone $result = $object->create($user); // Other options if ($result < 0) { - $error ++; + $error++; + $this->error = $object->error; $this->errors = $object->errors; dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR); } @@ -517,7 +547,7 @@ class WebsitePage extends CommonObject } else { $this->db->rollback(); - return - 1; + return -1; } } diff --git a/htdocs/websites/index.php b/htdocs/websites/index.php index 874679892d5..0f1e813e3ed 100644 --- a/htdocs/websites/index.php +++ b/htdocs/websites/index.php @@ -66,11 +66,12 @@ function llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, } - require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formwebsite.class.php'; require_once DOL_DOCUMENT_ROOT.'/websites/class/website.class.php'; require_once DOL_DOCUMENT_ROOT.'/websites/class/websitepage.class.php'; @@ -89,6 +90,7 @@ $error=0; $website=GETPOST('website', 'alpha'); $page=GETPOST('page', 'alpha'); $pageid=GETPOST('pageid', 'int'); +$pageref=GETPOST('pageref', 'aZ09'); $action=GETPOST('action','alpha'); if (GETPOST('delete')) { $action='delete'; } @@ -99,7 +101,10 @@ if (GETPOST('editcss')) { $action='editcss'; } if (GETPOST('editmenu')) { $action='editmenu'; } if (GETPOST('setashome')) { $action='setashome'; } if (GETPOST('editmeta')) { $action='editmeta'; } +if (GETPOST('editsource')) { $action='editsource'; } if (GETPOST('editcontent')) { $action='editcontent'; } +if (GETPOST('createfromclone')) { $action='createfromclone'; } +if (GETPOST('createpagefromclone')) { $action='createpagefromclone'; } if (empty($action)) $action='preview'; @@ -123,15 +128,18 @@ if ($website) } if ($pageid < 0) $pageid = 0; -if ($pageid > 0 && $action != 'add') +if (($pageid > 0 || $pageref) && $action != 'add') { - $res = $objectpage->fetch($pageid); + $res = $objectpage->fetch($pageid, ($object->id > 0 ? $object->id : null), $pageref); + $pageid = $objectpage->id; } global $dolibarr_main_data_root; $pathofwebsite=$dolibarr_main_data_root.'/websites/'.$website; -$filehtmlheader=$pathofwebsite.'/header.html'; +$filehtmlheader=$pathofwebsite.'/htmlheader.html'; $filecss=$pathofwebsite.'/styles.css.php'; +$filerobot=$pathofwebsite.'/robots.txt'; +$filehtaccess=$pathofwebsite.'/.htaccess'; $filetpl=$pathofwebsite.'/page'.$pageid.'.tpl.php'; $fileindex=$pathofwebsite.'/index.php'; @@ -159,7 +167,8 @@ if ($action == 'add') $objectpage->title = GETPOST('WEBSITE_TITLE'); $objectpage->pageurl = GETPOST('WEBSITE_PAGENAME'); $objectpage->description = GETPOST('WEBSITE_DESCRIPTION'); - $objectpage->keywords = GETPOST('WEBSITE_KEYWORD'); + $objectpage->keywords = GETPOST('WEBSITE_KEYWORDS'); + $objectpage->lang = GETPOST('WEBSITE_LANG'); if (empty($objectpage->pageurl)) { @@ -167,6 +176,12 @@ if ($action == 'add') $error++; $action='create'; } + else if (! preg_match('/^[a-z0-9\-\_]+$/i', $objectpage->pageurl)) + { + setEventMessages($langs->transnoentities("ErrorFieldCanNotContainSpecialCharacters", $langs->transnoentities('WEBSITE_PAGENAME')), null, 'errors'); + $error++; + $action='create'; + } if (empty($objectpage->title)) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("WEBSITE_TITLE")), null, 'errors'); @@ -250,10 +265,22 @@ if ($action == 'updatecss') $res = $object->fetch(0, $website); // Html header file - $htmlheadercontent = ''."\n"; - $htmlheadercontent.= ''."\n"; - $htmlheadercontent.= ''."\n"; - $htmlheadercontent.= GETPOST('WEBSITE_HTML_HEADER'); + $htmlheadercontent =''; + + $htmlheadercontent.= "\n"; + + $htmlheadercontent.= preg_replace(array('/\n*/ims','/<\/html>\n*/ims'),array('',''),GETPOST('WEBSITE_HTML_HEADER')); + + $htmlheadercontent.= "\n".'"."\n"; dol_syslog("Save file css into ".$filehtmlheader); @@ -269,14 +296,23 @@ if ($action == 'updatecss') } // Css file - $csscontent = ''."\n"; - $csscontent.= ''."\n"; - $csscontent.= '"."\n"; - $csscontent.= ''."\n"; + $csscontent.= "// END PHP ?>\n"; + $csscontent.= GETPOST('WEBSITE_CSS_INLINE'); + $csscontent.= "\n".'"."\n"; + dol_syslog("Save file css into ".$filecss); dol_mkdir($pathofwebsite); @@ -291,6 +327,70 @@ if ($action == 'updatecss') } + // Css file + $robotcontent =''; + + /*$robotcontent.= "\n";*/ + + $robotcontent.= GETPOST('WEBSITE_ROBOT'); + + /*$robotcontent.= "\n".'"."\n";*/ + + dol_syslog("Save file robot into ".$filerobot); + + dol_mkdir($pathofwebsite); + $result = file_put_contents($filerobot, $robotcontent); + if (! empty($conf->global->MAIN_UMASK)) + @chmod($filerobot, octdec($conf->global->MAIN_UMASK)); + + if (! $result) + { + $error++; + setEventMessages('Failed to write file '.$filerobot, null, 'errors'); + } + + + // Css file + $htaccesscontent =''; + + /*$robotcontent.= "\n";*/ + + $htaccesscontent.= GETPOST('WEBSITE_HTACCESS'); + + /*$robotcontent.= "\n".'"."\n";*/ + + dol_syslog("Save file htaccess into ".$filehtaccess); + + dol_mkdir($pathofwebsite); + $result = file_put_contents($filehtaccess, $htaccesscontent); + if (! empty($conf->global->MAIN_UMASK)) + @chmod($filehtaccess, octdec($conf->global->MAIN_UMASK)); + + if (! $result) + { + $error++; + setEventMessages('Failed to write file '.$filehtaccess, null, 'errors'); + } + + // Message if no error if (! $error) { setEventMessages($langs->trans("Saved"), null, 'mesgs'); @@ -350,8 +450,22 @@ if ($action == 'updatemeta') $objectpage->fk_website = $object->id; + // Check parameters + if (! preg_match('/^[a-z0-9\-\_]+$/i', $objectpage->pageurl)) + { + $error++; + setEventMessages($langs->transnoentities("ErrorFieldCanNotContainSpecialCharacters", $langs->transnoentities('WEBSITE_PAGENAME')), null, 'errors'); + $action='editmeta'; + } + $res = $objectpage->fetch($pageid, $object->fk_website); - if ($res > 0) + if ($res <= 0) + { + $error++; + dol_print_error($db, 'Page not found'); + } + + if (! $error) { $objectpage->old_object = clone $objectpage; @@ -359,6 +473,7 @@ if ($action == 'updatemeta') $objectpage->title = GETPOST('WEBSITE_TITLE'); $objectpage->description = GETPOST('WEBSITE_DESCRIPTION'); $objectpage->keywords = GETPOST('WEBSITE_KEYWORDS'); + $objectpage->lang = GETPOST('WEBSITE_LANG'); $res = $objectpage->update($user); if (! $res > 0) @@ -379,12 +494,14 @@ if ($action == 'updatemeta') // Now generate the master.inc.php page - dol_syslog("We regenerate the master file"); + dol_syslog("We regenerate the master file (because we update meta)"); dol_delete_file($filemaster); $mastercontent = ''."\n"; $result = file_put_contents($filemaster, $mastercontent); if (! empty($conf->global->MAIN_UMASK)) @@ -400,44 +517,60 @@ if ($action == 'updatemeta') dol_delete_file($fileoldalias); } - $aliascontent = 'id.".tpl.php';\n"; - $aliascontent.= '?>'."\n"; - $result = file_put_contents($filealias, $aliascontent); + $aliascontent = 'id.'.tpl.php\';'; + $aliascontent.= 'else require $dolibarr_main_data_root.\'/websites/\'.$website->ref.\'/page'.$objectpage->id.'.tpl.php\';'."\n"; + $aliascontent.= '?>'."\n"; + $result = file_put_contents($filealias, $aliascontent); if (! empty($conf->global->MAIN_UMASK)) @chmod($filealias, octdec($conf->global->MAIN_UMASK)); if (! $result) setEventMessages('Failed to write file '.$filealias, null, 'errors'); - // Now create the .tpl file (duplicate code with actions updatecontent but we need this to save new header) + // Now create the .tpl file (duplicate code with actions updatesource or updatecontent but we need this to save new header) dol_syslog("We regenerate the tpl page filetpl=".$filetpl); dol_delete_file($filetpl); + // TODO Same code than into updatesource updatecontent $tplcontent =''; - $tplcontent.= ''."\n"; + $tplcontent.= "\n"; $tplcontent.= ''."\n"; $tplcontent.= '
'."\n"; - $tplcontent.= ''.dol_escape_htmltag($objectpage->title).''."\n"; + $tplcontent.= ''.dol_string_nohtmltag($objectpage->title, 0, 'UTF-8').''."\n"; + $tplcontent.= ''."\n"; $tplcontent.= ''."\n"; $tplcontent.= ''."\n"; $tplcontent.= ''."\n"; $tplcontent.= ''."\n"; $tplcontent.= ''."\n"; - $tplcontent.= ''."\n"; - $tplcontent.= ''."\n"; - $tplcontent.= ''."\n"; + $tplcontent.= ''."\n"; + $tplcontent.= ''."\n"; + $tplcontent.= ''."\n"; $tplcontent.= ''."\n"; $tplcontent.= ''."\n"; - $tplcontent.= ''."\n"; - $tplcontent.= 'ref.'/header.html"); ?>'."\n"; + $tplcontent.= ''."\n"; + $tplcontent.= 'ref.'/htmlheader.html"); ?>'."\n"; $tplcontent.= '
'."\n"; - $tplcontent.= ''."\n"; + $tplcontent.= ''."\n"; + $tplcontent.= ''."\n"; $tplcontent.= $objectpage->content."\n"; $tplcontent.= ''."\n"; + + $tplcontent.= '"."\n"; + //var_dump($filetpl);exit; $result = file_put_contents($filetpl, $tplcontent); if (! empty($conf->global->MAIN_UMASK)) @@ -458,55 +591,83 @@ if ($action == 'updatemeta') $db->rollback(); } } - else - { - dol_print_error($db, 'Page not found'); - } } // Update page -if ($action == 'updatecontent' || ($action == 'preview' && (GETPOST('refreshsite') || GETPOST('refreshpage') || GETPOST('preview')))) +if (($action == 'updatesource' || $action == 'updatecontent' || $action == 'confirm_createpagefromclone') + || ($action == 'preview' && (GETPOST('refreshsite') || GETPOST('refreshpage') || GETPOST('preview')))) { $object->fetch(0, $website); - // Check symlink to medias and restore it if ko - $pathtomedias=DOL_DATA_ROOT.'/medias'; - $pathtomediasinwebsite=$pathofwebsite.'/medias'; - if (! is_link(dol_osencode($pathtomediasinwebsite))) - { - dol_syslog("Create symlink for ".$pathtomedias." into name ".$pathtomediasinwebsite); - dol_mkdir(dirname($pathtomediasinwebsite)); // To be sure dir for website exists - $result = symlink($pathtomedias, $pathtomediasinwebsite); + if ($action == 'confirm_createpagefromclone') + { + $istranslation=(GETPOST('is_a_translation','aZ09')=='on'?1:0); + if ($istranslation) + { + if (GETPOST('newlang','aZ09') == $objectpage->lang) + { + $error++; + setEventMessages($langs->trans("LanguageMustNotBeSameThanClonedPage"), null, 'errors'); + $action='preview'; + } + } + + if (! $error) + { + $objectpage = new WebsitePage($db); + $result = $objectpage->createFromClone($pageid, GETPOST('pageurl','aZ09'), (GETPOST('newlang','aZ09')?GETPOST('newlang','aZ09'):''), $istranslation, GETPOST('newwebsite','int')); + if ($result < 0) + { + $error++; + setEventMessages($objectpage->error, $objectpage->errors, 'errors'); + $action='createpagefromclone'; + } + } } - /*if (GETPOST('savevirtualhost') && $object->virtualhost != GETPOST('previewsite')) - { - $object->virtualhost = GETPOST('previewsite', 'alpha'); - $object->update($user); - }*/ + $res = 0; - $objectpage->fk_website = $object->id; + if (! $error) + { + // Check symlink to medias and restore it if ko + $pathtomedias=DOL_DATA_ROOT.'/medias'; + $pathtomediasinwebsite=$pathofwebsite.'/medias'; + if (! is_link(dol_osencode($pathtomediasinwebsite))) + { + dol_syslog("Create symlink for ".$pathtomedias." into name ".$pathtomediasinwebsite); + dol_mkdir(dirname($pathtomediasinwebsite)); // To be sure dir for website exists + $result = symlink($pathtomedias, $pathtomediasinwebsite); + } - if ($pageid > 0) - { - $res = $objectpage->fetch($pageid); - } - else - { - $res=0; - if ($object->fk_default_home > 0) - { - $res = $objectpage->fetch($object->fk_default_home); - } - if (! ($res > 0)) - { - $res = $objectpage->fetch(0, $object->id); - } + /*if (GETPOST('savevirtualhost') && $object->virtualhost != GETPOST('previewsite')) + { + $object->virtualhost = GETPOST('previewsite', 'alpha'); + $object->update($user); + }*/ + + $objectpage->fk_website = $object->id; + + if ($pageid > 0) + { + $res = $objectpage->fetch($pageid); + } + else + { + $res=0; + if ($object->fk_default_home > 0) + { + $res = $objectpage->fetch($object->fk_default_home); + } + if (! ($res > 0)) + { + $res = $objectpage->fetch(0, $object->id); + } + } } - if ($res > 0) + if (! $error && $res > 0) { - if ($action == 'updatecontent') + if ($action == 'updatesource' || $action == 'updatecontent') { $db->begin(); @@ -540,7 +701,7 @@ if ($action == 'updatecontent' || ($action == 'preview' && (GETPOST('refreshsite $mastercontent = ''."\n"; $result = file_put_contents($filemaster, $mastercontent); if (! empty($conf->global->MAIN_UMASK)) @@ -558,7 +719,9 @@ if ($action == 'updatecontent' || ($action == 'preview' && (GETPOST('refreshsite $aliascontent = 'id.".tpl.php';\n"; + $aliascontent.= 'global $dolibarr_main_data_root;'."\n"; + $aliascontent.= 'if (empty($dolibarr_main_data_root)) require \'./page'.$objectpage->id.'.tpl.php\';'; + $aliascontent.= 'else require $dolibarr_main_data_root.\'/websites/\'.$website->ref.\'/page'.$objectpage->id.'.tpl.php\';'."\n"; $aliascontent.= '?>'."\n"; $result = file_put_contents($filealias, $aliascontent); if (! empty($conf->global->MAIN_UMASK)) @@ -570,29 +733,34 @@ if ($action == 'updatecontent' || ($action == 'preview' && (GETPOST('refreshsite // Now create the .tpl file with code to be able to make dynamic changes dol_delete_file($filetpl); - $tplcontent =''; + // TODO Same code than into updatemeta + $tplcontent =''; $tplcontent.= "\n"; $tplcontent.= ''."\n"; $tplcontent.= '
'."\n"; - $tplcontent.= ''.dol_escape_htmltag($objectpage->title).''."\n"; + $tplcontent.= ''.dol_string_nohtmltag($objectpage->title, 0, 'UTF-8').''."\n"; + $tplcontent.= ''."\n"; $tplcontent.= ''."\n"; $tplcontent.= ''."\n"; $tplcontent.= ''."\n"; $tplcontent.= ''."\n"; - $tplcontent.= ''."\n"; - $tplcontent.= ''."\n"; - $tplcontent.= ''."\n"; + $tplcontent.= ''."\n"; + $tplcontent.= ''."\n"; + $tplcontent.= ''."\n"; $tplcontent.= ''."\n"; $tplcontent.= ''."\n"; - $tplcontent.= ''."\n"; - $tplcontent.= 'ref.'/header.html"); ?>'."\n"; + $tplcontent.= ''."\n"; + $tplcontent.= 'ref.'/htmlheader.html"); ?>'."\n"; $tplcontent.= '
'."\n"; - $tplcontent.= ''."\n"; + $tplcontent.= ''."\n"; + $tplcontent.= ''."\n"; $tplcontent.= $objectpage->content."\n"; $tplcontent.= ''."\n"; @@ -631,7 +799,7 @@ if ($action == 'updatecontent' || ($action == 'preview' && (GETPOST('refreshsite } else { - setEventMessages($langs->trans("NoPageYet"), null, 'warnings'); + if (! $error) setEventMessages($langs->trans("NoPageYet"), null, 'warnings'); } } @@ -642,6 +810,8 @@ if ($action == 'updatecontent' || ($action == 'preview' && (GETPOST('refreshsite */ $form = new Form($db); +$formadmin = new FormAdmin($db); +$formwebsite = new FormWebsite($db); $help_url=''; @@ -675,6 +845,10 @@ if ($action == 'editmeta') { print ''; } +if ($action == 'editsource') +{ + print ''; +} if ($action == 'editcontent') { print ''; @@ -687,7 +861,7 @@ if ($action == 'edit') // Add a margin under toolbar ? $style=''; -if ($action != 'preview' && $action != 'editcontent') $style=' margin-bottom: 5px;'; +if ($action != 'preview' && $action != 'editcontent' && $action != 'editsource') $style=' margin-bottom: 5px;'; //var_dump($objectpage);exit; print '
'; @@ -740,7 +914,7 @@ if (count($object->records) > 0) //print ''; print ''; print ''; - print ''; + //print ''; } print '
'; @@ -759,7 +933,7 @@ if (count($object->records) > 0) $urlext=$virtualurl; $urlint=$urlwithroot.'/public/websites/index.php?website='.$website; - print 'transnoentitiesnoconv("Site"), $langs->transnoentitiesnoconv("Site"), $dataroot, $urlext)).'">'; + print 'transnoentitiesnoconv("Site"), $langs->transnoentitiesnoconv("Site"), $dataroot, $urlext)).'">'; print $form->textwithpicto('', $langs->trans("PreviewSiteServedByWebServer", $langs->transnoentitiesnoconv("Site"), $langs->transnoentitiesnoconv("Site"), $dataroot, $urlext?$urlext:''.$langs->trans("VirtualHostUrlNotDefined").''), 1, 'preview_ext'); print ''; @@ -789,6 +963,11 @@ if (count($object->records) > 0) $atleastonepage=(is_array($array) && count($array) > 0); print '
'; + + print '
'; + print ''; + print '
'; + print '
'; print $langs->trans("Page").': '; print '
'; @@ -797,7 +976,7 @@ if (count($object->records) > 0) if ($action != 'add') { $out=''; - $out.=''; if ($atleastonepage) { if (empty($pageid) && $action != 'create') // Page id is not defined, we try to take one @@ -816,7 +995,7 @@ if (count($object->records) > 0) $out.=''; } @@ -832,52 +1011,63 @@ if (count($object->records) > 0) } print ''; - //print $form->selectarray('page', $array); - if ($action == 'preview') + if ($action == 'preview' || $action == 'createpagefromclone') { $disabled=''; if (empty($user->rights->websites->write)) $disabled=' disabled="disabled"'; if ($pageid > 0) { + // Confirmation to delete + if ($action == 'createpagefromclone') { + // Create an array for form + $formquestion = array( + array('type' => 'text', 'name' => 'pageurl', 'label'=> $langs->trans("WEBSITE_PAGENAME") ,'value'=> 'copy_of_'.$objectpage->pageurl), + array('type' => 'checkbox', 'name' => 'is_a_translation', 'label' => $langs->trans("PageIsANewTranslation"), 'value' => 0), + array('type' => 'other','name' => 'newlang','label' => $langs->trans("Language"), 'value' => $formadmin->select_language(GETPOST('newlang', 'az09')?GETPOST('newlang', 'az09'):$langs->defaultlang, 'newlang', 0, null, '', 0, 0, 'minwidth200')), + array('type' => 'other','name' => 'newwebsite','label' => $langs->trans("Website"), 'value' => $formwebsite->selectWebsite($object->id, 'newwebsite', 0)) + ); + + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?pageid=' . $pageid, $langs->trans('ClonePage'), '', 'confirm_createpagefromclone', $formquestion, 0, 1, 250); + + print $formconfirm; + } + print '   '; + print ''; + print ''; + print ''; if ($object->fk_default_home > 0 && $pageid == $object->fk_default_home) print ''; else print ''; - print ''; - print ''; - //print ''.dol_escape_htmltag($langs->trans("EditPageMeta")).''; - //print ''.dol_escape_htmltag($langs->trans("EditPageContent")).''; + print ''; print ''; } } - print '
'; - print '
'; print '
'; print '
'; - if ($website && $pageid > 0 && $action == 'preview') + if ($website && $pageid > 0 && ($action == 'preview' || $action == 'createpagefromclone')) { $websitepage = new WebSitePage($db); $websitepage->fetch($pageid); - $realpage=$urlwithroot.'/public/websites/index.php?website='.$website.'&page='.$pageid; + $realpage=$urlwithroot.'/public/websites/index.php?website='.$website.'&pageref='.$websitepage->pageurl; $pagealias = $websitepage->pageurl; print '
'; print ''; - //print ''; $htmltext=$langs->trans("PageNameAliasHelp", $langs->transnoentitiesnoconv("EditPageMeta")); print $form->textwithpicto('', $htmltext, 1, 'help', '', 0, 2, 'helppagealias'); print '
'; $urlext=$virtualurl.'/'.$pagealias.'.php'; $urlint=$urlwithroot.'/public/websites/index.php?website='.$website; - print 'transnoentitiesnoconv("Site"), $langs->transnoentitiesnoconv("Site"), $dataroot, $urlext)).'">'; - print $form->textwithpicto('', $langs->trans("PreviewSiteServedByWebServer", $langs->transnoentitiesnoconv("Site"), $langs->transnoentitiesnoconv("Site"), $dataroot, $virtualurl?$urlext:''.$langs->trans("VirtualHostUrlNotDefined").''), 1, 'preview_ext'); + print 'transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $dataroot, $urlext)).'">'; + print $form->textwithpicto('', $langs->trans("PreviewSiteServedByWebServer", $langs->transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $dataroot, $virtualurl?$urlext:''.$langs->trans("VirtualHostUrlNotDefined").''), 1, 'preview_ext'); print ''; print 'transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $realpage)).'">'; @@ -887,7 +1077,7 @@ if (count($object->records) > 0) // TODO Add js to save alias like we save virtual host name and use dynamic virtual host for url of id=previewpageext } - if (! in_array($action, array('editcss','editmenu','create'))) + if (! in_array($action, array('editcss','editmenu','create','createpagefromclone'))) { if (preg_match('/^create/',$action)) print ''; if (preg_match('/^edit/',$action)) print ''; @@ -896,7 +1086,17 @@ if (count($object->records) > 0) print '
'; - if ($action == 'preview') + print '
'; + if (GETPOST('editsource', 'alpha') || GETPOST('editcontent', 'alpha')) + { + $htmltext=$langs->transnoentitiesnoconv("YouCanEditHtmlSource"); + print $form->textwithpicto($langs->trans("SyntaxHelp"), $htmltext, 1, 'help', 'inline-block', 0, 2, 'tooltipsubstitution'); + } + print '
'; + + + + if ($action == 'preview' || $action == 'createpagefromclone') { // Adding jquery code to change on the fly url of preview ext if (! empty($conf->use_javascript_ajax)) @@ -962,27 +1162,50 @@ if ($action == 'editcss') $csscontent = @file_get_contents($filecss); // Clean the php css file to remove php code and get only css part - $csscontent = preg_replace('//s', '', $csscontent); - - if (! trim($csscontent)) $csscontent='/* CSS content (all website) */'; + $csscontent = preg_replace('/<\?php \/\/ BEGIN PHP.*END PHP \?>\n*/ims', '', $csscontent); + $csscontent.= GETPOST('WEBSITE_CSS_INLINE'); + if (! trim($csscontent)) $csscontent='/* CSS content (all pages) */'."\n".'body.bodywebsite { margin: 0; }'; $htmlheader = @file_get_contents($filehtmlheader); - // Clean the php css file to remove php code and get only html part - $htmlheader = preg_replace('//s', '', $htmlheader); + // Clean the php htmlheader file to remove php code and get only html part + $htmlheader = preg_replace('/<\?php \/\/ BEGIN PHP.*END PHP \?>\n*/ims', '', $htmlheader); + if (! trim($htmlheader)) $htmlheader=''."\n".''."\n".''; + else $htmlheader=''."\n".$htmlheader."\n".''; - if (! trim($htmlheader)) $htmlheader=''; + $robotcontent = @file_get_contents($filerobot); + // Clean the php htmlheader file to remove php code and get only html part + $robotcontent = preg_replace('/<\?php \/\/ BEGIN PHP.*END PHP \?>\n*/ims', '', $robotcontent); + if (! trim($robotcontent)) + { + $robotcontent.="# Robot file. Generated with ".DOL_APPLICATION_TITLE."\n"; + $robotcontent.="User-agent: *\n"; + $robotcontent.="Allow: /public/\n"; + $robotcontent.="Disallow: /administrator/\n"; + } + + $htaccesscontent = @file_get_contents($filehtaccess); + // Clean the php htmlheader file to remove php code and get only html part + $htaccesscontent = preg_replace('/<\?php \/\/ BEGIN PHP.*END PHP \?>\n*/ims', '', $htaccesscontent); + if (! trim($htaccesscontent)) + { + $htaccesscontent.="# Order allow,deny\n"; + $htaccesscontent.="# Deny from all\n"; + } + //else $htaccesscontent=''."\n".$htaccesscontent."\n".'';*/ dol_fiche_head(); print ''."\n"; print ''; + // Website print ''; + // CSS file print ''; + // Common HTML header print ''; - /*print '';*/ + + $doleditor=new DolEditor('WEBSITE_ROBOT', $robotcontent, '', '220', 'ace', 'In', true, false, 'ace', 0, '100%', ''); + print $doleditor->Create(1, '', true, 'Robot file', 'txt'); + + print ''; + + // .htaccess + print ''; print '
'; print $langs->trans('WebSite'); print ''; print $website; print '
'; print $langs->trans('WEBSITE_CSS_INLINE'); print ''; @@ -990,11 +1213,9 @@ if ($action == 'editcss') $doleditor=new DolEditor('WEBSITE_CSS_INLINE', $csscontent, '', '220', 'ace', 'In', true, false, 'ace', 0, '100%', ''); print $doleditor->Create(1, '', true, 'CSS', 'css'); - /*print '';*/ print '
'; print $langs->trans('WEBSITE_HTML_HEADER'); print ''; @@ -1002,16 +1223,27 @@ if ($action == 'editcss') $doleditor=new DolEditor('WEBSITE_HTML_HEADER', $htmlheader, '', '220', 'ace', 'In', true, false, 'ace', 0, '100%', ''); print $doleditor->Create(1, '', true, 'HTML Header', 'html'); - /*print '';*/ print '
'; - print $langs->trans('WEBSITE_CSS_URL'); + // Robot file + print '
'; + print $langs->trans('WEBSITE_ROBOT'); print ''; - print ''; - print '
'; + print $langs->trans('WEBSITE_HTACCESS'); + print ''; + + $doleditor=new DolEditor('WEBSITE_HTACCESS', $htaccesscontent, '', '220', 'ace', 'In', true, false, 'ace', 0, '100%', ''); + print $doleditor->Create(1, '', true, $langs->trans("File").' .htaccess', 'txt'); + + print '
'; @@ -1040,38 +1272,46 @@ if ($action == 'editmeta' || $action == 'create') print ''; print '/public/websites/index.php?website='.urlencode($website).'&pageid='.urlencode($pageid); print ''; - $pageurl=dol_escape_htmltag($objectpage->pageurl); - $pagetitle=dol_escape_htmltag($objectpage->title); - $pagedescription=dol_escape_htmltag($objectpage->description); - $pagekeywords=dol_escape_htmltag($objectpage->keywords); + $pageurl=$objectpage->pageurl; + $pagetitle=$objectpage->title; + $pagedescription=$objectpage->description; + $pagekeywords=$objectpage->keywords; + $pagelang=$objectpage->lang; } - if (GETPOST('WEBSITE_PAGENAME')) $pageurl=GETPOST('WEBSITE_PAGENAME'); - if (GETPOST('WEBSITE_TITLE')) $pagetitle=GETPOST('WEBSITE_TITLE'); - if (GETPOST('WEBSITE_DESCRIPTION')) $pagedescription=GETPOST('WEBSITE_DESCRIPTION'); - if (GETPOST('WEBSITE_KEYWORDS')) $pagekeywords=GETPOST('WEBSITE_KEYWORDS'); + if (GETPOST('WEBSITE_PAGENAME')) $pageurl=GETPOST('WEBSITE_PAGENAME','alpha'); + if (GETPOST('WEBSITE_TITLE')) $pagetitle=GETPOST('WEBSITE_TITLE','alpha'); + if (GETPOST('WEBSITE_DESCRIPTION')) $pagedescription=GETPOST('WEBSITE_DESCRIPTION','alpha'); + if (GETPOST('WEBSITE_KEYWORDS')) $pagekeywords=GETPOST('WEBSITE_KEYWORDS','alpha'); + if (GETPOST('WEBSITE_LANG')) $pagelang=GETPOST('WEBSITE_LANG','aZ09'); print ''; print $langs->trans('WEBSITE_PAGENAME'); print ''; - print ''; + print ''; print ''; print ''; print $langs->trans('WEBSITE_TITLE'); print ''; - print ''; + print ''; print ''; print ''; print $langs->trans('WEBSITE_DESCRIPTION'); print ''; - print ''; + print ''; print ''; print ''; print $langs->trans('WEBSITE_KEYWORDS'); print ''; - print ''; + print ''; + print ''; + + print ''; + print $langs->trans('Language'); + print ''; + print $formadmin->select_language($pagelang?$pagelang:$langs->defaultlang, 'WEBSITE_LANG'); print ''; print ''; @@ -1095,13 +1335,32 @@ if ($action == 'editmenu') print '
'.$langs->trans("FeatureNotYetAvailable").''; } +if ($action == 'editsource') +{ + /* + * Editing global variables not related to a specific theme + */ + + //$csscontent = @file_get_contents($filecss); + + $contentforedit = ''; + /*$contentforedit.=''."\n";*/ + $contentforedit .= $objectpage->content; + + require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; + $doleditor=new DolEditor('PAGE_CONTENT',$contentforedit,'',500,'Full','',true,true,'ace',ROWS_5,'90%'); + $doleditor->Create(0, '', false, 'HTML Source', 'php'); +} + if ($action == 'editcontent') { /* * Editing global variables not related to a specific theme */ - $csscontent = @file_get_contents($filecss); + //$csscontent = @file_get_contents($filecss); $contentforedit = ''; /*$contentforedit.=''."\n"; - // Replace php code - $content = preg_replace('/<\?php.*\?>/ims', '...php...', $objectpage->content); + $out.='
'."\n"; + + // Replace php code. Note $objectpage->content come from database and does not contains body tags. + $content = preg_replace('/<\?php[^\?]+\?>\n*/ims', '...php...', $objectpage->content); + + // Replace relative link / with dolibarr URL + $content = preg_replace('/(href=")\/\"/', '\1'.DOL_URL_ROOT.'/websites/index.php?website='.$object->ref.'&pageid='.$object->fk_default_home.'"', $content, -1, $nbrep); + // Replace relative link /xxx.php with dolibarr URL + $content = preg_replace('/(href=")\/?([^\"]*)(\.php\")/', '\1'.DOL_URL_ROOT.'/websites/index.php?website='.$object->ref.'&pageref=\2"', $content, -1, $nbrep); + $out.=$content."\n"; + $out.='
'; $out.='
'; $out.= "\n".''."\n\n"; diff --git a/test/phpunit/FunctionsLibTest.php b/test/phpunit/FunctionsLibTest.php index 873a17758c8..0821e6c7a6c 100644 --- a/test/phpunit/FunctionsLibTest.php +++ b/test/phpunit/FunctionsLibTest.php @@ -122,10 +122,75 @@ class FunctionsLibTest extends PHPUnit_Framework_TestCase + /** + * testDolGetFirstLineOfText + * + * @return void + */ + public function testDolGetFirstLineOfText() + { + // Nb of line is same than entry text + + $input="aaaa"; + $result=dolGetFirstLineOfText($input); + print __METHOD__." result=".$result."\n"; + $this->assertEquals("aaaa", $result); + + $input="aaaa\nbbbbbbbbbbbb\n"; + $result=dolGetFirstLineOfText($input, 2); + print __METHOD__." result=".$result."\n"; + $this->assertEquals("aaaa\nbbbbbbbbbbbb", $result); + + $input="aaaa
bbbbbbbbbbbb
"; + $result=dolGetFirstLineOfText($input, 2); + print __METHOD__." result=".$result."\n"; + $this->assertEquals("aaaa
\nbbbbbbbbbbbb", $result); + + // Nb of line is lower + + $input="aaaa\nbbbbbbbbbbbb\ncccccc\n"; + $result=dolGetFirstLineOfText($input); + print __METHOD__." result=".$result."\n"; + $this->assertEquals("aaaa...", $result); + + $input="aaaa
bbbbbbbbbbbb
cccccc
"; + $result=dolGetFirstLineOfText($input); + print __METHOD__." result=".$result."\n"; + $this->assertEquals("aaaa...", $result); + + $input="aaaa\nbbbbbbbbbbbb\ncccccc\n"; + $result=dolGetFirstLineOfText($input, 2); + print __METHOD__." result=".$result."\n"; + $this->assertEquals("aaaa\nbbbbbbbbbbbb...", $result); + + $input="aaaa
bbbbbbbbbbbb
cccccc
"; + $result=dolGetFirstLineOfText($input, 2); + print __METHOD__." result=".$result."\n"; + $this->assertEquals("aaaa
\nbbbbbbbbbbbb...", $result); + + // Nb of line is higher + + $input="aaaa
bbbbbbbbbbbb
cccccc"; + $result=dolGetFirstLineOfText($input, 100); + print __METHOD__." result=".$result."\n"; + $this->assertEquals("aaaa
\nbbbbbbbbbbbb
\ncccccc", $result, 'dolGetFirstLineOfText with nb 100 a'); + + $input="aaaa
bbbbbbbbbbbb
cccccc
"; + $result=dolGetFirstLineOfText($input, 100); + print __METHOD__." result=".$result."\n"; + $this->assertEquals("aaaa
\nbbbbbbbbbbbb
\ncccccc", $result, 'dolGetFirstLineOfText with nb 100 b'); + + $input="aaaa
bbbbbbbbbbbb
cccccc
\n"; + $result=dolGetFirstLineOfText($input, 100); + print __METHOD__." result=".$result."\n"; + $this->assertEquals("aaaa
\nbbbbbbbbbbbb
\ncccccc", $result, 'dolGetFirstLineOfText with nb 100 c'); + } + + /** * testDolBuildPath * - * @return boolean + * @return void */ public function testDolBuildPath() {