diff --git a/.gitignore b/.gitignore index 12983e5dfd8..1efe4f4bb82 100755 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,10 @@ doxygen_warnings.log *.iml Thumbs.db # Vagrant generated files -.vagrant \ No newline at end of file +.vagrant +# Composer installed repositories +/htdocs/includes/**/.git +# Composer autoloader and unwanted files +htdocs/includes/autoload.php +htdocs/includes/bin/ +htdocs/includes/composer/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 304924fe150..8640c5e9b2f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -38,7 +38,7 @@ We officially support versions N, N − 1 and N − 2 for N the latest version a Choose your base branch accordingly. ### General rules -Please don't edit the ChangeLog file. A project manager will update it from your commit messages. +Please don't edit the ChangeLog file. File will be generated from your commit messages during release process by the project manager. ### Commits Use clear commit messages with the following structure: @@ -50,7 +50,7 @@ LONGDESC ``` #### Keyword -In uppercase to appear in ChangeLog when generated. +In uppercase if you want to have the log comment appears into the generated ChangeLog file. The keyword can be ommitted if your commit does not fit in any of the following categories: - Fix: for a bug fix @@ -97,6 +97,10 @@ When submitting a pull request, use same rule as [Commits](#commits) for the mes If your pull request only contains one commit, GitHub will be smart enough to fill it for you. Otherwise, please be a bit verbose about what you're providing. +You Pull Request must pass the Continuous Integration checks. +Also, if you want to include a new external library (into htdocs/includes directory), please ask before to the project +leader to see if such a library can be accepted. + ### Resources [Developer documentation](http://wiki.dolibarr.org/index.php/Developer_documentation) diff --git a/COPYRIGHT b/COPYRIGHT index 4862ab1b339..b89c5d23e60 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -12,7 +12,7 @@ Dolibarr uses some external libraries released under different licenses. This is Component Version License GPL Compatible Usage ------------------------------------------------------------------------------------- PHP libraries: -AdoDb-Date 0.33 Modified BSD License Yes Date convertion (not into rpm package) +AdoDb-Date 0.36 Modified BSD License Yes Date convertion (not into rpm package) ChromePHP 4.1.0 Apache Software License 2.0 Yes Return server log to chrome browser console CKEditor 4.3.3 LGPL-2.1+ Yes Editor WYSIWYG EvalMath 1.0 BSD Yes Safe math expressions evaluation @@ -24,7 +24,7 @@ Mobiledetect 2.8.3 MIT License Yes NuSoap 0.9.5 LGPL 2.1+ Yes Library to develop SOAP Web services (not into rpm and deb package) PEAR Mail_MIME 1.8.9 BSD Yes NuSoap dependency odtPHP 1.0.1 GPL-2+ b Yes Library to build/edit ODT files -PHPExcel 1.8.0 LGPL-2.1+ Yes Read/Write XLS files, read ODS files +PHPExcel 1.8.1 LGPL-2.1+ Yes Read/Write XLS files, read ODS files php-iban 1.4.7 LGPL-3+ Yes Parse and validate IBAN (and IIBAN) bank account information in PHP PHPoAuthLib 0.8.2 MIT License Yes Library to provide oauth1 and oauth2 to different service PHPPrintIPP 1.3 GPL-2+ Yes Library to send print IPP requests @@ -54,7 +54,7 @@ jQuery TableDnD 0.6 GPL and MIT License Yes jQuery Timepicker 1.1.0 GPL and MIT License Yes JS library Timepicker addon for Datepicker jQuery Tiptip 1.3 GPL and MIT License Yes JS library for tooltips jsGantt 1.2 BSD License Yes JS library (to build Gantt reports) -JsTimezoneDetect 1.0.4 MIT License Yes JS library to detect user timezone +JsTimezoneDetect 1.0.6 MIT License Yes JS library to detect user timezone Raven.js 1.1.19 MIT License Yes Used for client-side error logging with Sentry logger For licenses compatibility informations: diff --git a/README-FR.md b/README-FR.md index 53ae1be8e8d..b3ce951c975 100644 --- a/README-FR.md +++ b/README-FR.md @@ -133,12 +133,19 @@ Voici un liste de fonctionnalites pas encore gérées par Dolibarr: - Dolibarr ne fait pas le café (pas encore). -## RESEAUX SOCIAUX +## ACTUALITES ET RESEAUX SOCIAUX -Suivez le projet Dolibarr project sur +Suivez le projet Dolibarr project sur les réseaux francophones -Facebook: +- Facebook: +- Google+: +- Twitter: -Google+: +ou sur les réseaux anglophones -Twitter: +- [Facebook](https://www.facebook.com/dolibarr) +- [Google+](https://plus.google.com/+DolibarrOrg) +- [Twitter](http://www.twitter.com/dolibarr) +- [LinkedIn](https://www.linkedin.com/company/association-dolibarr) +- [YouTube](https://www.youtube.com/user/DolibarrERPCRM) +- [GitHub](https://github.com/Dolibarr/dolibarr) diff --git a/README.md b/README.md index f6f4b8be34f..91f99dc8025 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # DOLIBARR ERP & CRM -![Build status](https://img.shields.io/travis/Dolibarr/dolibarr/develop.svg) ![Downloads per day](https://img.shields.io/sourceforge/dd/dolibarr.svg) +![Build status](https://img.shields.io/travis/Dolibarr/dolibarr/develop.svg) ![Downloads per day](https://img.shields.io/sourceforge/dm/dolibarr.svg) Dolibarr ERP & CRM is a modern software to manage your organization's activity (contacts, suppliers, invoices, orders, stocks, agenda, ...). @@ -16,9 +16,9 @@ You can use it as a standalone application or as a web application to be able to Dolibarr is released 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 (GPL-3+). -See the [COPYING](COPYING) file for a full copy of the license. +See the [COPYING](https://github.com/Dolibarr/dolibarr/blob/develop/COPYING) file for a full copy of the license. -Other licenses apply for some included dependencies. See [COPYRIGHT](COPYRIGHT) for a full list. +Other licenses apply for some included dependencies. See [COPYRIGHT](https://github.com/Dolibarr/dolibarr/blob/develop/COPYRIGHT) for a full list. ## INSTALLING @@ -65,9 +65,9 @@ You can use a Web server and a supported database (MySQL recommended) to install *Note: migration process can safely be done multiple times.* -## NEWS +## WHAT'S NEW -See the [ChangeLog](ChangeLog) file. +See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog) file. ## FEATURES @@ -153,9 +153,9 @@ Administrator, user, developer and translator's documentations are available alo Dolibarr is the work of many contributors over the years and uses some fine libraries. -See [COPYRIGHT](COPYRIGHT) file. +See [COPYRIGHT](https://github.com/Dolibarr/dolibarr/blob/develop/COPYRIGHT) file. -## SOCIAL NETWORKS +## NEWS AND SOCIAL NETWORKS Follow Dolibarr project on: diff --git a/composer.json b/composer.json index c5fab8bf290..9061efb3bfe 100644 --- a/composer.json +++ b/composer.json @@ -16,12 +16,12 @@ "php": ">=5.3.0", "ext-curl": "*", "ccampbell/chromephp": "^4.1", - "ckeditor/ckeditor": "4.3.3", + "ckeditor/ckeditor": "dev-full/4.3.x#0b7c3f1", "mike42/escpos-php": "dev-master", "mobiledetect/mobiledetectlib": "2.8.3", - "phpoffice/phpexcel": "1.8.0", + "phpoffice/phpexcel": "1.8.1", "restler/framework": "^3.0", - "tecnick.com/tcpdf": "6.2.6", + "tecnickcom/tcpdf": "6.2.6", "raven/raven": "^0.12.0", "firephp/firephp-core": "^0.4.0" }, diff --git a/composer.lock b/composer.lock index 47122ebe431..99bf8d6fa10 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "d88b5c84a9ea1af354d867ba2e2ab251", - "content-hash": "85e60ec7f8ab593387c7bd10d8db860d", + "hash": "335eb7bd5c2eb116fd2da80b4f48e857", "packages": [ { "name": "ccampbell/chromephp", @@ -52,16 +51,16 @@ }, { "name": "ckeditor/ckeditor", - "version": "4.3.3", + "version": "dev-full/4.3.x", "source": { "type": "git", "url": "https://github.com/ckeditor/ckeditor-releases.git", - "reference": "0068dd540ce8bf1815abb7b5455c55354bc56334" + "reference": "0b7c3f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ckeditor/ckeditor-releases/zipball/0068dd540ce8bf1815abb7b5455c55354bc56334", - "reference": "0068dd540ce8bf1815abb7b5455c55354bc56334", + "url": "https://api.github.com/repos/ckeditor/ckeditor-releases/zipball/252e512e911f21d880ea542fe162c4643885b317", + "reference": "0b7c3f1", "shasum": "" }, "type": "library", @@ -89,7 +88,7 @@ "text", "wysiwyg" ], - "time": "2014-02-26 15:34:37" + "time": "2014-02-26 15:43:10" }, { "name": "firephp/firephp-core", @@ -239,16 +238,16 @@ }, { "name": "phpoffice/phpexcel", - "version": "1.8.0", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/PHPOffice/PHPExcel.git", - "reference": "e69a5e4d0ffa7fb6f171859e0a04346e580df30b" + "reference": "372c7cbb695a6f6f1e62649381aeaa37e7e70b32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/PHPExcel/zipball/e69a5e4d0ffa7fb6f171859e0a04346e580df30b", - "reference": "e69a5e4d0ffa7fb6f171859e0a04346e580df30b", + "url": "https://api.github.com/repos/PHPOffice/PHPExcel/zipball/372c7cbb695a6f6f1e62649381aeaa37e7e70b32", + "reference": "372c7cbb695a6f6f1e62649381aeaa37e7e70b32", "shasum": "" }, "require": { @@ -292,7 +291,7 @@ "xls", "xlsx" ], - "time": "2014-03-02 15:22:49" + "time": "2015-05-01 07:00:55" }, { "name": "raven/raven", @@ -423,7 +422,7 @@ "time": "2015-08-04 07:52:49" }, { - "name": "tecnick.com/tcpdf", + "name": "tecnickcom/tcpdf", "version": "6.2.6", "source": { "type": "git", @@ -483,7 +482,6 @@ "pdf417", "qrcode" ], - "abandoned": "tecnickcom/tcpdf", "time": "2015-01-28 18:51:40" } ], @@ -491,6 +489,7 @@ "aliases": [], "minimum-stability": "stable", "stability-flags": { + "ckeditor/ckeditor": 20, "mike42/escpos-php": 20 }, "prefer-stable": false, diff --git a/dev/dolibarr_changes.txt b/dev/dolibarr_changes.txt index 9d449070a5f..f761bc940db 100644 --- a/dev/dolibarr_changes.txt +++ b/dev/dolibarr_changes.txt @@ -69,7 +69,7 @@ Add tcpdi.php Add tcpdi_parser.php and replace: require_once(dirname(__FILE__).'/include/tcpdf_filters.php'); with: -require_once(dirname(__FILE__).'/../tecnick.com/tcpdf/include/tcpdf_filters.php'); +require_once(dirname(__FILE__).'/../tecnickcom/tcpdf/include/tcpdf_filters.php'); diff --git a/dev/skeletons/skeleton_list.php b/dev/skeletons/skeleton_list.php index 3018a23fdea..686549f19a8 100644 --- a/dev/skeletons/skeleton_list.php +++ b/dev/skeletons/skeleton_list.php @@ -96,6 +96,23 @@ if (($id > 0 || ! empty($ref)) && $action != 'add') if ($result < 0) dol_print_error($db); } +// Definition of fields for list +$arrayfields=array( + 't.field1'=>array('label'=>$langs->trans("Field1"), 'checked'=>1), + 't.field2'=>array('label'=>$langs->trans("Field2"), 'checked'=>1), + //'t.entity'=>array('label'=>$langs->trans("Entity"), 'checked'=>1, 'enabled'=>(! empty($conf->multicompany->enabled) && empty($conf->multicompany->transverse_mode))), + 't.datec'=>array('label'=>$langs->trans("DateCreation"), 'checked'=>0, 'position'=>500), + 't.tms'=>array('label'=>$langs->trans("DateModificationShort"), 'checked'=>0, 'position'=>500), + //'t.statut'=>array('label'=>$langs->trans("Status"), 'checked'=>1, 'position'=>1000), +); +// 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]); + } +} @@ -267,22 +284,6 @@ if ($resql) print ''; } - $arrayfields=array( - 't.field1'=>array('label'=>$langs->trans("Field1"), 'checked'=>1), - 't.field2'=>array('label'=>$langs->trans("Field2"), 'checked'=>1), - //'t.entity'=>array('label'=>$langs->trans("Entity"), 'checked'=>1, 'enabled'=>(! empty($conf->multicompany->enabled) && empty($conf->multicompany->transverse_mode))), - 't.datec'=>array('label'=>$langs->trans("DateCreation"), 'checked'=>0, 'position'=>500), - 't.tms'=>array('label'=>$langs->trans("DateModificationShort"), 'checked'=>0, 'position'=>500), - //'t.statut'=>array('label'=>$langs->trans("Status"), 'checked'=>1, 'position'=>1000), - ); - // 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]); - } - } $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage; $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields diff --git a/dev/test/testtcpdf.php b/dev/test/testtcpdf.php index 6b600c630d3..ad67bce8af9 100755 --- a/dev/test/testtcpdf.php +++ b/dev/test/testtcpdf.php @@ -27,8 +27,8 @@ * @since 2008-03-04 */ -require_once('../../htdocs/includes/tecnick.com/tcpdf/config/tcpdf_config.php'); -require_once('../../htdocs/includes/tecnick.com/tcpdf/tcpdf.php'); +require_once('../../htdocs/includes/tecnickcom/tcpdf/config/tcpdf_config.php'); +require_once('../../htdocs/includes/tecnickcom/tcpdf/tcpdf.php'); // create new PDF document $pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false); diff --git a/dev/test/testutf.php b/dev/test/testutf.php index f60f9d195a3..cb83f431b93 100644 --- a/dev/test/testutf.php +++ b/dev/test/testutf.php @@ -47,8 +47,8 @@ print 'Files has been created. Check its name from your explorer'."\n"; * @since 2008-09-15 */ -require_once('../../htdocs/includes/tecnick.com/tcpdf/config/tcpdf_config.php'); -require_once('../../htdocs/includes/tecnick.com/tcpdf/tcpdf.php'); +require_once('../../htdocs/includes/tecnickcom/tcpdf/config/tcpdf_config.php'); +require_once('../../htdocs/includes/tecnickcom/tcpdf/tcpdf.php'); // create new PDF document $pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false); diff --git a/htdocs/comm/card.php b/htdocs/comm/card.php index 3083ac9505c..0045316d419 100644 --- a/htdocs/comm/card.php +++ b/htdocs/comm/card.php @@ -139,7 +139,7 @@ if (empty($reshook)) $object->fetch($id); $object->fk_prospectlevel=GETPOST('prospect_level_id','alpha'); $result=$object->set_prospect_level($user); - if ($result < 0) setEventMessage($object->error,$object->errors,'errors'); + if ($result < 0) setEventMessages($object->error, $object->errors, 'errors'); } // set communication status @@ -148,7 +148,7 @@ if (empty($reshook)) $object->fetch($id); $object->stcomm_id=dol_getIdFromCode($db, GETPOST('stcomm','alpha'), 'c_stcomm'); $result=$object->set_commnucation_level($user); - if ($result < 0) setEventMessages($object->error,$object->errors,'errors'); + if ($result < 0) setEventMessages($object->error, $object->errors, 'errors'); } // update outstandng limit diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index a3d30316522..65540732674 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -5,10 +5,10 @@ * Copyright (C) 2005-2015 Regis Houssin * Copyright (C) 2006 Andre Cianfarani * Copyright (C) 2010-2013 Juanjo Menent - * Copyright (C) 2011 Philippe Grand + * Copyright (C) 2011-2015 Philippe Grand * Copyright (C) 2012-2013 Christophe Battarel * Copyright (C) 2012 Marcos García - * Copyright (C) 2012 Cedric Salvador + * Copyright (C) 2012 Cedric Salvador * Copyright (C) 2013 Florian Henry * Copyright (C) 2014 Ferran Marcet * Copyright (C) 2015 Jean-François Ferry @@ -123,7 +123,7 @@ if (empty($reshook)) { if (1==0 && ! GETPOST('clone_content') && ! GETPOST('clone_receivers')) { - setEventMessage($langs->trans("NoCloneOptionsSpecified"), 'errors'); + setEventMessages($langs->trans("NoCloneOptionsSpecified"), null, 'errors'); } else { @@ -140,7 +140,7 @@ if (empty($reshook)) } else { - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); $object = $orig; $action=''; } @@ -156,12 +156,11 @@ if (empty($reshook)) $result = $object->set_reopen($user); if ($result > 0) { - header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); - exit; + setEventMessages($langs->trans('OrderReopened', $object->ref), null); } else { - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } } } @@ -177,7 +176,7 @@ if (empty($reshook)) } else { - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } } @@ -208,7 +207,7 @@ if (empty($reshook)) } else { - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } } @@ -225,7 +224,7 @@ if (empty($reshook)) $datelivraison = dol_mktime(12, 0, 0, GETPOST('liv_month'), GETPOST('liv_day'), GETPOST('liv_year')); if ($datecommande == '') { - setEventMessage($langs->trans('ErrorFieldRequired', $langs->transnoentities('Date')), 'errors'); + setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentities('Date')), null, 'errors'); $action = 'create'; $error++; } @@ -374,11 +373,11 @@ if (empty($reshook)) if ($reshook < 0) $error++; } else { - setEventMessage($srcobject->error, 'errors'); + setEventMessages($srcobject->error, $srcobject->errors, 'errors'); $error++; } } else { - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); $error++; } } else { @@ -414,7 +413,7 @@ if (empty($reshook)) { $result = $object->add_contact(GETPOST('contactid'), 'CUSTOMER', 'external'); if ($result < 0) { - setEventMessage($langs->trans("ErrorFailedToAddContact"), 'errors'); + setEventMessages($langs->trans("ErrorFailedToAddContact"), null, 'errors'); $error++; } } @@ -432,7 +431,7 @@ if (empty($reshook)) } else { $db->rollback(); $action = 'create'; - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } } } @@ -442,7 +441,7 @@ if (empty($reshook)) $ret=$object->classifyBilled(); if ($ret < 0) { - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } } @@ -471,7 +470,7 @@ if (empty($reshook)) $result = $object->set_date($user, $date); if ($result < 0) { - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } } @@ -481,7 +480,7 @@ if (empty($reshook)) $result = $object->set_date_livraison($user, $datelivraison); if ($result < 0) { - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } } @@ -529,16 +528,25 @@ if (empty($reshook)) elseif ($action == 'set_incoterms' && !empty($conf->incoterm->enabled)) { $result = $object->setIncoterms(GETPOST('incoterm_id', 'int'), GETPOST('location_incoterms', 'alpha')); + if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + } } // bank account else if ($action == 'setbankaccount' && $user->rights->commande->creer) { $result=$object->setBankAccount(GETPOST('fk_account', 'int')); + if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + } } // shipping method else if ($action == 'setshippingmethod' && $user->rights->commande->creer) { $result = $object->setShippingMethod(GETPOST('shipping_method_id', 'int')); + if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + } } else if ($action == 'setremisepercent' && $user->rights->commande->creer) { @@ -586,11 +594,11 @@ if (empty($reshook)) } if (empty($idprod) && ($price_ht < 0) && ($qty < 0)) { - setEventMessage($langs->trans('ErrorBothFieldCantBeNegative', $langs->transnoentitiesnoconv('UnitPriceHT'), $langs->transnoentitiesnoconv('Qty')), 'errors'); + setEventMessages($langs->trans('ErrorBothFieldCantBeNegative', $langs->transnoentitiesnoconv('UnitPriceHT'), $langs->transnoentitiesnoconv('Qty')), null, 'errors'); $error++; } if (GETPOST('prod_entry_mode') == 'free' && empty($idprod) && GETPOST('type') < 0) { - setEventMessage($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), 'errors'); + setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), null, 'errors'); $error++; } if (GETPOST('prod_entry_mode') == 'free' && empty($idprod) && (! ($price_ht >= 0) || $price_ht == '')) // Unit price can be 0 but not '' @@ -599,11 +607,11 @@ if (empty($reshook)) $error++; } if ($qty == '') { - setEventMessage($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), 'errors'); + setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors'); $error++; } if (GETPOST('prod_entry_mode') == 'free' && empty($idprod) && empty($product_desc)) { - setEventMessage($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Description')), 'errors'); + setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Description')), null, 'errors'); $error++; } @@ -664,7 +672,7 @@ if (empty($reshook)) } else { - setEventMessage($prodcustprice->error,'errors'); + setEventMessages($prodcustprice->error, $prodcustprice->errors, 'errors'); } } @@ -748,7 +756,7 @@ if (empty($reshook)) if (! empty($price_min) && (price2num($pu_ht) * (1 - price2num($remise_percent) / 100) < price2num($price_min))) { $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency)); - setEventMessage($mesg, 'errors'); + setEventMessages($mesg, null, 'errors'); } else { // Insert line $result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $info_bits, 0, $price_base_type, $pu_ttc, $date_start, $date_end, $type, - 1, 0, GETPOST('fk_parent_line'), $fournprice, $buyingprice, $label, $array_options, $fk_unit); @@ -802,7 +810,7 @@ if (empty($reshook)) unset($_POST['date_endmonth']); unset($_POST['date_endyear']); } else { - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } } } @@ -866,7 +874,7 @@ if (empty($reshook)) $label = ((GETPOST('update_label') && GETPOST('product_label')) ? GETPOST('product_label') : ''); if ($price_min && (price2num($pu_ht) * (1 - price2num(GETPOST('remise_percent')) / 100) < price2num($price_min))) { - setEventMessage($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency)), 'errors'); + setEventMessages($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency)), null, 'errors'); $error++; } } else { @@ -914,7 +922,7 @@ if (empty($reshook)) unset($_POST['fournprice']); unset($_POST['buying_price']); } else { - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } } } @@ -947,7 +955,7 @@ if (empty($reshook)) if (! $idwarehouse || $idwarehouse == -1) { $error++; - setEventMessage($langs->trans('ErrorFieldRequired',$langs->transnoentitiesnoconv("Warehouse")), 'errors'); + setEventMessages($langs->trans('ErrorFieldRequired',$langs->transnoentitiesnoconv("Warehouse")), null, 'errors'); $action=''; } } @@ -1000,7 +1008,7 @@ if (empty($reshook)) if (! $idwarehouse || $idwarehouse == -1) { $error++; - setEventMessage($langs->trans('ErrorFieldRequired',$langs->transnoentitiesnoconv("Warehouse")), 'errors'); + setEventMessages($langs->trans('ErrorFieldRequired',$langs->transnoentitiesnoconv("Warehouse")), null, 'errors'); $action=''; } } @@ -1032,7 +1040,7 @@ if (empty($reshook)) else if ($action == 'confirm_shipped' && $confirm == 'yes' && $user->rights->commande->cloturer) { $result = $object->cloture($user); if ($result < 0) { - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } } @@ -1059,7 +1067,7 @@ if (empty($reshook)) if (! $idwarehouse || $idwarehouse == -1) { $error++; - setEventMessage($langs->trans('ErrorFieldRequired',$langs->transnoentitiesnoconv("Warehouse")), 'errors'); + setEventMessages($langs->trans('ErrorFieldRequired',$langs->transnoentitiesnoconv("Warehouse")), null, 'errors'); $action=''; } } @@ -1068,7 +1076,7 @@ if (empty($reshook)) $result = $object->cancel($idwarehouse); if ($result < 0) { - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } } } @@ -1115,9 +1123,9 @@ if (empty($reshook)) $file = $upload_dir . '/' . GETPOST('file'); $ret = dol_delete_file($file, 0, 0, 0, $object); if ($ret) - setEventMessage($langs->trans("FileWasRemoved", GETPOST('urlfile'))); + setEventMessages($langs->trans("FileWasRemoved", GETPOST('urlfile')), null, 'mesgs'); else - setEventMessage($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), 'errors'); + setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), null, 'errors'); $action = ''; } } @@ -1181,9 +1189,9 @@ if (empty($reshook)) } else { if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') { $langs->load("errors"); - setEventMessage($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), 'errors'); + setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors'); } else { - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } } } diff --git a/htdocs/commande/contact.php b/htdocs/commande/contact.php index 6a322e8681e..c72e040e61c 100644 --- a/htdocs/commande/contact.php +++ b/htdocs/commande/contact.php @@ -2,7 +2,7 @@ /* Copyright (C) 2005 Patrick Rouillon * Copyright (C) 2005-2011 Laurent Destailleur * Copyright (C) 2005-2012 Regis Houssin - * Copyright (C) 2011-2012 Philippe Grand + * Copyright (C) 2011-2015 Philippe Grand * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -69,11 +69,11 @@ if ($action == 'addcontact' && $user->rights->commande->creer) if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') { $langs->load("errors"); - setEventMessage($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), 'errors'); + setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors'); } else { - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } } } diff --git a/htdocs/commande/orderstoinvoice.php b/htdocs/commande/orderstoinvoice.php index 136ac6c1b89..1abffe069f4 100644 --- a/htdocs/commande/orderstoinvoice.php +++ b/htdocs/commande/orderstoinvoice.php @@ -74,7 +74,7 @@ if ($action == 'create') if (is_array($selected) == false) { $error++; - setEventMessage($langs->trans('Error_OrderNotChecked'), 'errors'); + setEventMessages($langs->trans('Error_OrderNotChecked'), null, 'errors'); } else { @@ -251,7 +251,7 @@ if (($action == 'create' || $action == 'add') && !$error) } else { - setEventMessage($discount->error, 'errors'); + setEventMessages($discount->error, $discount->errors, 'errors'); $error++; break; } @@ -320,7 +320,7 @@ if (($action == 'create' || $action == 'add') && !$error) } else { - setEventMessage($objectsrc->error, 'errors'); + setEventMessages($objectsrc->error, $objectsrc->errors, 'errors'); $error++; } $ii++; @@ -328,7 +328,7 @@ if (($action == 'create' || $action == 'add') && !$error) } else { - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); $error++; } } @@ -348,7 +348,7 @@ if (($action == 'create' || $action == 'add') && !$error) $action='create'; $_GET["origin"]=$_POST["origin"]; $_GET["originid"]=$_POST["originid"]; - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); $error++; } } diff --git a/htdocs/compta/bank/account.php b/htdocs/compta/bank/account.php index b9c0d3821bc..d6f8652d31c 100644 --- a/htdocs/compta/bank/account.php +++ b/htdocs/compta/bank/account.php @@ -152,13 +152,13 @@ if ($action == 'add' && $id && ! isset($_POST["cancel"]) && $user->rights->banqu $insertid = $object->addline($dateop, $operation, $label, $amount, $num_chq, $cat1, $user); if ($insertid > 0) { - setEventMessage($langs->trans("RecordSaved")); + setEventMessages($langs->trans("RecordSaved"), null, 'mesgs'); header("Location: ".$_SERVER['PHP_SELF']."?id=".$id."&action=addline"); exit; } else { - setEventMessage($object->error, 'errors'); + setEventMessages($object->error, $object->errors, 'errors'); } } else diff --git a/htdocs/compta/bank/annuel.php b/htdocs/compta/bank/annuel.php index 68ef0a42e32..7b53d775cb6 100644 --- a/htdocs/compta/bank/annuel.php +++ b/htdocs/compta/bank/annuel.php @@ -291,7 +291,7 @@ if ($result < 0) { $langs->load("errors"); $error++; - setEventMessage($langs->trans("ErrorFailedToCreateDir"), 'errors'); + setEventMessages($langs->trans("ErrorFailedToCreateDir"), null, 'errors'); } else { diff --git a/htdocs/compta/bank/card.php b/htdocs/compta/bank/card.php index 063fee8ca78..fb8383cd91a 100644 --- a/htdocs/compta/bank/card.php +++ b/htdocs/compta/bank/card.php @@ -4,7 +4,7 @@ * Copyright (C) 2004-2015 Laurent Destailleur * Copyright (C) 2005-2009 Regis Houssin * Copyright (C) 2014-2015 Alexandre Spangaro - * Copyright (C) 2015 Jean-François Ferry + * Copyright (C) 2015 Jean-François Ferry * * 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 @@ -102,19 +102,19 @@ if ($_POST["action"] == 'add') if ($conf->global->MAIN_BANK_ACCOUNTANCY_CODE_ALWAYS_REQUIRED && empty($account->account_number)) { - setEventMessage($langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("AccountancyCode")), 'error'); + setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("AccountancyCode")), null, 'error'); $action='create'; // Force chargement page en mode creation $error++; } if (empty($account->ref)) { - setEventMessage($langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("Ref")), 'errors'); + setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("Ref")), null, 'errors'); $action='create'; // Force chargement page en mode creation $error++; } if (empty($account->label)) { - setEventMessage($langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("LabelBankCashAccount")), 'errors'); + setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("LabelBankCashAccount")), null, 'errors'); $action='create'; // Force chargement page en mode creation $error++; } @@ -130,7 +130,7 @@ if ($_POST["action"] == 'add') $_GET["id"]=$id; // Force chargement page en mode visu } else { - setEventMessage($account->error,'errors'); + setEventMessages($account->error, $account->errors, 'errors'); $action='create'; // Force chargement page en mode creation } } @@ -177,19 +177,19 @@ if ($_POST["action"] == 'update' && ! $_POST["cancel"]) if ($conf->global->MAIN_BANK_ACCOUNTANCY_CODE_ALWAYS_REQUIRED && empty($account->account_number)) { - setEventMessage($langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("AccountancyCode")), 'error'); + setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("AccountancyCode")), null, 'error'); $action='edit'; // Force chargement page en mode creation $error++; } if (empty($account->ref)) { - setEventMessage($langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("Ref")), 'errors'); + setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("Ref")), null, 'errors'); $action='edit'; // Force chargement page en mode creation $error++; } if (empty($account->label)) { - setEventMessage($langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("LabelBankCashAccount")), 'errors'); + setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("LabelBankCashAccount")), null, 'errors'); $action='edit'; // Force chargement page en mode creation $error++; } @@ -206,7 +206,7 @@ if ($_POST["action"] == 'update' && ! $_POST["cancel"]) } else { - setEventMessage($account->error, 'errors'); + setEventMessages($account->error, $account->errors, 'errors'); $action='edit'; // Force chargement page edition } } diff --git a/htdocs/compta/bank/document.php b/htdocs/compta/bank/document.php index 0b588fa64d0..3b6957df40f 100644 --- a/htdocs/compta/bank/document.php +++ b/htdocs/compta/bank/document.php @@ -133,9 +133,9 @@ else if ($action == 'confirm_deletefile' && $confirm == 'yes') { $ret = dol_delete_file($file, 0, 0, 0, $object); if ($ret) { - setEventMessage($langs->trans("FileWasRemoved", GETPOST('urlfile'))); + setEventMessages($langs->trans("FileWasRemoved", GETPOST('urlfile')), null, 'mesgs'); } else { - setEventMessage($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), 'errors'); + setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), null, 'errors'); } Header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $id); diff --git a/htdocs/compta/bank/graph.php b/htdocs/compta/bank/graph.php index 6f885e12bde..0764c87f5ab 100644 --- a/htdocs/compta/bank/graph.php +++ b/htdocs/compta/bank/graph.php @@ -81,7 +81,7 @@ if ($result < 0) { $langs->load("errors"); $error++; - setEventMessage($langs->trans("ErrorFailedToCreateDir"), 'errors'); + setEventMessages($langs->trans("ErrorFailedToCreateDir"), null, 'errors'); } else { @@ -113,7 +113,7 @@ else if ($mode == 'standard') { - // Chargement du tableau $amounts + // Loading table $amounts $amounts = array(); $monthnext = $month+1; @@ -153,7 +153,7 @@ else dol_print_error($db); } - // Calcul de $solde avant le debut du graphe + // Calculation of $solde before the start of the graph $solde = 0; $sql = "SELECT SUM(b.amount)"; @@ -265,7 +265,7 @@ else if ($mode == 'standard') { - // Chargement du tableau $amounts + // Loading table $amounts $amounts = array(); $sql = "SELECT date_format(b.datev,'%Y%m%d')"; $sql.= ", SUM(b.amount)"; @@ -296,7 +296,7 @@ else dol_print_error($db); } - // Calcul de $solde avant le debut du graphe + // Calculation of $solde before the start of the graph $solde = 0; $sql = "SELECT SUM(b.amount)"; @@ -403,7 +403,7 @@ else if ($mode == 'showalltime') { - // Chargement du tableau $amounts + // Loading table $amounts $amounts = array(); $sql = "SELECT date_format(b.datev,'%Y%m%d')"; diff --git a/htdocs/compta/bank/index.php b/htdocs/compta/bank/index.php index 46b382ed080..7ea3bf1be5a 100644 --- a/htdocs/compta/bank/index.php +++ b/htdocs/compta/bank/index.php @@ -113,7 +113,7 @@ foreach ($accounts as $key=>$type) { $result=$acc->load_board($user,$acc->id); if ($result<0) { - setEventMessage($acc->error, 'errors'); + setEventMessages($acc->error, $acc->errors, 'errors'); } else { print $result->nbtodo; if ($result->nbtodolate) print ' ('.$result->nbtodolate.img_warning($langs->trans("Late")).')'; @@ -229,7 +229,7 @@ foreach ($accounts as $key=>$type) { $result=$acc->load_board($user,$acc->id); if ($result<0) { - setEventMessage($acc->error, 'errors'); + setEventMessages($acc->error, $acc->errors, 'errors'); } else { print $result->nbtodo; if ($result->nbtodolate) print ' ('.$result->nbtodolate.img_warning($langs->trans("Late")).')'; diff --git a/htdocs/compta/bank/ligne.php b/htdocs/compta/bank/ligne.php index d210e209b59..0f73e5cb6cf 100644 --- a/htdocs/compta/bank/ligne.php +++ b/htdocs/compta/bank/ligne.php @@ -104,7 +104,7 @@ if ($user->rights->banque->modifier && $action == "update") if ($ac->courant == 2 && $_POST['value'] != 'LIQ') { - setEventMessage($langs->trans("ErrorCashAccountAcceptsOnlyCashMoney"), 'errors'); + setEventMessages($langs->trans("ErrorCashAccountAcceptsOnlyCashMoney"), null, 'errors'); $error++; } @@ -146,7 +146,7 @@ if ($user->rights->banque->modifier && $action == "update") $result = $db->query($sql); if ($result) { - setEventMessage($langs->trans("RecordSaved")); + setEventMessages($langs->trans("RecordSaved"), null, 'mesgs'); $db->commit(); } else @@ -184,7 +184,7 @@ if ($user->rights->banque->consolidate && ($action == 'num_releve' || $action == $result = $db->query($sql); if ($result) { - setEventMessage($langs->trans("RecordSaved")); + setEventMessages($langs->trans("RecordSaved"), null, 'mesgs'); $db->commit(); } else @@ -205,7 +205,7 @@ $form = new Form($db); llxHeader(); -// On initialise la liste des categories +// The list of categories is initialized $sql = "SELECT rowid, label"; $sql.= " FROM ".MAIN_DB_PREFIX."bank_categ"; $sql.= " ORDER BY label"; diff --git a/htdocs/compta/bank/rappro.php b/htdocs/compta/bank/rappro.php index 332e7fffe60..82070a957e2 100644 --- a/htdocs/compta/bank/rappro.php +++ b/htdocs/compta/bank/rappro.php @@ -71,7 +71,7 @@ if ($action == 'rappro' && $user->rights->banque->consolidate) $result=$bankline->update_conciliation($user,$_POST["cat"]); if ($result < 0) { - setEventMessage($bankline->error, 'errors'); + setEventMessages($bankline->error, $bankline->errors, 'errors'); $error++; break; } @@ -83,7 +83,7 @@ if ($action == 'rappro' && $user->rights->banque->consolidate) { $error++; $langs->load("errors"); - setEventMessage($langs->trans("ErrorPleaseTypeBankTransactionReportName"), 'errors'); + setEventMessages($langs->trans("ErrorPleaseTypeBankTransactionReportName"), null, 'errors'); } if (! $error) diff --git a/htdocs/compta/bank/virement.php b/htdocs/compta/bank/virement.php index 56071d61f9b..4e323893d85 100644 --- a/htdocs/compta/bank/virement.php +++ b/htdocs/compta/bank/virement.php @@ -113,18 +113,18 @@ if ($action == 'add') if (! $error) { $mesgs = $langs->trans("TransferFromToDone","id."\">".$accountfrom->label."","id."\">".$accountto->label."",$amount,$langs->transnoentities("Currency".$conf->currency)); - setEventMessage($mesgs); + setEventMessages($mesgs, null, 'mesgs'); $db->commit(); } else { - setEventMessage($accountfrom->error.' '.$accountto->error, 'errors'); + setEventMessages($accountfrom->error.' '.$accountto->error, null, 'errors'); $db->rollback(); } } else { - setEventMessage($langs->trans("ErrorFromToAccountsMustDiffers"), 'errors'); + setEventMessages($langs->trans("ErrorFromToAccountsMustDiffers"), null, 'errors'); } } } @@ -132,7 +132,7 @@ if ($action == 'add') /* - * Affichage + * View */ llxHeader(); diff --git a/htdocs/contact/list.php b/htdocs/contact/list.php index ee5c24f3017..d10e34227d6 100644 --- a/htdocs/contact/list.php +++ b/htdocs/contact/list.php @@ -122,6 +122,34 @@ $fieldstosearchall = array( 's.nom'=>"ThirdParty", ); +// Definition of fields for list +$arrayfields=array( + 'p.lastname'=>array('label'=>$langs->trans("Lastname"), 'checked'=>1), + 'p.firstname'=>array('label'=>$langs->trans("Firsname"), 'checked'=>1), + 'p.poste'=>array('label'=>$langs->trans("Post"), 'checked'=>1), + 'p.town'=>array('label'=>$langs->trans("Town"), 'checked'=>0), + 'p.zip'=>array('label'=>$langs->trans("Zip"), 'checked'=>0), + 'p.phone'=>array('label'=>$langs->trans("PhonePro"), 'checked'=>1), + 'p.phone_perso'=>array('label'=>$langs->trans("PhonePerso"), 'checked'=>0), + 'p.phone_mobile'=>array('label'=>$langs->trans("PhoneMobile"), 'checked'=>1), + 'p.fax'=>array('label'=>$langs->trans("Fax"), 'checked'=>1), + 'p.email'=>array('label'=>$langs->trans("Email"), 'checked'=>1), + 'p.skype'=>array('label'=>$langs->trans("Skype"), 'checked'=>1, 'enabled'=>(! empty($conf->skype->enabled))), + 'p.thirdparty'=>array('label'=>$langs->trans("ThirdParty"), 'checked'=>1, 'enabled'=>empty($conf->global->SOCIETE_DISABLE_CONTACTS)), + 'p.priv'=>array('label'=>$langs->trans("ContactVisibility"), 'checked'=>1, 'position'=>200), + 'p.datec'=>array('label'=>$langs->trans("DateCreation"), 'checked'=>0, 'position'=>500), + 'p.tms'=>array('label'=>$langs->trans("DateModificationShort"), 'checked'=>0, 'position'=>500), + 'p.statut'=>array('label'=>$langs->trans("Status"), 'checked'=>1, 'position'=>1000), +); +// 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 @@ -386,35 +414,10 @@ if ($result) print ''; } - $arrayfields=array( - 'p.lastname'=>array('label'=>$langs->trans("Lastname"), 'checked'=>1), - 'p.firstname'=>array('label'=>$langs->trans("Firsname"), 'checked'=>1), - 'p.poste'=>array('label'=>$langs->trans("Post"), 'checked'=>1), - 'p.town'=>array('label'=>$langs->trans("Town"), 'checked'=>0), - 'p.zip'=>array('label'=>$langs->trans("Zip"), 'checked'=>0), - 'p.phone'=>array('label'=>$langs->trans("PhonePro"), 'checked'=>1), - 'p.phone_perso'=>array('label'=>$langs->trans("PhonePerso"), 'checked'=>0), - 'p.phone_mobile'=>array('label'=>$langs->trans("PhoneMobile"), 'checked'=>1), - 'p.fax'=>array('label'=>$langs->trans("Fax"), 'checked'=>1), - 'p.email'=>array('label'=>$langs->trans("Email"), 'checked'=>1), - 'p.skype'=>array('label'=>$langs->trans("Skype"), 'checked'=>1, 'enabled'=>(! empty($conf->skype->enabled))), - 'p.thirdparty'=>array('label'=>$langs->trans("ThirdParty"), 'checked'=>1, 'enabled'=>empty($conf->global->SOCIETE_DISABLE_CONTACTS)), - 'p.priv'=>array('label'=>$langs->trans("ContactVisibility"), 'checked'=>1, 'position'=>200), - 'p.datec'=>array('label'=>$langs->trans("DateCreation"), 'checked'=>0, 'position'=>500), - 'p.tms'=>array('label'=>$langs->trans("DateModificationShort"), 'checked'=>0, 'position'=>500), - 'p.statut'=>array('label'=>$langs->trans("Status"), 'checked'=>1, 'position'=>1000), - ); - // 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]); - } - } $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage; $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields - print ''; + + print '
'; // Ligne des titres print ''; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 907c9c7b46b..e4bb572a3eb 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -2866,6 +2866,7 @@ abstract class CommonObject } else { + $this->errors[] = $this->db->lasterror(); return false; } } @@ -2903,6 +2904,7 @@ abstract class CommonObject } else { + $this->errors[] = $this->db->lasterror(); return -1; } } diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 393560b4640..2198cd9df13 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -76,7 +76,7 @@ class Form * @param string $htmlname Name of select field ('edit' prefix will be added) * @param string $preselected Name of Value to show/edit (not used in this function) * @param object $object Object - * @param boolean $perm Permission to allow button to edit parameter + * @param boolean $perm Permission to allow button to edit parameter. Set it to 0 to have a not edited field. * @param string $typeofdata Type of data ('string' by default, 'email', 'numeric:99', 'text' or 'textarea:rows:cols', 'day' or 'datepicker', 'ckeditor:dolibarr_zzz:width:height:savemethod:1:rows:cols', 'select;xxx[:class]'...) * @param string $moreparam More param to add on a href URL * @return string HTML edit field @@ -104,11 +104,11 @@ class Form } else { - $ret.='
'; + if (GETPOST('action') != 'edit'.$htmlname && $perm) $ret.=''; + if (GETPOST('action') != 'edit'.$htmlname && $perm) $ret.=''; if (GETPOST('action') != 'edit'.$htmlname && $perm) $ret.=''; - $ret.='
'; $ret.=$langs->trans($text); - $ret.='id.$moreparam.'">'.img_edit($langs->trans('Edit'),1).'
'; + if (GETPOST('action') != 'edit'.$htmlname && $perm) $ret.='
'; } return $ret; diff --git a/htdocs/core/class/menu.class.php b/htdocs/core/class/menu.class.php index 737e682bba3..0715c2fafdc 100644 --- a/htdocs/core/class/menu.class.php +++ b/htdocs/core/class/menu.class.php @@ -98,4 +98,18 @@ class Menu if (count($this->liste) > 1) array_pop($this->liste); } + /** + * Return number of visible entries (gray or not) + * + * @return int Number of visible (gray or not) menu entries + */ + function getNbOfVisibleMenuEntries() + { + $nb=0; + foreach($this->liste as $val) + { + if (! empty($val['enabled'])) $nb++; + } + return $nb; + } } diff --git a/htdocs/core/menus/standard/auguria_menu.php b/htdocs/core/menus/standard/auguria_menu.php index a7c701aaeff..ae173504ed6 100644 --- a/htdocs/core/menus/standard/auguria_menu.php +++ b/htdocs/core/menus/standard/auguria_menu.php @@ -157,9 +157,9 @@ class MenuManager /** * Show menu * - * @param string $mode 'top', 'left', 'jmobile' + * @param string $mode 'top', 'left', 'jmobile' * @param array $moredata An array with more data to output - * @return string + * @return int 0 or nb of top menu entries if $mode = 'topnb' */ function showmenu($mode, $moredata=null) { @@ -169,8 +169,8 @@ class MenuManager if ($this->type_user == 1) { - $conf->global->MAIN_SEARCHFORM_SOCIETE=0; - $conf->global->MAIN_SEARCHFORM_CONTACT=0; + $conf->global->MAIN_SEARCHFORM_SOCIETE_DISABLED=1; + $conf->global->MAIN_SEARCHFORM_CONTACT_DISABLED=1; } require_once DOL_DOCUMENT_ROOT.'/core/class/menu.class.php'; @@ -178,6 +178,13 @@ class MenuManager if ($mode == 'top') print_auguria_menu($this->db,$this->atarget,$this->type_user,$this->tabMenu,$this->menu,0); if ($mode == 'left') print_left_auguria_menu($this->db,$this->menu_array,$this->menu_array_after,$this->tabMenu,$this->menu,0,'','',$moredata); + + if ($mode == 'topnb') + { + print_auguria_menu($this->db,$this->atarget,$this->type_user,$this->tabMenu,$this->menu,1); + return $this->menu->getNbOfVisibleMenuEntries(); + } + if ($mode == 'jmobile') { print_auguria_menu($this->db,$this->atarget,$this->type_user,$this->tabMenu,$this->menu,1); diff --git a/htdocs/core/menus/standard/eldy_menu.php b/htdocs/core/menus/standard/eldy_menu.php index 4326de6d98f..354f7de1453 100644 --- a/htdocs/core/menus/standard/eldy_menu.php +++ b/htdocs/core/menus/standard/eldy_menu.php @@ -113,7 +113,7 @@ class MenuManager * * @param string $mode 'top', 'left', 'jmobile' * @param array $moredata An array with more data to output - * @return string + * @return int 0 or nb of top menu entries if $mode = 'topnb' */ function showmenu($mode, $moredata=null) { @@ -123,8 +123,8 @@ class MenuManager if ($this->type_user == 1) { - $conf->global->MAIN_SEARCHFORM_SOCIETE=0; - $conf->global->MAIN_SEARCHFORM_CONTACT=0; + $conf->global->MAIN_SEARCHFORM_SOCIETE_DISABLED=0; + $conf->global->MAIN_SEARCHFORM_CONTACT_DISABLED=1; } require_once DOL_DOCUMENT_ROOT.'/core/class/menu.class.php'; @@ -142,6 +142,12 @@ class MenuManager if ($mode == 'left') print_eldy_menu($this->db,$this->atarget,$this->type_user,$this->tabMenu,$this->menu,0); } + if ($mode == 'topnb') + { + print_eldy_menu($this->db,$this->atarget,$this->type_user,$this->tabMenu,$this->menu,1); + return $this->menu->getNbOfVisibleMenuEntries(); + } + if ($mode == 'jmobile') { print_eldy_menu($this->db,$this->atarget,$this->type_user,$this->tabMenu,$this->menu,1); @@ -238,6 +244,7 @@ class MenuManager unset($this->menu); //print 'xx'.$mode; + return 0; } } diff --git a/htdocs/core/menus/standard/empty.php b/htdocs/core/menus/standard/empty.php index e1b240a8e5e..60f9f3cec7f 100644 --- a/htdocs/core/menus/standard/empty.php +++ b/htdocs/core/menus/standard/empty.php @@ -62,7 +62,7 @@ class MenuManager * * @param string $mode 'top', 'left', 'jmobile' * @param array $moredata An array with more data to output - * @return string + * @return int 0 or nb of top menu entries if $mode = 'topnb' */ function showmenu($mode, $moredata=null) { @@ -78,6 +78,11 @@ class MenuManager $noout=0; if ($mode == 'jmobile') $noout=1; + if ($mode == 'topnb') + { + return 1; + } + if ($mode == 'top' || $mode == 'jmobile') { if (empty($noout)) print_start_menu_array_empty(); diff --git a/htdocs/filefunc.inc.php b/htdocs/filefunc.inc.php index 5a492940cf1..7abc17b49cd 100644 --- a/htdocs/filefunc.inc.php +++ b/htdocs/filefunc.inc.php @@ -208,7 +208,7 @@ define('MAIN_DB_PREFIX',$dolibarr_main_db_prefix); // Path to root libraries if (! defined('ADODB_PATH')) { define('ADODB_PATH', (!isset($dolibarr_lib_ADODB_PATH))?DOL_DOCUMENT_ROOT.'/includes/adodbtime/':(empty($dolibarr_lib_ADODB_PATH)?'':$dolibarr_lib_ADODB_PATH.'/')); } if (! defined('FPDF_PATH')) { define('FPDF_PATH', (empty($dolibarr_lib_FPDF_PATH))?DOL_DOCUMENT_ROOT.'/includes/fpdf/':$dolibarr_lib_FPDF_PATH.'/'); } // Used only for package that can't include tcpdf -if (! defined('TCPDF_PATH')) { define('TCPDF_PATH', (empty($dolibarr_lib_TCPDF_PATH))?DOL_DOCUMENT_ROOT.'/includes/tecnick.com/tcpdf/':$dolibarr_lib_TCPDF_PATH.'/'); } +if (! defined('TCPDF_PATH')) { define('TCPDF_PATH', (empty($dolibarr_lib_TCPDF_PATH))?DOL_DOCUMENT_ROOT.'/includes/tecnickcom/tcpdf/':$dolibarr_lib_TCPDF_PATH.'/'); } if (! defined('FPDI_PATH')) { define('FPDI_PATH', (empty($dolibarr_lib_FPDI_PATH))?DOL_DOCUMENT_ROOT.'/includes/fpdfi/':$dolibarr_lib_FPDI_PATH.'/'); } if (! defined('TCPDI_PATH')) { define('TCPDI_PATH', (empty($dolibarr_lib_TCPDI_PATH))?DOL_DOCUMENT_ROOT.'/includes/tcpdi/':$dolibarr_lib_TCPDI_PATH.'/'); } if (! defined('NUSOAP_PATH')) { define('NUSOAP_PATH', (!isset($dolibarr_lib_NUSOAP_PATH))?DOL_DOCUMENT_ROOT.'/includes/nusoap/lib/':(empty($dolibarr_lib_NUSOAP_PATH)?'':$dolibarr_lib_NUSOAP_PATH.'/')); } diff --git a/htdocs/hrm/employee/list.php b/htdocs/hrm/employee/list.php index 46c59e90937..86e1f3d10d5 100644 --- a/htdocs/hrm/employee/list.php +++ b/htdocs/hrm/employee/list.php @@ -169,8 +169,8 @@ if ($result) $employeestatic->email=$obj->email; $employeestatic->gender=$obj->gender; $employeestatic->societe_id=$obj->fk_soc; - $userstatic->firstname=$obj->firstname; - $userstatic->lastname=$obj->lastname; + $employeestatic->firstname=$obj->firstname; + $employeestatic->lastname=$obj->lastname; $li=$employeestatic->getNomUrl(1,'',0,0,24,1); @@ -203,8 +203,7 @@ if ($result) print ''; // Statut - $employeestatic->statut=$obj->statut; - print ''.$employeestatic->getLibStatut(5).''; + print ''.$employeestatic->getLibStatut(5).''; print ' '; print "\n"; $i++; diff --git a/htdocs/includes/adodbtime/adodb-time.inc.php b/htdocs/includes/adodbtime/adodb-time.inc.php index 1be5f4cd607..c74778bb991 100644 --- a/htdocs/includes/adodbtime/adodb-time.inc.php +++ b/htdocs/includes/adodbtime/adodb-time.inc.php @@ -57,7 +57,7 @@ adodb_mktime(0,0,0,10,15,1582) - adodb_mktime(0,0,0,10,4,1582) COPYRIGHT -(c) 2003-2005 John Lim and released under BSD-style license except for code by +(c) 2003-2014 John Lim and released under BSD-style license except for code by jackbbs, which includes adodb_mktime, adodb_get_gmt_diff, adodb_is_leap_year and originally found at http://www.php.net/manual/en/function.mktime.php @@ -73,6 +73,9 @@ These should be posted to the ADOdb forums at FUNCTION DESCRIPTIONS +** FUNCTION adodb_time() + +Returns the current time measured in the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT) as an unsigned integer. ** FUNCTION adodb_getdate($date=false) @@ -241,6 +244,14 @@ b. Implement daylight savings, which looks awfully complicated, see CHANGELOG +- 16 Jan 2011 0.36 +Added adodb_time() which returns current time. If > 2038, will return as float + +- 7 Feb 2011 0.35 +Changed adodb_date to be symmetric with adodb_mktime. See $jan1_71. fix for bc. + +- 13 July 2010 0.34 +Changed adodb_get_gm_diff to use DateTimeZone(). - 11 Feb 2008 0.33 * Bug in 0.32 fix for hour handling. Fixed. @@ -386,7 +397,7 @@ First implementation. /* Version Number */ -define('ADODB_DATE_VERSION',0.33); +define('ADODB_DATE_VERSION',0.35); $ADODB_DATETIME_CLASS = (PHP_VERSION >= 5.2); @@ -601,6 +612,12 @@ function adodb_date_test() else print "

Failed :-(

"; } +function adodb_time() +{ + $d = new DateTime(); + return $d->format('U'); +} + /** Returns day of week, 0 = Sunday,... 6=Saturday. Algorithm from PEAR::Date_Calc @@ -729,9 +746,17 @@ global $ADODB_DATETIME_CLASS; } else { if (isset($TZ)) return $TZ; $y = date('Y'); - $TZ = mktime(0,0,0,12,2,$y) - gmmktime(0,0,0,12,2,$y); + /* + if (function_exists('date_default_timezone_get') && function_exists('timezone_offset_get')) { + $tzonename = date_default_timezone_get(); + if ($tzonename) { + $tobj = new DateTimeZone($tzonename); + $TZ = -timezone_offset_get($tobj,new DateTime("now",$tzo)); + } + } + */ + if (empty($TZ)) $TZ = mktime(0,0,0,12,2,$y) - gmmktime(0,0,0,12,2,$y); } - return $TZ; } @@ -1006,7 +1031,6 @@ function adodb_tz_offset($gmt,$isphp5) return sprintf('%s%02d%02d',($gmt<=0)?'+':'-',floor($zhrs),($zhrs-$hrs)*60); else return sprintf('%s%02d%02d',($gmt<0)?'+':'-',floor($zhrs),($zhrs-$hrs)*60); - break; } @@ -1041,11 +1065,19 @@ function adodb_date($fmt,$d=false,$is_gmt=false) { static $daylight; global $ADODB_DATETIME_CLASS; +static $jan1_1971; + + + if (!isset($daylight)) { + $daylight = function_exists('adodb_daylight_sv'); + if (empty($jan1_1971)) $jan1_1971 = mktime(0,0,0,1,1,1971); // we only use date() when > 1970 as adodb_mktime() only uses mktime() when > 1970 + } if ($d === false) return ($is_gmt)? @gmdate($fmt): @date($fmt); if (!defined('ADODB_TEST_DATES')) { if ((abs($d) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range - if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= 0) // if windows, must be +ve integer + + if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= $jan1_1971) // if windows, must be +ve integer return ($is_gmt)? @gmdate($fmt,$d): @date($fmt,$d); } @@ -1054,7 +1086,6 @@ global $ADODB_DATETIME_CLASS; $arr = _adodb_getdate($d,true,$is_gmt); - if (!isset($daylight)) $daylight = function_exists('adodb_daylight_sv'); if ($daylight) adodb_daylight_sv($arr, $is_gmt); $year = $arr['year']; @@ -1075,6 +1106,9 @@ global $ADODB_DATETIME_CLASS; */ for ($i=0; $i < $max; $i++) { switch($fmt[$i]) { + case 'e': + $dates .= date('e'); + break; case 'T': if ($ADODB_DATETIME_CLASS) { $dt = new DateTime(); @@ -1215,7 +1249,7 @@ function adodb_mktime($hr,$min,$sec,$mon=false,$day=false,$year=false,$is_dst=fa // for windows, we don't check 1970 because with timezone differences, // 1 Jan 1970 could generate negative timestamp, which is illegal - $usephpfns = (1971 < $year && $year < 2038 + $usephpfns = (1970 < $year && $year < 2038 || !defined('ADODB_NO_NEGATIVE_TS') && (1901 < $year && $year < 2038) ); @@ -1422,5 +1456,3 @@ global $ADODB_DATE_LOCALE; $ret = adodb_date($fmtdate, $ts, $is_gmt); return $ret; } - -?> \ No newline at end of file diff --git a/htdocs/includes/ckeditor/ckeditor/README.md b/htdocs/includes/ckeditor/ckeditor/README.md index c5a55cd88f8..d6b5e2af515 100644 --- a/htdocs/includes/ckeditor/ckeditor/README.md +++ b/htdocs/includes/ckeditor/ckeditor/README.md @@ -1,39 +1,82 @@ -CKEditor 4 -========== +CKEditor 4 - Releases +===================== -Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. -http://ckeditor.com - See LICENSE.md for license information. +## Releases Code -CKEditor is a text editor to be used inside web pages. It's not a replacement -for desktop text editors like Word or OpenOffice, but a component to be used as -part of web applications and websites. +This repository contains the official release versions of [CKEditor](http://ckeditor.com). + +There are four versions for each release — `standard-all`, `basic`, `standard`, and `full`. +They differ in the number of plugins that are compiled into the main `ckeditor.js` file as well as the toolbar configuration. + +See the [comparison](http://ckeditor.com/presets) of the `basic`, `standard`, and `full` installation presets for more details. + +The `standard-all` build includes all official CKSource plugins with only those from the `standard` installation preset compiled into the `ckeditor.js` file and enabled in the configuration. + +All versions available in this repository were built using [CKBuilder](http://ckeditor.com/builder), so they are optimized and ready to be used in a production environment. ## Documentation -The full editor documentation is available online at the following address: -http://docs.ckeditor.com +Developer documentation for CKEditor is available online at: . ## Installation -Installing CKEditor is an easy task. Just follow these simple steps: +### Git clone - 1. **Download** the latest version from the CKEditor website: - http://ckeditor.com. You should have already completed this step, but be - sure you have the very latest version. - 2. **Extract** (decompress) the downloaded file into the root of your website. +To install one of the available releases, just clone this repository and switch to the respective branch (see next section): -**Note:** CKEditor is by default installed in the `ckeditor` folder. You can -place the files in whichever you want though. + git clone -b git://github.com/ckeditor/ckeditor-releases.git + +### Git submodule + +If you are using git for your project and you want to integrate CKEditor, we recommend to add this repository as a +[submodule](http://git-scm.com/book/en/Git-Tools-Submodules). + + git submodule add -b git://github.com/ckeditor/ckeditor-releases.git + git commit -m "Added CKEditor submodule in directory." + +### Using Package Managers + +See the [Installing CKEditor with Package Managers](http://docs.ckeditor.com/#!/guide/dev_package_managers) article for more details about installing CKEditor with Bower and Composer. + +## Repository Structure + +### Branches + +This repository contains the following branches: + + - `master` and `latest` – the latest release of the `standard-all` preset (including betas). + - `stable` – the latest stable release of the `standard-all` preset (non-beta). + - `A.B.x` (e.g. `4.3.x`) – the latest release of the `standard-all` preset in the `A.B` branch. + - `(basic|standard|full)/stable` – the latest stable release tag point (non-beta). + - `(basic|standard|full)/latest` – the latest release tag point (including betas). + - `(basic|standard|full)/A.B.x` (e.g. `basic/4.0.x`) – the latest releases in the `A.B` branch. + +### Tags + +**Since version 4.3.3** this repository uses the following tag naming rules: + + - `x.y.z` – contains the `standard-all` editor build, e.g. `4.3.3`, `4.4.0` etc. + - `(basic|standard|full)/x.y.z` – contains the editor build with a given preset, e.g. `basic/4.3.3`. + +The version numbers follow the [Semantic Versioning 2.0.0](http://semver.org/) scheme. + +Up to version **4.3.2** the tags were released in the following form `x.y[.z]/(basic|standard|full)`. +For example: `4.0/basic`, `4.0.1/standard`. This convention was changed in CKEditor 4.3.3 to conform to the Semantic Versioning scheme. ## Checking Your Installation -The editor comes with a few sample pages that can be used to verify that -installation proceeded properly. Take a look at the `samples` directory. +The editor comes with a few sample pages that can be used to verify if the installation succeeded. Take a look at the `samples` directory. -To test your installation, just call the following page at your website: +To test your installation, just call the following page for your website: http:////samples/index.html For example: http://www.example.com/ckeditor/samples/index.html + +### License + +Licensed under the GPL, LGPL, and MPL licenses, at your choice. + +Please check the `LICENSE.md` file for more information about the license. \ No newline at end of file diff --git a/htdocs/includes/ckeditor/ckeditor/_source/CHANGES.md b/htdocs/includes/ckeditor/ckeditor/_source/CHANGES.md deleted file mode 100644 index a5bec2ba830..00000000000 --- a/htdocs/includes/ckeditor/ckeditor/_source/CHANGES.md +++ /dev/null @@ -1,442 +0,0 @@ -CKEditor 4 Changelog -==================== - -## CKEditor 4.3.3 - -Fixed Issues: - -* [#11500](http://dev.ckeditor.com/ticket/11500): [Webkit/Blink] Fixed: Selection lost when setting data in another inline editor. Additionally, [`selection.removeAllRanges()`](http://docs.ckeditor.com/#!/api/CKEDITOR.dom.selection-method-removeAllRanges) is now scoped to selection's [root](http://docs.ckeditor.com/#!/api/CKEDITOR.dom.selection-property-root). -* [#11104](http://dev.ckeditor.com/ticket/11104): [IE] Fixed: Various issues with scrolling and selection when focusing widgets. -* [#11487](http://dev.ckeditor.com/ticket/11487): Moving mouse over the [Enhanced Image](http://ckeditor.com/addon/image2) widget will no longer change the value returned by the [`editor.checkDirty()`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-method-checkDirty) method. -* [#8673](http://dev.ckeditor.com/ticket/8673): [WebKit] Fixed: Cannot select and remove the [Page Break](http://ckeditor.com/addon/pagebreak). -* [#11413](http://dev.ckeditor.com/ticket/11413): Fixed: Incorrect [`editor.execCommand()`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-method-execCommand) behavior. -* [#11438](http://dev.ckeditor.com/ticket/11438): Splitting table cells vertically is no longer changing table structure. -* [#8899](http://dev.ckeditor.com/ticket/8899): Fixed: Links in the [About CKEditor](http://ckeditor.com/addon/about) dialog window now open in a new browser window or tab. -* [#11490](http://dev.ckeditor.com/ticket/11490): Fixed: [Menu button](http://ckeditor.com/addon/menubutton) panel not showing in the source mode. -* [#11417](http://dev.ckeditor.com/ticket/11417): The [`widget.doubleclick`](http://docs.ckeditor.com/#!/api/CKEDITOR.plugins.widget-event-doubleclick) event is not canceled anymore after editing was triggered. -* [#11253](http://dev.ckeditor.com/ticket/11253): [IE] Fixed: Clipped upload button in the [Enhanced Image](http://ckeditor.com/addon/image2) dialog window. -* [#11359](http://dev.ckeditor.com/ticket/11359): Standardized the way anchors are discovered by the [Link](http://ckeditor.com/addon/link) plugin. -* [#11058](http://dev.ckeditor.com/ticket/11058): [IE8] Fixed: Error when deleting a table row. -* [#11508](http://dev.ckeditor.com/ticket/11508): Fixed: [`htmlDataProcessor`](http://docs.ckeditor.com/#!/api/CKEDITOR.htmlDataProcessor) discovering protected attributes within other attributes' values. -* [#11533](http://dev.ckeditor.com/ticket/11533): Widgets: Avoid recurring upcasts if the DOM structure was modified during an upcast. -* [#11400](http://dev.ckeditor.com/ticket/11400): Fixed: The [`domObject.removeAllListeners()`](http://docs.ckeditor.com/#!/api/CKEDITOR.dom.domObject-method-removeAllListeners) method does not remove custom listeners completely. -* [#11493](http://dev.ckeditor.com/ticket/11493): Fixed: The [`selection.getRanges()`](http://docs.ckeditor.com/#!/api/CKEDITOR.dom.selection-method-getRanges) method does not override cached ranges when used with the `onlyEditables` argument. -* [#11390](http://dev.ckeditor.com/ticket/11390): [IE] All [XML](http://ckeditor.com/addon/xml) plugin [methods](http://docs.ckeditor.com/#!/api/CKEDITOR.xml) now work in IE10+. -* [#11542](http://dev.ckeditor.com/ticket/11542): [IE11] Fixed: Blurry toolbar icons when Right-to-Left UI language is set. -* [#11504](http://dev.ckeditor.com/ticket/11504): Fixed: When [`config.fullPage`](http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-fullPage) is set to `true`, entities are not encoded in editor output. -* [#11004](http://dev.ckeditor.com/ticket/11004): Integrated [Enhanced Image](http://ckeditor.com/addon/image2) dialog window with [Advanced Content Filter](http://docs.ckeditor.com/#!/guide/dev_advanced_content_filter). -* [#11439](http://dev.ckeditor.com/ticket/11439): Fixed: Properties get cloned in the Cell Properties dialog window if multiple cells are selected. - -## CKEditor 4.3.2 - -Fixed Issues: - -* [#11331](http://dev.ckeditor.com/ticket/11331): A menu button will have a changed label when selected instead of using the `aria-pressed` attribute. -* [#11177](http://dev.ckeditor.com/ticket/11177): Widget drag handler improvements: - * [#11176](http://dev.ckeditor.com/ticket/11176): Fixed: Initial position is not updated when the widget data object is empty. - * [#11001](http://dev.ckeditor.com/ticket/11001): Fixed: Multiple synchronous layout recalculations are caused by initial drag handler positioning causing performance issues. - * [#11161](http://dev.ckeditor.com/ticket/11161): Fixed: Drag handler is not repositioned in various situations. - * [#11281](http://dev.ckeditor.com/ticket/11281): Fixed: Drag handler and mask are duplicated after widget reinitialization. -* [#11207](http://dev.ckeditor.com/ticket/11207): [Firefox] Fixed: Misplaced [Enhanced Image](http://ckeditor.com/addon/image2) resizer in the inline editor. -* [#11102](http://dev.ckeditor.com/ticket/11102): `CKEDITOR.template` improvements: - * [#11102](http://dev.ckeditor.com/ticket/11102): Added newline character support. - * [#11216](http://dev.ckeditor.com/ticket/11216): Added "\\'" substring support. -* [#11121](http://dev.ckeditor.com/ticket/11121): [Firefox] Fixed: High Contrast mode is enabled when the editor is loaded in a hidden iframe. -* [#11350](http://dev.ckeditor.com/ticket/11350): The default value of [`config.contentsCss`](http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-contentsCss) is affected by [`CKEDITOR.getUrl()`](http://docs.ckeditor.com/#!/api/CKEDITOR-method-getUrl). -* [#11097](http://dev.ckeditor.com/ticket/11097): Improved the [Autogrow](http://ckeditor.com/addon/autogrow) plugin performance when dealing with very big tables. -* [#11290](http://dev.ckeditor.com/ticket/11290): Removed redundant code in the [Source Dialog](http://ckeditor.com/addon/sourcedialog) plugin. -* [#11133](http://dev.ckeditor.com/ticket/11133): [Page Break](http://ckeditor.com/addon/pagebreak) becomes editable if pasted. -* [#11126](http://dev.ckeditor.com/ticket/11126): Fixed: Native Undo executed once the bottom of the snapshot stack is reached. -* [#11131](http://dev.ckeditor.com/ticket/11131): [Div Editing Area](http://ckeditor.com/addon/divarea): Fixed: Error thrown when switching to source mode if the selection was in widget's nested editable. -* [#11139](http://dev.ckeditor.com/ticket/11139): [Div Editing Area](http://ckeditor.com/addon/divarea): Fixed: Elements Path is not cleared after switching to source mode. -* [#10778](http://dev.ckeditor.com/ticket/10778): Fixed a bug with range enlargement. The range no longer expands to visible whitespace. -* [#11146](http://dev.ckeditor.com/ticket/11146): [IE] Fixed: Preview window switches Internet Explorer to Quirks Mode. -* [#10762](http://dev.ckeditor.com/ticket/10762): [IE] Fixed: JavaScript code displayed in preview window's URL bar. -* [#11186](http://dev.ckeditor.com/ticket/11186): Introduced the [`widgets.repository.addUpcastCallback()`](http://docs.ckeditor.com/#!/api/CKEDITOR.plugins.widget.repository-method-addUpcastCallback) method that allows to block upcasting given element to a widget. -* [#11307](http://dev.ckeditor.com/ticket/11307): Fixed: Paste as Plain Text conflict with the [MooTools](http://mootools.net) library. -* [#11140](http://dev.ckeditor.com/ticket/11140): [IE11] Fixed: Anchors are not draggable. -* [#11379](http://dev.ckeditor.com/ticket/11379): Changed default contents `line-height` to unitless values to avoid huge text overlapping (like in [#9696](http://dev.ckeditor.com/ticket/9696)). -* [#10787](http://dev.ckeditor.com/ticket/10787): [Firefox] Fixed: Broken replacement of text while pasting into `div`-based editor. -* [#10884](http://dev.ckeditor.com/ticket/10884): Widgets integration with the [Show Blocks](http://ckeditor.com/addon/showblocks) plugin. -* [#11021](http://dev.ckeditor.com/ticket/11021): Fixed: An error thrown when selecting entire editable contents while fake selection is on. -* [#11086](http://dev.ckeditor.com/ticket/11086): [IE8] Re-enable inline widgets drag&drop in Internet Explorer 8. -* [#11372](http://dev.ckeditor.com/ticket/11372): Widgets: Special characters encoded twice in nested editables. -* [#10068](http://dev.ckeditor.com/ticket/10068): Fixed: Support for protocol-relative URLs. -* [#11283](http://dev.ckeditor.com/ticket/11283): [Enhanced Image](http://ckeditor.com/addon/image2): A `
` element with `text-align: center` and an image inside is not recognised correctly. -* [#11196](http://dev.ckeditor.com/ticket/11196): [Accessibility Instructions](http://ckeditor.com/addon/a11yhelp): Allowed additional keyboard button labels to be translated in the dialog window. - -## CKEditor 4.3.1 - -**Important Notes:** - -* To match the naming convention, the `language` button is now `Language` ([#11201](http://dev.ckeditor.com/ticket/11201)). -* [Enhanced Image](http://ckeditor.com/addon/image2) button, context menu, command, and icon names match those of the [Image](http://ckeditor.com/addon/image) plugin ([#11222](http://dev.ckeditor.com/ticket/11222)). - -Fixed Issues: - -* [#11244](http://dev.ckeditor.com/ticket/11244): Changed: The [`widget.repository.checkWidgets()`](http://docs.ckeditor.com/#!/api/CKEDITOR.plugins.widget.repository-method-checkWidgets) method now fires the [`widget.repository.checkWidgets`](http://docs.ckeditor.com/#!/api/CKEDITOR.plugins.widget.repository-event-checkWidgets) event, so from CKEditor 4.3.1 it is preferred to use the method rather than fire the event. -* [#11171](http://dev.ckeditor.com/ticket/11171): Fixed: [`editor.insertElement()`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-method-insertElement) and [`editor.insertText()`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-method-insertText) methods do not call the [`widget.repository.checkWidgets()`](http://docs.ckeditor.com/#!/api/CKEDITOR.plugins.widget.repository-method-checkWidgets) method. -* [#11085](http://dev.ckeditor.com/ticket/11085): [IE8] Replaced preview generated by the [Mathematical Formulas](http://ckeditor.com/addon/mathjax) widget with a placeholder. -* [#11044](http://dev.ckeditor.com/ticket/11044): Enhanced WAI-ARIA support for the [Language](http://ckeditor.com/addon/language) plugin drop-down menu. -* [#11075](http://dev.ckeditor.com/ticket/11075): With drop-down menu button focused, pressing the *Down Arrow* key will now open the menu and focus its first option. -* [#11165](http://dev.ckeditor.com/ticket/11165): Fixed: The [File Browser](http://ckeditor.com/addon/filebrowser) plugin cannot be removed from the editor. -* [#11159](http://dev.ckeditor.com/ticket/11159): [IE9-10] [Enhanced Image](http://ckeditor.com/addon/image2): Fixed buggy discovery of image dimensions. -* [#11101](http://dev.ckeditor.com/ticket/11101): Drop-down lists no longer break when given double quotes. -* [#11077](http://dev.ckeditor.com/ticket/11077): [Enhanced Image](http://ckeditor.com/addon/image2): Empty undo step recorded when resizing the image. -* [#10853](http://dev.ckeditor.com/ticket/10853): [Enhanced Image](http://ckeditor.com/addon/image2): Widget has paragraph wrapper when de-captioning unaligned image. -* [#11198](http://dev.ckeditor.com/ticket/11198): Widgets: Drag handler is not fully visible when an inline widget is in a heading. -* [#11132](http://dev.ckeditor.com/ticket/11132): [Firefox] Fixed: Caret is lost after drag and drop of an inline widget. -* [#11182](http://dev.ckeditor.com/ticket/11182): [IE10-11] Fixed: Editor crashes (IE11) or works with minor issues (IE10) if a page is loaded in Quirks Mode. See [`env.quirks`](http://docs.ckeditor.com/#!/api/CKEDITOR.env-property-quirks) for more details. -* [#11204](http://dev.ckeditor.com/ticket/11204): Added `figure` and `figcaption` styles to the `contents.css` file so [Enhanced Image](http://ckeditor.com/addon/image2) looks nicer. -* [#11202](http://dev.ckeditor.com/ticket/11202): Fixed: No newline in [BBCode](http://ckeditor.com/addon/bbcode) mode. -* [#10890](http://dev.ckeditor.com/ticket/10890): Fixed: Error thrown when pressing the *Delete* key in a list item. -* [#10055](http://dev.ckeditor.com/ticket/10055): [IE8-10] Fixed: *Delete* pressed on a selected image causes the browser to go back. -* [#11183](http://dev.ckeditor.com/ticket/11183): Fixed: Inserting a horizontal rule or a table in multiple row selection causes a browser crash. Additionally, the [`editor.insertElement()`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-method-insertElement) method does not insert the element into every range of a selection any more. -* [#11042](http://dev.ckeditor.com/ticket/11042): Fixed: Selection made on an element containing a non-editable element was not auto faked. -* [#11125](http://dev.ckeditor.com/ticket/11125): Fixed: Keyboard navigation through menu and drop-down items will now cycle. -* [#11011](http://dev.ckeditor.com/ticket/11011): Fixed: The [`editor.applyStyle()`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-method-applyStyle) method removes attributes from nested elements. -* [#11179](http://dev.ckeditor.com/ticket/11179): Fixed: [`editor.destroy()`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-method-destroy) does not cleanup content generated by the [Table Resize](http://ckeditor.com/addon/tableresize) plugin for inline editors. -* [#11237](http://dev.ckeditor.com/ticket/11237): Fixed: Table border attribute value is deleted when pasting content from Microsoft Word. -* [#11250](http://dev.ckeditor.com/ticket/11250): Fixed: HTML entities inside the ` - * ... - * CKEDITOR.replace( 'myfield' ); - * - * var textarea = document.body.appendChild( document.createElement( 'textarea' ) ); - * CKEDITOR.replace( textarea ); - * - * @param {Object/String} element The DOM element (textarea), its ID, or name. - * @param {Object} [config] The specific configuration to apply to this - * editor instance. Configuration set here will override the global CKEditor settings - * (see {@link CKEDITOR.config}). - * @returns {CKEDITOR.editor} The editor instance created. - */ - CKEDITOR.replace = function( element, config ) { - return createInstance( element, config, null, CKEDITOR.ELEMENT_MODE_REPLACE ); - }; - - /** - * Creates a new editor instance at the end of a specific DOM element. - * - *
- * ... - * CKEDITOR.appendTo( 'editorSpace' ); - * - * @param {Object/String} element The DOM element, its ID, or name. - * @param {Object} [config] The specific configuration to apply to this - * editor instance. Configuration set here will override the global CKEditor settings - * (see {@link CKEDITOR.config}). - * @param {String} [data] Since 3.3. Initial value for the instance. - * @returns {CKEDITOR.editor} The editor instance created. - */ - CKEDITOR.appendTo = function( element, config, data ) - { - return createInstance( element, config, data, CKEDITOR.ELEMENT_MODE_APPENDTO ); - }; - - /** - * Replaces all ` - data = protectElements( data, protectTextareaRegex ); - - // Before anything, we must protect the URL attributes as the - // browser may changing them when setting the innerHTML later in - // the code. - data = protectAttributes( data ); - - // Protect elements than can't be set inside a DIV. E.g. IE removes - // style tags from innerHTML. (#3710) - data = protectElements( data, protectElementsRegex ); - - // Certain elements has problem to go through DOM operation, protect - // them by prefixing 'cke' namespace. (#3591) - data = protectElementsNames( data ); - - // All none-IE browsers ignore self-closed custom elements, - // protecting them into open-close. (#3591) - data = protectSelfClosingElements( data ); - - // Compensate one leading line break after
 open as browsers
-			// eat it up. (#5789)
-			data = protectPreFormatted( data );
-
-			var fixBin = evtData.context || editor.editable().getName(),
-				isPre;
-
-			// Old IEs loose formats when load html into 
.
-			if ( CKEDITOR.env.ie && CKEDITOR.env.version < 9 && fixBin == 'pre' ) {
-				fixBin = 'div';
-				data = '
' + data + '
'; - isPre = 1; - } - - // Call the browser to help us fixing a possibly invalid HTML - // structure. - var el = editor.document.createElement( fixBin ); - // Add fake character to workaround IE comments bug. (#3801) - el.setHtml( 'a' + data ); - data = el.getHtml().substr( 1 ); - - // Restore shortly protected attribute names. - data = data.replace( new RegExp( ' data-cke-' + CKEDITOR.rnd + '-', 'ig' ), ' ' ); - - isPre && ( data = data.replace( /^
|<\/pre>$/gi, '' ) );
-
-			// Unprotect "some" of the protected elements at this point.
-			data = unprotectElementNames( data );
-
-			data = unprotectElements( data );
-
-			// Restore the comments that have been protected, in this way they
-			// can be properly filtered.
-			data = unprotectRealComments( data );
-
-			// Now use our parser to make further fixes to the structure, as
-			// well as apply the filter.
-			evtData.dataValue = CKEDITOR.htmlParser.fragment.fromHtml(
-				data, evtData.context, evtData.fixForBody === false ? false : getFixBodyTag( evtData.enterMode, editor.config.autoParagraph ) );
-		}, null, null, 5 );
-
-		// Filter incoming "data".
-		// Add element filter before htmlDataProcessor.dataFilter when purifying input data to correct html.
-		editor.on( 'toHtml', function( evt ) {
-			if ( evt.data.filter.applyTo( evt.data.dataValue, true, evt.data.dontFilter, evt.data.enterMode ) )
-				editor.fire( 'dataFiltered' );
-		}, null, null, 6 );
-
-		editor.on( 'toHtml', function( evt ) {
-			evt.data.dataValue.filterChildren( that.dataFilter, true );
-		}, null, null, 10 );
-
-		editor.on( 'toHtml', function( evt ) {
-			var evtData = evt.data,
-				data = evtData.dataValue,
-				writer = new CKEDITOR.htmlParser.basicWriter();
-
-			data.writeChildrenHtml( writer );
-			data = writer.getHtml( true );
-
-			// Protect the real comments again.
-			evtData.dataValue = protectRealComments( data );
-		}, null, null, 15 );
-
-
-		editor.on( 'toDataFormat', function( evt ) {
-			var data = evt.data.dataValue;
-
-			// #10854 - we need to strip leading blockless 
which FF adds - // automatically when editable contains only non-editable content. - // We do that for every browser (so it's a constant behavior) and - // not in BR mode, in which chance of valid leading blockless
is higher. - if ( evt.data.enterMode != CKEDITOR.ENTER_BR ) - data = data.replace( /^
/i, '' ); - - evt.data.dataValue = CKEDITOR.htmlParser.fragment.fromHtml( - data, evt.data.context, getFixBodyTag( evt.data.enterMode, editor.config.autoParagraph ) ); - }, null, null, 5 ); - - editor.on( 'toDataFormat', function( evt ) { - evt.data.dataValue.filterChildren( that.htmlFilter, true ); - }, null, null, 10 ); - - // Transform outcoming "data". - // Add element filter after htmlDataProcessor.htmlFilter when preparing output data HTML. - editor.on( 'toDataFormat', function( evt ) { - evt.data.filter.applyTo( evt.data.dataValue, false, true ); - }, null, null, 11 ); - - editor.on( 'toDataFormat', function( evt ) { - var data = evt.data.dataValue, - writer = that.writer; - - writer.reset(); - data.writeChildrenHtml( writer ); - data = writer.getHtml( true ); - - // Restore those non-HTML protected source. (#4475,#4880) - data = unprotectRealComments( data ); - data = unprotectSource( data, editor ); - - evt.data.dataValue = data; - }, null, null, 15 ); - }; - - CKEDITOR.htmlDataProcessor.prototype = { - /** - * Processes the input (potentially malformed) HTML to a purified form which - * is suitable for using in the WYSIWYG editable. - * - * This method fires the {@link CKEDITOR.editor#toHtml} event which makes it possible - * to hook into the process at various stages. - * - * **Note:** Since CKEditor 4.3 the signature of this method changed and all options - * are now grouped in one `options` object. Previously `context`, `fixForBody` and `dontFilter` - * were passed separately. - * - * @param {String} data The raw data. - * @param {Object} [options] The options object. - * @param {String} [options.context] The tag name of a context element within which - * the input is to be processed, default to be the editable element. - * If `null` is passed, then data will be parsed without context (as children of {@link CKEDITOR.htmlParser.fragment}). - * See {@link CKEDITOR.htmlParser.fragment#fromHtml} for more details. - * @param {Boolean} [options.fixForBody=true] Whether to trigger the auto paragraph for non-block contents. - * @param {CKEDITOR.filter} [options.filter] When specified, instead of using the {@link CKEDITOR.editor#filter main filter}, - * passed instance will be used to filter the content. - * @param {Boolean} [options.dontFilter] Do not filter data with {@link CKEDITOR.filter} (note: transformations - * will be still applied). - * @param {Number} [options.enterMode] When specified it will be used instead of the {@link CKEDITOR.editor#enterMode main enterMode}. - * @returns {String} - */ - toHtml: function( data, options, fixForBody, dontFilter ) { - var editor = this.editor, - context, filter, enterMode; - - // Typeof null == 'object', so check truthiness of options too. - if ( options && typeof options == 'object' ) { - context = options.context; - fixForBody = options.fixForBody; - dontFilter = options.dontFilter; - filter = options.filter; - enterMode = options.enterMode; - } - // Backward compatibility. Since CKEDITOR 4.3 every option was a separate argument. - else - context = options; - - // Fall back to the editable as context if not specified. - if ( !context && context !== null ) - context = editor.editable().getName(); - - return editor.fire( 'toHtml', { - dataValue: data, - context: context, - fixForBody: fixForBody, - dontFilter: dontFilter, - filter: filter || editor.filter, - enterMode: enterMode || editor.enterMode - } ).dataValue; - }, - - /** - * See {@link CKEDITOR.dataProcessor#toDataFormat}. - * - * This method fires the {@link CKEDITOR.editor#toDataFormat} event which makes it possible - * to hook into the process at various steps. - * - * @param {String} html - * @param {Object} [options] The options object. - * @param {String} [options.context] The tag name of a context element within which - * the input is to be processed, default to be the editable element. - * @param {CKEDITOR.filter} [options.filter] When specified, instead of using the {@link CKEDITOR.editor#filter main filter}, - * passed instance will be used to apply content transformations to the content. - * @param {Number} [options.enterMode] When specified it will be used instead of the {@link CKEDITOR.editor#enterMode main enterMode}. - * @returns {String} - */ - toDataFormat: function( html, options ) { - var context, filter, enterMode; - - // Do not shorten this to `options && options.xxx`, because - // falsy `options` will be passed instead of undefined. - if ( options ) { - context = options.context; - filter = options.filter; - enterMode = options.enterMode; - } - - // Fall back to the editable as context if not specified. - if ( !context && context !== null ) - context = this.editor.editable().getName(); - - return this.editor.fire( 'toDataFormat', { - dataValue: html, - filter: filter || this.editor.filter, - context: context, - enterMode: enterMode || this.editor.enterMode - } ).dataValue; - } - }; - - // Produce a set of filtering rules that handles bogus and filler node at the - // end of block/pseudo block, in the following consequence: - // 1. elements: - this filter removes any bogus node, then check - // if it's an empty block that requires a filler. - // 2. elements:
- After cleaned with bogus, this filter checks the real - // line-break BR to compensate a filler after it. - // - // Terms definitions: - // filler: An element that's either
or &NBSP; at the end of block that established line height. - // bogus: Whenever a filler is proceeded with inline content, it becomes a bogus which is subjected to be removed. - // - // Various forms of the filler: - // In output HTML: Filler should be consistently &NBSP;
at the end of block is always considered as bogus. - // In Wysiwyg HTML: Browser dependent - see env.needsBrFiller. Either BR for when needsBrFiller is true, or &NBSP; otherwise. - //
is NEVER considered as bogus when needsBrFiller is true. - function createBogusAndFillerRules( editor, type ) { - function createFiller( isOutput ) { - return isOutput || CKEDITOR.env.needsNbspFiller ? - new CKEDITOR.htmlParser.text( '\xa0' ) : - new CKEDITOR.htmlParser.element( 'br', { 'data-cke-bogus': 1 } ); - } - - // This text block filter, remove any bogus and create the filler on demand. - function blockFilter( isOutput, fillEmptyBlock ) { - - return function( block ) { - - // DO NOT apply the filer if it's a fragment node. - if ( block.type == CKEDITOR.NODE_DOCUMENT_FRAGMENT ) - return; - - cleanBogus( block ); - - // [Opera] it's mandatory for the filler to present inside of empty block when in WYSIWYG. - if ( ( ( CKEDITOR.env.opera && !isOutput ) || - ( typeof fillEmptyBlock == 'function' ? fillEmptyBlock( block ) !== false : fillEmptyBlock ) ) && - isEmptyBlockNeedFiller( block ) ) - { - block.add( createFiller( isOutput ) ); - } - }; - } - - // Append a filler right after the last line-break BR, found at the end of block. - function brFilter( isOutput ) { - return function( br ) { - - // DO NOT apply the filer if parent's a fragment node. - if ( br.parent.type == CKEDITOR.NODE_DOCUMENT_FRAGMENT ) - return; - - var attrs = br.attributes; - // Dismiss BRs that are either bogus or eol marker. - if ( 'data-cke-bogus' in attrs || - 'data-cke-eol' in attrs ) { - delete attrs [ 'data-cke-bogus' ]; - return; - } - - // Judge the tail line-break BR, and to insert bogus after it. - var next = getNext( br ), previous = getPrevious( br ); - - if ( !next && isBlockBoundary( br.parent ) ) - append( br.parent, createFiller( isOutput ) ); - else if ( isBlockBoundary( next ) && previous && !isBlockBoundary( previous ) ) - createFiller( isOutput ).insertBefore( next ); - }; - } - - // Determinate whether this node is potentially a bogus node. - function maybeBogus( node, atBlockEnd ) { - - // BR that's not from IE<11 DOM, except for a EOL marker. - if ( !( isOutput && !CKEDITOR.env.needsBrFiller ) && - node.type == CKEDITOR.NODE_ELEMENT && node.name == 'br' && - !node.attributes[ 'data-cke-eol' ] ) - return true; - - var match; - // NBSP, possibly. - if ( node.type == CKEDITOR.NODE_TEXT && - ( match = node.value.match( tailNbspRegex ) ) ) - { - // We need to separate tail NBSP out of a text node, for later removal. - if ( match.index ) { - ( new CKEDITOR.htmlParser.text( node.value.substring( 0, match.index ) ) ).insertBefore( node ); - node.value = match[ 0 ]; - } - - // From IE<11 DOM, at the end of a text block, or before block boundary. - if ( !CKEDITOR.env.needsBrFiller && isOutput && ( !atBlockEnd || node.parent.name in textBlockTags ) ) - return true; - - // From the output. - if ( !isOutput ) { - var previous = node.previous; - - // Following a line-break at the end of block. - if ( previous && previous.name == 'br' ) - return true; - - // Or a single NBSP between two blocks. - if ( !previous || isBlockBoundary( previous ) ) - return true; - } - } - - return false; - } - - // Removes all bogus inside of this block, and to convert fillers into the proper form. - function cleanBogus( block ) { - var bogus = []; - var last = getLast( block ), node, previous; - if ( last ) { - - // Check for bogus at the end of this block. - // e.g.

foo

- maybeBogus( last, 1 ) && bogus.push( last ); - - while ( last ) { - - // Check for bogus at the end of any pseudo block contained. - if ( isBlockBoundary( last ) && - ( node = getPrevious( last ) ) && - maybeBogus( node ) ) - { - // Bogus must have inline proceeding, instead single BR between two blocks, - // is considered as filler, e.g.


- if ( ( previous = getPrevious( node ) ) && !isBlockBoundary( previous ) ) - bogus.push( node ); - // Convert the filler into appropriate form. - else { - createFiller( isOutput ).insertAfter( node ); - node.remove(); - } - } - - last = last.previous; - } - } - - // Now remove all bogus collected from above. - for ( var i = 0 ; i < bogus.length ; i++ ) - bogus[ i ].remove(); - } - - // Judge whether it's an empty block that requires a filler node. - function isEmptyBlockNeedFiller( block ) { - - // DO NOT fill empty editable in IE<11. - if ( !isOutput && !CKEDITOR.env.needsBrFiller && block.type == CKEDITOR.NODE_DOCUMENT_FRAGMENT ) - return false; - - // 1. For IE version >=8, empty blocks are displayed correctly themself in wysiwiyg; - // 2. For the rest, at least table cell and list item need no filler space. (#6248) - if ( !isOutput && !CKEDITOR.env.needsBrFiller && - ( document.documentMode > 7 || - block.name in CKEDITOR.dtd.tr || - block.name in CKEDITOR.dtd.$listItem ) ) { - return false; - } - - var last = getLast( block ); - return !last || block.name == 'form' && last.name == 'input' ; - } - - var rules = { elements: {} }; - var isOutput = type == 'html'; - - // Build the list of text blocks. - var textBlockTags = CKEDITOR.tools.extend( {}, blockLikeTags ); - for ( var i in textBlockTags ) { - if ( !( '#' in dtd[ i ] ) ) - delete textBlockTags[ i ]; - } - - for ( i in textBlockTags ) - rules.elements[ i ] = blockFilter( isOutput, editor.config.fillEmptyBlocks !== false ); - - // Editable element is to be checked separately. - rules.root = blockFilter( isOutput ); - rules.elements.br = brFilter( isOutput ); - return rules; - } - - function getFixBodyTag( enterMode, autoParagraph ) { - return ( enterMode != CKEDITOR.ENTER_BR && autoParagraph !== false ) ? enterMode == CKEDITOR.ENTER_DIV ? 'div' : 'p' : false; - } - - // Regex to scan for   at the end of blocks, which are actually placeholders. - // Safari transforms the   to \xa0. (#4172) - var tailNbspRegex = /(?: |\xa0)$/; - - var protectedSourceMarker = '{cke_protected}'; - - function getLast( node ) { - var last = node.children[ node.children.length - 1 ]; - while ( last && isEmpty( last ) ) - last = last.previous; - return last; - } - - function getNext( node ) { - var next = node.next; - while ( next && isEmpty( next ) ) - next = next.next; - return next; - } - - function getPrevious( node ) { - var previous = node.previous; - while ( previous && isEmpty( previous ) ) - previous = previous.previous; - return previous; - } - - // Judge whether the node is an ghost node to be ignored, when traversing. - function isEmpty( node ) { - return node.type == CKEDITOR.NODE_TEXT && - !CKEDITOR.tools.trim( node.value ) || - node.type == CKEDITOR.NODE_ELEMENT && - node.attributes[ 'data-cke-bookmark' ]; - } - - // Judge whether the node is a block-like element. - function isBlockBoundary( node ) { - return node && - ( node.type == CKEDITOR.NODE_ELEMENT && node.name in blockLikeTags || - node.type == CKEDITOR.NODE_DOCUMENT_FRAGMENT ); - } - - function append( parent, node ) { - var last = parent.children[ parent.children.length -1 ]; - parent.children.push( node ); - node.parent = parent; - if ( last ) { - last.next = node; - node.previous = last; - } - } - - function getNodeIndex( node ) { - return node.parent ? node.getIndex() : -1; - } - - var dtd = CKEDITOR.dtd, - // Define orders of table elements. - tableOrder = [ 'caption', 'colgroup', 'col', 'thead', 'tfoot', 'tbody' ], - // List of all block elements. - blockLikeTags = CKEDITOR.tools.extend( {}, dtd.$blockLimit, dtd.$block ); - - // - // DATA filter rules ------------------------------------------------------ - // - - var defaultDataFilterRulesEditableOnly = { - elements: { - input: protectReadOnly, - textarea: protectReadOnly - } - }; - - // These rules will also be applied to non-editable content. - var defaultDataFilterRulesForAll = { - attributeNames: [ - // Event attributes (onXYZ) must not be directly set. They can become - // active in the editing area (IE|WebKit). - [ ( /^on/ ), 'data-cke-pa-on' ], - - // Don't let some old expando enter editor. Concerns only IE8, - // but for consistency remove on all browsers. - [ ( /^data-cke-expando$/ ), '' ] - ] - }; - - // Disable form elements editing mode provided by some browsers. (#5746) - function protectReadOnly( element ) { - var attrs = element.attributes; - - // We should flag that the element was locked by our code so - // it'll be editable by the editor functions (#6046). - if ( attrs.contenteditable != 'false' ) - attrs[ 'data-cke-editable' ] = attrs.contenteditable ? 'true' : 1; - - attrs.contenteditable = 'false'; - } - - // - // HTML filter rules ------------------------------------------------------ - // - - var defaultHtmlFilterRulesEditableOnly = { - elements: { - embed: function( element ) { - var parent = element.parent; - - // If the is child of a , copy the width - // and height attributes from it. - if ( parent && parent.name == 'object' ) { - var parentWidth = parent.attributes.width, - parentHeight = parent.attributes.height; - if ( parentWidth ) - element.attributes.width = parentWidth; - if ( parentHeight ) - element.attributes.height = parentHeight; - } - }, - - // Remove empty link but not empty anchor. (#3829) - a: function( element ) { - if ( !( element.children.length || element.attributes.name || element.attributes[ 'data-cke-saved-name' ] ) ) - return false; - } - } - }; - - // These rules will also be applied to non-editable content. - var defaultHtmlFilterRulesForAll = { - elementNames: [ - // Remove the "cke:" namespace prefix. - [ ( /^cke:/ ), '' ], - - // Ignore tags. - [ ( /^\?xml:namespace$/ ), '' ] - ], - - attributeNames: [ - // Attributes saved for changes and protected attributes. - [ ( /^data-cke-(saved|pa)-/ ), '' ], - - // All "data-cke-" attributes are to be ignored. - [ ( /^data-cke-.*/ ), '' ], - - [ 'hidefocus', '' ] - ], - - elements: { - $: function( element ) { - var attribs = element.attributes; - - if ( attribs ) { - // Elements marked as temporary are to be ignored. - if ( attribs[ 'data-cke-temp' ] ) - return false; - - // Remove duplicated attributes - #3789. - var attributeNames = [ 'name', 'href', 'src' ], - savedAttributeName; - for ( var i = 0; i < attributeNames.length; i++ ) { - savedAttributeName = 'data-cke-saved-' + attributeNames[ i ]; - savedAttributeName in attribs && ( delete attribs[ attributeNames[ i ] ] ); - } - } - - return element; - }, - - // The contents of table should be in correct order (#4809). - table: function( element ) { - // Clone the array as it would become empty during the sort call. - var children = element.children.slice( 0 ); - children.sort( function( node1, node2 ) { - var index1, index2; - - // Compare in the predefined order. - if ( node1.type == CKEDITOR.NODE_ELEMENT && - node2.type == node1.type ) { - index1 = CKEDITOR.tools.indexOf( tableOrder, node1.name ); - index2 = CKEDITOR.tools.indexOf( tableOrder, node2.name ); - } - - // Make sure the sort is stable, if no order can be established above. - if ( !( index1 > -1 && index2 > -1 && index1 != index2 ) ) { - index1 = getNodeIndex( node1 ); - index2 = getNodeIndex( node2 ); - } - - return index1 > index2 ? 1 : -1; - } ); - }, - - // Restore param elements into self-closing. - param: function( param ) { - param.children = []; - param.isEmpty = true; - return param; - }, - - // Remove dummy span in webkit. - span: function( element ) { - if ( element.attributes[ 'class' ] == 'Apple-style-span' ) - delete element.name; - }, - - html: function( element ) { - delete element.attributes.contenteditable; - delete element.attributes[ 'class' ]; - }, - - body: function( element ) { - delete element.attributes.spellcheck; - delete element.attributes.contenteditable; - }, - - style: function( element ) { - var child = element.children[ 0 ]; - if ( child && child.value ) - child.value = CKEDITOR.tools.trim( child.value ); - - if ( !element.attributes.type ) - element.attributes.type = 'text/css'; - }, - - title: function( element ) { - var titleText = element.children[ 0 ]; - - // Append text-node to title tag if not present (i.e. non-IEs) (#9882). - !titleText && append( element, titleText = new CKEDITOR.htmlParser.text() ); - - // Transfer data-saved title to title tag. - titleText.value = element.attributes[ 'data-cke-title' ] || ''; - }, - - input: unprotectReadyOnly, - textarea: unprotectReadyOnly - }, - - attributes: { - 'class': function( value, element ) { - // Remove all class names starting with "cke_". - return CKEDITOR.tools.ltrim( value.replace( /(?:^|\s+)cke_[^\s]*/g, '' ) ) || false; - } - } - }; - - if ( CKEDITOR.env.ie ) { - // IE outputs style attribute in capital letters. We should convert - // them back to lower case, while not hurting the values (#5930) - defaultHtmlFilterRulesForAll.attributes.style = function( value, element ) { - return value.replace( /(^|;)([^\:]+)/g, function( match ) { - return match.toLowerCase(); - } ); - }; - } - - // Disable form elements editing mode provided by some browsers. (#5746) - function unprotectReadyOnly( element ) { - var attrs = element.attributes; - switch ( attrs[ 'data-cke-editable' ] ) { - case 'true': - attrs.contenteditable = 'true'; - break; - case '1': - delete attrs.contenteditable; - break; - } - } - - // - // Preprocessor filters --------------------------------------------------- - // - - var protectElementRegex = /<(a|area|img|input|source)\b([^>]*)>/gi, - // Be greedy while looking for protected attributes. This will let us avoid an unfortunate - // situation when "nested attributes", which may appear valid, are also protected. - // I.e. if we consider the following HTML: - // - // - // - // then the "non-greedy match" returns: - // - // 'href' => '"X"' // It's wrong! Href is not an attribute of . - // - // while greedy match returns: - // - // 'data-x' => '<a href="X"' - // - // which, can be easily filtered out (#11508). - protectAttributeRegex = /([\w-]+)\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|(?:[^ "'>]+))/gi, - protectAttributeNameRegex = /^(href|src|name)$/i; - - // Note: we use lazy star '*?' to prevent eating everything up to the last occurrence of or . - var protectElementsRegex = /(?:])[^>]*>[\s\S]*?<\/style>)|(?:<(:?link|meta|base)[^>]*>)/gi, - protectTextareaRegex = /(])[^>]*>)([\s\S]*?)(?:<\/textarea>)/gi, - encodedElementsRegex = /([^<]*)<\/cke:encoded>/gi; - - var protectElementNamesRegex = /(<\/?)((?:object|embed|param|html|body|head|title)[^>]*>)/gi, - unprotectElementNamesRegex = /(<\/?)cke:((?:html|body|head|title)[^>]*>)/gi; - - var protectSelfClosingRegex = /]*?)\/?>(?!\s*<\/cke:\1)/gi; - - function protectAttributes( html ) { - return html.replace( protectElementRegex, function( element, tag, attributes ) { - return '<' + tag + attributes.replace( protectAttributeRegex, function( fullAttr, attrName ) { - // Avoid corrupting the inline event attributes (#7243). - // We should not rewrite the existed protected attributes, e.g. clipboard content from editor. (#5218) - if ( protectAttributeNameRegex.test( attrName ) && attributes.indexOf( 'data-cke-saved-' + attrName ) == -1 ) - return ' data-cke-saved-' + fullAttr + ' data-cke-' + CKEDITOR.rnd + '-' + fullAttr; - - return fullAttr; - } ) + '>'; - } ); - } - - function protectElements( html, regex ) { - return html.replace( regex, function( match, tag, content ) { - // Encode < and > in textarea because this won't be done by a browser, since - // textarea will be protected during passing data through fix bin. - if ( match.indexOf( '/g, '>' ) + ''; - - return '' + encodeURIComponent( match ) + ''; - } ); - } - - function unprotectElements( html ) { - return html.replace( encodedElementsRegex, function( match, encoded ) { - return decodeURIComponent( encoded ); - } ); - } - - function protectElementsNames( html ) { - return html.replace( protectElementNamesRegex, '$1cke:$2' ); - } - - function unprotectElementNames( html ) { - return html.replace( unprotectElementNamesRegex, '$1$2' ); - } - - function protectSelfClosingElements( html ) { - return html.replace( protectSelfClosingRegex, '' ); - } - - function protectPreFormatted( html ) { - return CKEDITOR.env.opera ? html : html.replace( /(]*>)(\r\n|\n)/g, '$1$2$2' ); - } - - function protectRealComments( html ) { - return html.replace( //g, function( match ) { - return ''; - } ); - } - - function unprotectRealComments( html ) { - return html.replace( //g, function( match, data ) { - return decodeURIComponent( data ); - } ); - } - - function unprotectSource( html, editor ) { - var store = editor._.dataStore; - - return html.replace( //g, function( match, data ) { - return decodeURIComponent( data ); - } ).replace( /\{cke_protected_(\d+)\}/g, function( match, id ) { - return store && store[ id ] || ''; - } ); - } - - function protectSource( data, editor ) { - var protectedHtml = [], - protectRegexes = editor.config.protectedSource, - store = editor._.dataStore || ( editor._.dataStore = { id: 1 } ), - tempRegex = /<\!--\{cke_temp(comment)?\}(\d*?)-->/g; - - var regexes = [ - // Script tags will also be forced to be protected, otherwise - // IE will execute them. - ( //gi ), - - //