From 568d5cb5ba8f2eddc729a4b6d362f24fe6fcf1eb Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 23 Jan 2015 18:47:47 +0100 Subject: [PATCH 001/173] Fixed: Tracking number restored on PDF shipments Fixed: Translation Conflicts: htdocs/langs/en_US/agenda.lang --- ChangeLog | 1 + .../modules/expedition/doc/pdf_merou.modules.php | 16 ++++++++-------- .../expedition/doc/pdf_rouget.modules.php | 14 ++++++++++---- htdocs/expedition/class/expedition.class.php | 2 +- htdocs/langs/en_US/admin.lang | 4 ++-- htdocs/langs/en_US/agenda.lang | 4 ++-- htdocs/langs/en_US/sendings.lang | 8 ++++---- htdocs/langs/en_US/stocks.lang | 2 +- 8 files changed, 29 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2643b444876..ace6a13363d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -17,6 +17,7 @@ English Dolibarr ChangeLog - Fix: [ bug #1783 ] SQL error when enabling 3rd party module with PostgreSQL and MySQL strict mode ON - Fix: [ bug #1717 ] Sorting unpaid invoices by amount received brings due amount - Fix: [ bug #1784 ] MOTD doesn't show up in Amarok theme +- Fix: Tracking number not visible on shipment pdf ***** ChangeLog for 3.6.2 compared to 3.6.1 ***** - Fix: fix ErrorBadValueForParamNotAString error message in price customer multiprice. diff --git a/htdocs/core/modules/expedition/doc/pdf_merou.modules.php b/htdocs/core/modules/expedition/doc/pdf_merou.modules.php index cc9d884a831..8fab26f211c 100644 --- a/htdocs/core/modules/expedition/doc/pdf_merou.modules.php +++ b/htdocs/core/modules/expedition/doc/pdf_merou.modules.php @@ -534,13 +534,18 @@ class pdf_merou extends ModelePdfExpedition // Date Expedition $Yoff = $Yoff+7; - $pdf->SetXY($blSocX-80,$blSocY+20); + $pdf->SetXY($blSocX-80,$blSocY+17); $pdf->SetFont('','B', $default_font_size - 2); $pdf->SetTextColor(0,0,0); $pdf->MultiCell(50, 8, $outputlangs->transnoentities("Date")." : " . dol_print_date($object->date_delivery,'day',false,$outputlangs,true), '', 'L'); + $pdf->SetXY($blSocX-80,$blSocY+20); + $pdf->SetFont('','B', $default_font_size - 2); + $pdf->SetTextColor(0,0,0); + $pdf->MultiCell(50, 8, $outputlangs->transnoentities("TrackingNumber")." : " . $object->tracking_number, '', 'L'); + // Deliverer - $pdf->SetXY($blSocX-80,$blSocY+23); + $pdf->SetXY($blSocX-80,$blSocY+24); $pdf->SetFont('','', $default_font_size - 2); $pdf->SetTextColor(0,0,0); @@ -554,13 +559,8 @@ class pdf_merou extends ModelePdfExpedition // Get code using getLabelFromKey $code=$outputlangs->getLabelFromKey($this->db,$object->shipping_method_id,'c_shipment_mode','rowid','code'); $label=$outputlangs->trans("SendingMethod".strtoupper($code))." :"; + $pdf->writeHTMLCell(50, 8, '', '', $label." ".$object->tracking_url, '', 'L'); } - else - { - $label=$outputlangs->transnoentities("Deliverer"); - } - - $pdf->writeHTMLCell(50, 8, '', '', $label." ".$object->tracking_url, '', 'L'); } } else diff --git a/htdocs/core/modules/expedition/doc/pdf_rouget.modules.php b/htdocs/core/modules/expedition/doc/pdf_rouget.modules.php index eedc4b91827..12fd723bf9b 100644 --- a/htdocs/core/modules/expedition/doc/pdf_rouget.modules.php +++ b/htdocs/core/modules/expedition/doc/pdf_rouget.modules.php @@ -180,11 +180,17 @@ class pdf_rouget extends ModelePdfExpedition $tab_height = 130; $tab_height_newpage = 150; - if (! empty($object->note_public) || (! empty($object->tracking_number) && ! empty($object->shipping_method_id))) + if (! empty($object->note_public) || ! empty($object->tracking_number)) { $tab_top = 88; $tab_top_alt = $tab_top; + $pdf->SetFont('','B', $default_font_size - 2); + $pdf->writeHTMLCell(60, 4, $this->posxdesc-1, $tab_top-1, $outputlangs->transnoentities("TrackingNumber")." : " . $object->tracking_number, 0, 1, false, true, 'L'); + + $tab_top_alt = $pdf->GetY(); + //$tab_top_alt += 1; + // Tracking number if (! empty($object->tracking_number)) { @@ -198,14 +204,14 @@ class pdf_rouget extends ModelePdfExpedition $label=$outputlangs->trans("LinkToTrackYourPackage")."
"; $label.=$outputlangs->trans("SendingMethod".strtoupper($code))." :"; $pdf->SetFont('','B', $default_font_size - 2); - $pdf->writeHTMLCell(60, 7, $this->posxdesc-1, $tab_top-1, $label." ".$object->tracking_url, 0, 1, false, true, 'L'); + $pdf->writeHTMLCell(60, 4, $this->posxdesc-1, $tab_top+6, $label." ".$object->tracking_url, 0, 1, false, true, 'L'); - $tab_top_alt += 7; + $tab_top_alt = $pdf->GetY(); } } } - // Affiche notes + // Notes if (! empty($object->note_public)) { $pdf->SetFont('','', $default_font_size - 1); // Dans boucle pour gerer multi-page diff --git a/htdocs/expedition/class/expedition.class.php b/htdocs/expedition/class/expedition.class.php index 1045bed42be..e120ce24a40 100644 --- a/htdocs/expedition/class/expedition.class.php +++ b/htdocs/expedition/class/expedition.class.php @@ -1494,7 +1494,7 @@ class Expedition extends CommonObject } /** - * Get tracking url status + * Forge an set tracking url * * @param string $value Value * @return void diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 2aa09fd867d..57d496bd0f4 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1374,9 +1374,9 @@ ListOfAvailableNotifications=List of available notifications (This list depends SendingsSetup=Sending module setup SendingsReceiptModel=Sending receipt model SendingsNumberingModules=Sendings numbering modules -SendingsAbility=Support sendings sheets for customer deliveries +SendingsAbility=Support shipment sheets for customer deliveries NoNeedForDeliveryReceipts=In most cases, sendings receipts are used both as sheets for customer deliveries (list of products to send) and sheets that is recevied and signed by customer. So product deliveries receipts is a duplicated feature and is rarely activated. -FreeLegalTextOnShippings=Free text on shippings +FreeLegalTextOnShippings=Free text on shipments ##### Deliveries ##### DeliveryOrderNumberingModules=Products deliveries receipt numbering module DeliveryOrderModel=Products deliveries receipt model diff --git a/htdocs/langs/en_US/agenda.lang b/htdocs/langs/en_US/agenda.lang index 687e3cae146..52b2e8128fd 100644 --- a/htdocs/langs/en_US/agenda.lang +++ b/htdocs/langs/en_US/agenda.lang @@ -52,8 +52,8 @@ OrderSentByEMail=Customer order %s sent by EMail InvoiceSentByEMail=Customer invoice %s sent by EMail SupplierOrderSentByEMail=Supplier order %s sent by EMail SupplierInvoiceSentByEMail=Supplier invoice %s sent by EMail -ShippingSentByEMail=Shipping %s sent by EMail -ShippingValidated= Shipping %s validated +ShippingSentByEMail=Shipment %s sent by EMail +ShippingValidated= Shipment %s validated InterventionSentByEMail=Intervention %s sent by EMail NewCompanyToDolibarr= Third party created DateActionPlannedStart= Planned start date diff --git a/htdocs/langs/en_US/sendings.lang b/htdocs/langs/en_US/sendings.lang index 039d47f6aa9..861feeaf8d0 100644 --- a/htdocs/langs/en_US/sendings.lang +++ b/htdocs/langs/en_US/sendings.lang @@ -4,7 +4,7 @@ Sending=Shipment Sendings=Shipments Shipment=Shipment Shipments=Shipments -Receivings=Receivings +Receivings=Receipts SendingsArea=Shipments area ListOfSendings=List of shipments SendingMethod=Shipping method @@ -14,7 +14,7 @@ SearchASending=Search for shipment StatisticsOfSendings=Statistics for shipments NbOfSendings=Number of shipments NumberOfShipmentsByMonth=Number of shipments by month -SendingCard=Shipping card +SendingCard=Shipment card NewSending=New shipment CreateASending=Create a shipment CreateSending=Create shipment @@ -37,7 +37,7 @@ StatusSendingCanceledShort=Canceled StatusSendingDraftShort=Draft StatusSendingValidatedShort=Validated StatusSendingProcessedShort=Processed -SendingSheet=Sending sheet +SendingSheet=Shipment sheet Carriers=Carriers Carrier=Carrier CarriersArea=Carriers area @@ -58,7 +58,7 @@ SendShippingRef=Send shipment %s ActionsOnShipping=Events on shipment LinkToTrackYourPackage=Link to track your package ShipmentCreationIsDoneFromOrder=For the moment, creation of a new shipment is done from the order card. -RelatedShippings=Related shippings +RelatedShippings=Related shipments ShipmentLine=Shipment line CarrierList=List of transporters diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang index 7a08148c9ce..63c118dd6e2 100644 --- a/htdocs/langs/en_US/stocks.lang +++ b/htdocs/langs/en_US/stocks.lang @@ -116,7 +116,7 @@ MassMovement=Mass movement MassStockMovement=Mass stock movement SelectProductInAndOutWareHouse=Select a product, a quantity, a source warehouse and a target warehouse, then click "%s". Once this is done for all required movements, click onto "%s". RecordMovement=Record transfert -ReceivingForSameOrder=Receivings for this order +ReceivingForSameOrder=Receipts for this order StockMovementRecorded=Stock movements recorded RuleForStockAvailability=Rules on stock requirements StockMustBeEnoughForInvoice=Stock level must be enough to add product/service into invoice From 11dd32a8fd7d7d29061145203e7a329762d8d051 Mon Sep 17 00:00:00 2001 From: Maxime Kohlhaas Date: Mon, 26 Jan 2015 23:37:25 +0100 Subject: [PATCH 002/173] FIXED Import module was not working with multi-company and importing everything in entity 1 --- htdocs/core/modules/import/import_csv.modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/import/import_csv.modules.php b/htdocs/core/modules/import/import_csv.modules.php index e83f812e8c4..da8d57395bc 100644 --- a/htdocs/core/modules/import/import_csv.modules.php +++ b/htdocs/core/modules/import/import_csv.modules.php @@ -607,7 +607,7 @@ class ImportCsv extends ModeleImports //var_dump($objimport->array_import_convertvalue); exit; // Build SQL request - if (empty($tablewithentity[$tablename])) + if (empty($tablewithentity_cache[$tablename])) { $sql ='INSERT INTO '.$tablename.'('.$listfields.', import_key'; if (! empty($objimport->array_import_tables_creator[0][$alias])) $sql.=', '.$objimport->array_import_tables_creator[0][$alias]; From 04f83ae4ff9feddbf567dc1c94f41b083ee03cb7 Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Wed, 28 Jan 2015 16:19:56 +0100 Subject: [PATCH 003/173] FIX: always show fournprice select --- htdocs/core/tpl/objectline_edit.tpl.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/tpl/objectline_edit.tpl.php b/htdocs/core/tpl/objectline_edit.tpl.php index d48abbc0aa1..3f9bd972122 100644 --- a/htdocs/core/tpl/objectline_edit.tpl.php +++ b/htdocs/core/tpl/objectline_edit.tpl.php @@ -128,7 +128,7 @@ $coldisplay=-1; // We remove first td margin->enabled)) { ?> - + rights->margins->creer) { From 87b75126aa2cbc5bbe5704bd926557aceeac3a7c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 31 Jan 2015 16:52:34 +0100 Subject: [PATCH 004/173] Fix missing set into specimen --- htdocs/comm/action/class/actioncomm.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index 360f38c3f45..96135cd3569 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -1060,6 +1060,7 @@ class ActionComm extends CommonObject $this->datef=$now; $this->author=$user; $this->usermod=$user; + $this->usertodo=$user; $this->fulldayevent=0; $this->punctual=0; $this->percentage=0; From ef354834943a7af57c792a3e7d84cedca88ee8dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Sun, 1 Feb 2015 12:58:54 +0100 Subject: [PATCH 005/173] Fix: [ bug #1819 ] SQL error when searching for an invoice payment --- ChangeLog | 1 + htdocs/compta/paiement/liste.php | 17 +++++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index ace6a13363d..ab0f89efd60 100644 --- a/ChangeLog +++ b/ChangeLog @@ -18,6 +18,7 @@ English Dolibarr ChangeLog - Fix: [ bug #1717 ] Sorting unpaid invoices by amount received brings due amount - Fix: [ bug #1784 ] MOTD doesn't show up in Amarok theme - Fix: Tracking number not visible on shipment pdf +- Fix: [ bug #1819 ] SQL error when searching for an invoice payment ***** ChangeLog for 3.6.2 compared to 3.6.1 ***** - Fix: fix ErrorBadValueForParamNotAString error message in price customer multiprice. diff --git a/htdocs/compta/paiement/liste.php b/htdocs/compta/paiement/liste.php index 6e3e1bc54ff..26f5c6eb5da 100644 --- a/htdocs/compta/paiement/liste.php +++ b/htdocs/compta/paiement/liste.php @@ -3,6 +3,7 @@ * Copyright (C) 2004-2011 Laurent Destailleur * Copyright (C) 2005-2009 Regis Houssin * Copyright (C) 2013 Cédric Salvador + * Copyright (C) 2015 Marcos García * * 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 @@ -53,6 +54,8 @@ $limit = $conf->liste_limit; if (! $sortorder) $sortorder="DESC"; if (! $sortfield) $sortfield="p.rowid"; +$search_ref = GETPOST("search_ref",'int'); +$search_account = GETPOST("search_account",'int'); @@ -109,11 +112,13 @@ else if ($userid == -1) $sql.= " AND f.fk_user_author IS NULL"; else $sql.= " AND f.fk_user_author = ".$userid; } + + // Search criteria - if (GETPOST("search_ref")) $sql .=" AND p.rowid=".GETPOST("search_ref",'int'); - if (GETPOST("search_account") > 0) $sql .=" AND b.fk_account=".GETPOST("search_account",'int'); - if (GETPOST("search_paymenttype") != "") $sql .=" AND c.code='".GETPOST("search_paymenttype")."'"; - if (GETPOST("search_amount")) $sql .=" AND p.amount=".price2num(GETPOST("search_amount")); + if ($search_ref) $sql .=" AND p.rowid=".$search_ref; + if ($search_account > 0) $sql .=" AND b.fk_account=".$search_account; + if (GETPOST("search_paymenttype") != "") $sql .=" AND c.code='".$db->escape(GETPOST("search_paymenttype"))."'"; + if (GETPOST("search_amount")) $sql .=" AND p.amount='".$db->escape(price2num(GETPOST("search_amount")))."'"; if (GETPOST("search_company")) $sql .= natural_search('s.nom', GETPOST('search_company')); } $sql.= $db->order($sortfield,$sortorder); @@ -129,7 +134,7 @@ if ($resql) $paramlist=''; $paramlist.=(GETPOST("orphelins")?"&orphelins=1":""); - $paramlist.=($_REQUEST["search_ref"]?"&search_ref=".$_REQUEST["search_ref"]:""); + $paramlist.=($search_ref?"&search_ref=".$search_ref:""); $paramlist.=($_REQUEST["search_company"]?"&search_company=".$_REQUEST["search_company"]:""); $paramlist.=($_REQUEST["search_amount"]?"&search_amount=".$_REQUEST["search_amount"]:""); @@ -154,7 +159,7 @@ if ($resql) // Lines for filters fields print ''; print ''; - print ''; + print ''; print ''; print ' '; print ''; From 0c6364403850cb293ed92b9e1906a58b2f70862e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Sun, 1 Feb 2015 13:26:30 +0100 Subject: [PATCH 006/173] Fix: [ bug #1819 ] SQL error when searching for an invoice payment --- ChangeLog | 1 + htdocs/comm/mailing/fiche.php | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index ace6a13363d..a3b356e2436 100644 --- a/ChangeLog +++ b/ChangeLog @@ -18,6 +18,7 @@ English Dolibarr ChangeLog - Fix: [ bug #1717 ] Sorting unpaid invoices by amount received brings due amount - Fix: [ bug #1784 ] MOTD doesn't show up in Amarok theme - Fix: Tracking number not visible on shipment pdf +- Fix: [ bug #1812 ] SQL Error message while sending emailing with PostgreSQL datatabase ***** ChangeLog for 3.6.2 compared to 3.6.1 ***** - Fix: fix ErrorBadValueForParamNotAString error message in price customer multiprice. diff --git a/htdocs/comm/mailing/fiche.php b/htdocs/comm/mailing/fiche.php index 6e7546fb70d..97f06b3d9ba 100644 --- a/htdocs/comm/mailing/fiche.php +++ b/htdocs/comm/mailing/fiche.php @@ -188,7 +188,7 @@ if (empty($reshook)) { $now=dol_now(); // Positionne date debut envoi - $sql="UPDATE ".MAIN_DB_PREFIX."mailing SET date_envoi=".$db->idate($now)." WHERE rowid=".$object->id; + $sql="UPDATE ".MAIN_DB_PREFIX."mailing SET date_envoi='".$db->idate($now)."' WHERE rowid=".$object->id; $resql2=$db->query($sql); if (! $resql2) { @@ -284,7 +284,7 @@ if (empty($reshook)) { dol_syslog("comm/mailing/fiche.php: ok for #".$i.($mail->error?' - '.$mail->error:''), LOG_DEBUG); $sql="UPDATE ".MAIN_DB_PREFIX."mailing_cibles"; - $sql.=" SET statut=1, date_envoi=".$db->idate($now)." WHERE rowid=".$obj->rowid; + $sql.=" SET statut=1, date_envoi='".$db->idate($now)."' WHERE rowid=".$obj->rowid; $resql2=$db->query($sql); if (! $resql2) { From a9ba2f317986ca4542dbdcdda07504ad0691d98d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Mon, 2 Feb 2015 11:48:57 +0100 Subject: [PATCH 007/173] Fix: [ bug #1810 ] [pgsql] Error while upgrading from 3.6 to 3.7 --- htdocs/core/db/pgsql.class.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/core/db/pgsql.class.php b/htdocs/core/db/pgsql.class.php index 7381fd77b93..58e79da87b9 100644 --- a/htdocs/core/db/pgsql.class.php +++ b/htdocs/core/db/pgsql.class.php @@ -7,6 +7,7 @@ * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2012 Yann Droneaud * Copyright (C) 2012 Florian Henry + * Copyright (C) 2015 Marcos García * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -255,7 +256,7 @@ class DoliDBPgsql extends DoliDB $newreg3=preg_replace('/ NOT NULL/i','',$newreg3); $newreg3=preg_replace('/ NULL/i','',$newreg3); $newreg3=preg_replace('/ DEFAULT 0/i','',$newreg3); - $newreg3=preg_replace('/ DEFAULT \'[0-9a-zA-Z_@]*\'/i','',$newreg3); + $newreg3=preg_replace('/ DEFAULT \'?[0-9a-zA-Z_@]*\'?/i','',$newreg3); $line.= "ALTER TABLE ".$reg[1]." ALTER COLUMN ".$reg[2]." TYPE ".$newreg3; // TODO Add alter to set default value or null/not null if there is this in $reg[3] } From fb865e818490ba2008d2d44fc1a4a5737e4e5478 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Doursenaud?= Date: Mon, 2 Feb 2015 17:08:59 +0100 Subject: [PATCH 008/173] FIXED Removed deprecated forcing SSLv3 for CURL Since the Poodle vulnerability, SSLv3 has been supersedded by TLS. Many services do not offer SSLv3 anymore. CURL has also been patched in PHP so it now auto-negociates the most appropriate protocol. This prevented most API calls from working. --- htdocs/core/lib/geturl.lib.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/core/lib/geturl.lib.php b/htdocs/core/lib/geturl.lib.php index 8a9ac1385be..e4c3625257d 100644 --- a/htdocs/core/lib/geturl.lib.php +++ b/htdocs/core/lib/geturl.lib.php @@ -52,7 +52,6 @@ function getURLContent($url,$postorget='GET',$param='',$followlocation=1,$addhea exit;*/ curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_VERBOSE, 1); - curl_setopt($ch, CURLOPT_SSLVERSION, 3); // Force SSLv3 curl_setopt($ch, CURLOPT_USERAGENT, 'Dolibarr geturl function'); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, ($followlocation?true:false)); From 14a078c9a7b32f13cca4d33c80aae25df2892d7b Mon Sep 17 00:00:00 2001 From: aspangaro Date: Tue, 3 Feb 2015 06:39:44 +0100 Subject: [PATCH 009/173] FIXED Accountancy clean code --- htdocs/accountancy/admin/export.php | 35 +++++++------ htdocs/accountancy/bookkeeping/list.php | 4 +- htdocs/accountancy/journal/bankjournal.php | 44 ++++++++-------- htdocs/accountancy/journal/cashjournal.php | 50 +++++++++--------- .../accountancy/journal/purchasesjournal.php | 36 ++++++------- htdocs/accountancy/journal/sellsjournal.php | 52 ++++++++++--------- htdocs/core/modules/modAccounting.class.php | 2 +- htdocs/langs/en_US/accountancy.lang | 4 +- 8 files changed, 119 insertions(+), 108 deletions(-) diff --git a/htdocs/accountancy/admin/export.php b/htdocs/accountancy/admin/export.php index 8fd0795c262..2954047e310 100644 --- a/htdocs/accountancy/admin/export.php +++ b/htdocs/accountancy/admin/export.php @@ -42,7 +42,7 @@ if (!$user->admin) $action = GETPOST('action', 'alpha'); -// Other parameters ACCOUNTING_* +// Other parameters ACCOUNTING_EXPORT_* $list = array ( 'ACCOUNTING_EXPORT_SEPARATORCSV', 'ACCOUNTING_EXPORT_DATE', @@ -114,20 +114,24 @@ print ''; $var = ! $var; print ''; -print "" . $langs->trans("Selectmodelcsv") . ""; -print ""; -print '"; print ""; print ""; @@ -143,6 +147,7 @@ if ($num) { print ''; print '' . $langs->trans('OtherOptions') . ''; print "\n"; + if ($conf->global->ACCOUNTING_EXPORT_MODELCSV > 1) print '' . $langs->trans('OptionsDeactivatedForThisExportModel') . ''; } foreach ( $list as $key ) { @@ -152,7 +157,7 @@ foreach ( $list as $key ) { // Param $label = $langs->trans($key); - print '' . $label . ''; + print '' . $label . ''; // Value print ''; @@ -163,7 +168,7 @@ foreach ( $list as $key ) { print ''; print "\n"; -print '
'; +print '
'; llxFooter(); $db->close(); \ No newline at end of file diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index f1dc892c10f..6c06c2ba3d7 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -75,7 +75,7 @@ if ($action == 'delbookkeeping') { setEventMessage($object->errors, 'errors'); } } -} // export csv +} // Export else if ($action == 'export_csv') { header('Content-Type: text/csv'); @@ -160,7 +160,7 @@ else { print '
'; print ''; print ''; - print ''; + print ''; print '
'; print ''; diff --git a/htdocs/accountancy/journal/bankjournal.php b/htdocs/accountancy/journal/bankjournal.php index 95a00eaf950..5fc98690933 100644 --- a/htdocs/accountancy/journal/bankjournal.php +++ b/htdocs/accountancy/journal/bankjournal.php @@ -4,7 +4,7 @@ * Copyright (C) 2011 Juanjo Menent * Copyright (C) 2012 Regis Houssin * Copyright (C) 2013 Christophe Battarel - * Copyright (C) 2013-2014 Alexandre Spangaro + * Copyright (C) 2013-2015 Alexandre Spangaro * Copyright (C) 2013-2014 Florian Henry * Copyright (C) 2013-2014 Olivier Geffroy * @@ -99,10 +99,10 @@ $idpays = $p[0]; $sql = "SELECT b.rowid , b.dateo as do, b.datev as dv, b.amount, b.label, b.rappro, b.num_releve, b.num_chq, b.fk_type, soc.code_compta, ba.courant,"; $sql .= " soc.code_compta_fournisseur, soc.rowid as socid, soc.nom as name, ba.account_number, bu1.type as typeop"; -$sql .= " FROM " . MAIN_DB_PREFIX . "bank b"; -$sql .= " JOIN " . MAIN_DB_PREFIX . "bank_account ba on b.fk_account=ba.rowid"; -$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url bu1 ON bu1.fk_bank = b.rowid AND bu1.type='company'"; -$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe soc on bu1.url_id=soc.rowid"; +$sql .= " FROM " . MAIN_DB_PREFIX . "bank as b"; +$sql .= " JOIN " . MAIN_DB_PREFIX . "bank_account as ba on b.fk_account=ba.rowid"; +$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url as bu1 ON bu1.fk_bank = b.rowid AND bu1.type='company'"; +$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe as soc on bu1.url_id=soc.rowid"; // To isolate the cash of the other accounts $sql .= " WHERE ba.courant <> 2"; $sql .= " AND ba.rowid=".$id_accountancy_journal; @@ -169,10 +169,12 @@ if ($result) { } $links = $object->get_url($obj->rowid); + foreach ( $links as $key => $val ) { $tabtype[$obj->rowid] = $links[$key]['type']; + if ($links[$key]['type'] == 'payment') { $paymentstatic->id = $links[$key]['url_id']; @@ -401,18 +403,21 @@ if ($action == 'writeBookKeeping') setEventMessage($langs->trans('Success'), 'mesgs'); } } -// export csv +// Export if ($action == 'export_csv') { $sep = $conf->global->ACCOUNTING_EXPORT_SEPARATORCSV; + $bank_journal = $conf->global->ACCOUNTING_BANK_JOURNAL; header('Content-Type: text/csv'); header('Content-Disposition: attachment;filename=journal_banque.csv'); $companystatic = new Client($db); - if ($conf->global->ACCOUNTING_EXPORT_MODELCSV == 1) // Modèle Export Cegid Expert + if ($conf->global->ACCOUNTING_EXPORT_MODELCSV == 2) // Model Cegid Expert Export { + $sep = ";"; + foreach ( $tabpay as $key => $val ) { $date = dol_print_date($db->jdate($val["date"]), '%d%m%Y'); @@ -420,23 +425,23 @@ if ($action == 'export_csv') $companystatic->name = $tabcompany[$key]['name']; // Bank - print $date . $sep; - print $conf->global->ACCOUNTING_BANK_JOURNAL . $sep; foreach ( $tabbq[$key] as $k => $mt ) { + print $date . $sep; + print $bank_journal . $sep; print length_accountg(html_entity_decode($k)) . $sep; print $sep; print ($mt < 0 ? 'C' : 'D') . $sep; print ($mt <= 0 ? price(- $mt) : $mt) . $sep; print $val["type_payment"] . $sep; - print $sep; + print $val["ref"] . $sep; + print "\n"; } - print "\n"; // Third party foreach ( $tabtp[$key] as $k => $mt ) { if ($mt) { print $date . $sep; - print $conf->global->ACCOUNTING_BANK_JOURNAL . $sep; + print $bank_journal . $sep; if ($val["lib"] == '(SupplierInvoicePayment)') { print length_accountg($conf->global->ACCOUNTING_ACCOUNT_SUPPLIER) . $sep; } else { @@ -446,12 +451,12 @@ if ($action == 'export_csv') print ($mt < 0 ? 'D' : 'C') . $sep; print ($mt <= 0 ? price(- $mt) : $mt) . $sep; print $val["type_payment"] . $sep; - print $sep; + print $val["ref"] . $sep; print "\n"; } } } - } else // Modèle Export Classique + } else // Model Classic Export { foreach ( $tabpay as $key => $val ) { $date = dol_print_date($db->jdate($val["date"]), 'day'); @@ -459,24 +464,22 @@ if ($action == 'export_csv') $companystatic->id = $tabcompany[$key]['id']; $companystatic->name = $tabcompany[$key]['name']; - print '"' . $date . '"' . $sep; - print '"' . $val["type_payment"] . '"' . $sep; - // Bank foreach ( $tabbq[$key] as $k => $mt ) { + print '"' . $date . '"' . $sep; + print '"' . $val["type_payment"] . '"' . $sep; print '"' . length_accountg(html_entity_decode($k)) . '"' . $sep; print '"' . $langs->trans("Bank") . '"' . $sep; print '"' . ($mt >= 0 ? price($mt) : '') . '"' . $sep; print '"' . ($mt < 0 ? price(- $mt) : '') . '"'; + print "\n"; } - print "\n"; // Third party foreach ( $tabtp[$key] as $k => $mt ) { if ($mt) { print '"' . $date . '"' . $sep; print '"' . $val["type_payment"] . '"' . $sep; - print '"' . length_accounta(html_entity_decode($k)) . '"' . $sep; print '"' . $companystatic->name . '"' . $sep; print '"' . ($mt < 0 ? price(- $mt) : '') . '"' . $sep; @@ -503,7 +506,7 @@ else $period = $form->select_date($date_start, 'date_start', 0, 0, 0, '', 1, 0, 1) . ' - ' . $form->select_date($date_end, 'date_end', 0, 0, 0, '', 1, 0, 1); report_header($namereport, $namelink, $period, $periodlink, $description, $builddate, $exportlink, array('action' => '')); - print ''; + print ''; print ''; @@ -586,5 +589,4 @@ else // End of page llxFooter(); } - $db->close(); diff --git a/htdocs/accountancy/journal/cashjournal.php b/htdocs/accountancy/journal/cashjournal.php index 51b8625f9b3..bbd74a8c29c 100644 --- a/htdocs/accountancy/journal/cashjournal.php +++ b/htdocs/accountancy/journal/cashjournal.php @@ -4,7 +4,7 @@ * Copyright (C) 2011 Juanjo Menent * Copyright (C) 2012 Regis Houssin * Copyright (C) 2013 Christophe Battarel - * Copyright (C) 2013-2014 Alexandre Spangaro + * Copyright (C) 2013-2015 Alexandre Spangaro * Copyright (C) 2013-2014 Florian Henry * Copyright (C) 2013-2014 Olivier Geffroy * @@ -91,10 +91,10 @@ $idpays = $p[0]; $sql = "SELECT b.rowid , b.dateo as do, b.datev as dv, b.amount, b.label, b.rappro, b.num_releve, b.num_chq, b.fk_type, soc.code_compta, ba.courant,"; $sql .= " soc.code_compta_fournisseur, soc.rowid as socid, soc.nom as name, ba.account_number, bu1.type as typeop"; -$sql .= " FROM " . MAIN_DB_PREFIX . "bank b"; -$sql .= " JOIN " . MAIN_DB_PREFIX . "bank_account ba on b.fk_account=ba.rowid"; -$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url bu1 ON bu1.fk_bank = b.rowid AND bu1.type='company'"; -$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe soc on bu1.url_id=soc.rowid"; +$sql .= " FROM " . MAIN_DB_PREFIX . "bank as b"; +$sql .= " JOIN " . MAIN_DB_PREFIX . "bank_account as ba on b.fk_account=ba.rowid"; +$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url as bu1 ON bu1.fk_bank = b.rowid AND bu1.type='company'"; +$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe as soc on bu1.url_id=soc.rowid"; // Code opération type caisse $sql .= " WHERE ba.courant = 2"; @@ -365,67 +365,69 @@ if ($action == 'writeBookKeeping') { setEventMessage($langs->trans('Success'), 'mesgs'); } } -// export csv +// Export if ($action == 'export_csv') { $sep = $conf->global->ACCOUNTING_EXPORT_SEPARATORCSV; + $cash_journal = $conf->global->ACCOUNTING_CASH_JOURNAL; header('Content-Type: text/csv'); header('Content-Disposition:attachment;filename=journal_caisse.csv'); - if ($conf->global->ACCOUNTING_EXPORT_MODELCSV == 1) // Modèle Export Cegid Expert + if ($conf->global->ACCOUNTING_EXPORT_MODELCSV == 2) // Model Cegid Expert Export { + $sep = ";"; + foreach ( $tabpay as $key => $val ) { $date = dol_print_date($db->jdate($val["date"]), '%d%m%Y'); // Cash - print $date . $sep; - print $conf->global->ACCOUNTING_CASH_JOURNAL . $sep; - foreach ( $tabbq[$key] as $k => $mt ) { + print $date . $sep; + print $cash_journal . $sep; print length_accountg(html_entity_decode($k)) . $sep; print $sep; print ($mt < 0 ? 'C' : 'D') . $sep; - print price($mt) . $sep; + print ($mt <= 0 ? price(- $mt) : $mt) . $sep; + print $val["type_payment"] . $sep; + print $val["ref"] . $sep; + print "\n"; } - print utf8_decode($langs->trans("CashPayment")) . $sep; - print $val["ref"] . $sep; - print "\n"; // Third party foreach ( $tabtp[$key] as $k => $mt ) { if ($mt) { print $date . $sep; - print $conf->global->ACCOUNTING_CASH_JOURNAL . $sep; - if ($obj->label == '(SupplierInvoicePayment)') { + print $cash_journal . $sep; + if ($val["lib"] == '(SupplierInvoicePayment)') { print length_accountg($conf->global->ACCOUNTING_ACCOUNT_SUPPLIER) . $sep; } else { print length_accountg($conf->global->ACCOUNTING_ACCOUNT_CUSTOMER) . $sep; } print length_accounta(html_entity_decode($k)) . $sep; print ($mt < 0 ? 'D' : 'C') . $sep; - print price($mt) . $sep; - print $langs->trans("ThirdParty") . $sep; + print ($mt <= 0 ? price(- $mt) : $mt) . $sep; + print $val["type_payment"] . $sep; print $val["ref"] . $sep; print "\n"; } } } - } else // Modèle Export Classique + } else // Model Classic Export { foreach ( $tabpay as $key => $val ) { $date = dol_print_date($db->jdate($val["date"]), 'day'); - print '"' . $date . '"' . $sep; - print '"' . $val["ref"] . '"' . $sep; // Cash foreach ( $tabbq[$key] as $k => $mt ) { + print '"' . $date . '"' . $sep; + print '"' . $val["ref"] . '"' . $sep; print '"' . length_accountg(html_entity_decode($k)) . '"' . $sep; print '"' . $langs->trans("Cash") . '"' . $sep; print '"' . ($mt >= 0 ? price($mt) : '') . '"' . $sep; print '"' . ($mt < 0 ? price(- $mt) : '') . '"'; + print "\n"; } - print "\n"; - + // Third party foreach ( $tabtp[$key] as $k => $mt ) { if ($mt) { @@ -455,7 +457,7 @@ if ($action == 'export_csv') { $period = $form->select_date($date_start, 'date_start', 0, 0, 0, '', 1, 0, 1) . ' - ' . $form->select_date($date_end, 'date_end', 0, 0, 0, '', 1, 0, 1); report_header($name, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array('action' => '')); - print ''; + print ''; print ''; diff --git a/htdocs/accountancy/journal/purchasesjournal.php b/htdocs/accountancy/journal/purchasesjournal.php index 68bcdaa394f..8b9b7929db8 100644 --- a/htdocs/accountancy/journal/purchasesjournal.php +++ b/htdocs/accountancy/journal/purchasesjournal.php @@ -242,16 +242,19 @@ if ($action == 'writebookkeeping') { $companystatic = new Societe($db); -// export csv +// Export if ($action == 'export_csv') { $sep = $conf->global->ACCOUNTING_EXPORT_SEPARATORCSV; + $purchase_journal = $conf->global->ACCOUNTING_PURCHASE_JOURNAL; header('Content-Type: text/csv'); header('Content-Disposition: attachment;filename=journal_achats.csv'); - if ($conf->global->ACCOUNTING_EXPORT_MODELCSV == 1) // Modèle Export Cegid Expert + if ($conf->global->ACCOUNTING_EXPORT_MODELCSV == 2) // Model Cegid Expert Export { + $sep = ";"; + foreach ( $tabfac as $key => $val ) { $date = dol_print_date($db->jdate($val["date"]), '%d%m%Y'); @@ -263,7 +266,7 @@ if ($action == 'export_csv') if ($mt) { print $date . $sep; - print $conf->global->ACCOUNTING_PURCHASE_JOURNAL . $sep; + print $purchase_journal . $sep; print length_accountg(html_entity_decode($k)) . $sep; print $sep; print ($mt < 0 ? 'C' : 'D') . $sep; @@ -275,11 +278,10 @@ if ($action == 'export_csv') } // VAT - // var_dump($tabtva); foreach ( $tabtva[$key] as $k => $mt ) { if ($mt) { print $date . $sep; - print $conf->global->ACCOUNTING_PURCHASE_JOURNAL . $sep; + print $purchase_journal . $sep; print length_accountg(html_entity_decode($k)) . $sep; print $sep; print ($mt < 0 ? 'C' : 'D') . $sep; @@ -289,20 +291,20 @@ if ($action == 'export_csv') print "\n"; } } - print $date . $sep; - print $conf->global->ACCOUNTING_PURCHASE_JOURNAL . $sep; - print length_accountg($conf->global->ACCOUNTING_ACCOUNT_SUPPLIER) . $sep; foreach ( $tabttc[$key] as $k => $mt ) { + print $date . $sep; + print $purchase_journal . $sep; + print length_accountg($conf->global->ACCOUNTING_ACCOUNT_SUPPLIER) . $sep; print length_accounta(html_entity_decode($k)) . $sep; print ($mt < 0 ? 'D' : 'C') . $sep; print ($mt <= 0 ? price(- $mt) : $mt) . $sep; print utf8_decode($companystatic->name) . $sep; print $val["ref"]; + print "\n"; } - print "\n"; } - } else // Modèle Export Classique + } else // Model Classic Export { foreach ( $tabfac as $key => $val ) { $date = dol_print_date($db->jdate($val["date"]), 'day'); @@ -326,7 +328,6 @@ if ($action == 'export_csv') } } // VAT - // var_dump($tabtva); foreach ( $tabtva[$key] as $k => $mt ) { if ($mt) { print '"' . $date . '"' . $sep; @@ -340,9 +341,9 @@ if ($action == 'export_csv') } // Third party - print '"' . $date . '"' . $sep; - print '"' . $val["ref"] . '"' . $sep; foreach ( $tabttc[$key] as $k => $mt ) { + print '"' . $date . '"' . $sep; + print '"' . $val["ref"] . '"' . $sep; print '"' . length_accounta(html_entity_decode($k)) . '"' . $sep; print '"' . utf8_decode($companystatic->name) . '"' . $sep; print '"' . ($mt < 0 ? price(- $mt) : '') . '"' . $sep; @@ -370,7 +371,7 @@ if ($action == 'export_csv') $period = $form->select_date($date_start, 'date_start', 0, 0, 0, '', 1, 0, 1) . ' - ' . $form->select_date($date_end, 'date_end', 0, 0, 0, '', 1, 0, 1); report_header($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array('action' => '')); - print ''; + print ''; print ''; @@ -434,7 +435,6 @@ if ($action == 'export_csv') } } // VAT - // var_dump($tabtva); foreach ( $tabtva[$key] as $k => $mt ) { if ($mt) { print ""; @@ -449,13 +449,11 @@ if ($action == 'export_csv') print ""; // Third party - print ""; - print ""; - foreach ( $tabttc[$key] as $k => $mt ) { + print ""; + print ""; $companystatic->id = $tabcompany[$key]['id']; $companystatic->name = $tabcompany[$key]['name']; - print ""; - // Third party - print ""; - print ""; foreach ( $tabttc[$key] as $k => $mt ) { + print ""; + print ""; + print ""; $companystatic->id = $tabcompany[$key]['id']; $companystatic->name = $tabcompany[$key]['name']; $companystatic->client = $tabcompany[$key]['code_client']; @@ -455,7 +458,6 @@ if ($action == 'export_csv') { } // VAT - // var_dump($tabtva); foreach ( $tabtva[$key] as $k => $mt ) { if ($mt) { print ""; @@ -473,8 +475,8 @@ if ($action == 'export_csv') { } print "
" . $date . "" . $invoicestatic->getNomUrl(1) . "" . $date . "" . $invoicestatic->getNomUrl(1) . "" . length_accounta($k); print "" . $langs->trans("ThirdParty"); print ' (' . $companystatic->getNomUrl(0, 'supplier', 16) . ')'; diff --git a/htdocs/accountancy/journal/sellsjournal.php b/htdocs/accountancy/journal/sellsjournal.php index 892272d6a5a..4c260f9fa99 100644 --- a/htdocs/accountancy/journal/sellsjournal.php +++ b/htdocs/accountancy/journal/sellsjournal.php @@ -4,7 +4,7 @@ * Copyright (C) 2011 Juanjo Menent * Copyright (C) 2012 Regis Houssin * Copyright (C) 2013 Christophe Battarel - * Copyright (C) 2013-2014 Alexandre Spangaro + * Copyright (C) 2013-2015 Alexandre Spangaro * Copyright (C) 2013-2014 Florian Henry * Copyright (C) 2013-2014 Olivier Geffroy * @@ -93,7 +93,7 @@ $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p ON p.rowid = fd.fk_produc $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accountingaccount as aa ON aa.rowid = fd.fk_code_ventilation"; $sql .= " JOIN " . MAIN_DB_PREFIX . "facture as f ON f.rowid = fd.fk_facture"; $sql .= " JOIN " . MAIN_DB_PREFIX . "societe as s ON s.rowid = f.fk_soc"; -$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_tva ct ON fd.tva_tx = ct.taux AND ct.fk_pays = '" . $idpays . "'"; +$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_tva as ct ON fd.tva_tx = ct.taux AND ct.fk_pays = '" . $idpays . "'"; $sql .= " WHERE fd.fk_code_ventilation > 0 "; if (! empty($conf->multicompany->enabled)) { $sql .= " AND f.entity = " . $conf->entity; @@ -245,17 +245,20 @@ if ($action == 'writebookkeeping') { } } } -// export csv +// Export if ($action == 'export_csv') { $sep = $conf->global->ACCOUNTING_EXPORT_SEPARATORCSV; + $sell_journal = $conf->global->ACCOUNTING_SELL_JOURNAL; header('Content-Type: text/csv'); header('Content-Disposition: attachment;filename=journal_ventes.csv'); $companystatic = new Client($db); - if ($conf->global->ACCOUNTING_EXPORT_MODELCSV == 1) // Modèle Export Cegid Expert + if ($conf->global->ACCOUNTING_EXPORT_MODELCSV == 2) // Model Cegid Expert Export { + $sep = ";"; + foreach ( $tabfac as $key => $val ) { $companystatic->id = $tabcompany[$key]['id']; $companystatic->name = $tabcompany[$key]['name']; @@ -263,23 +266,23 @@ if ($action == 'export_csv') { $date = dol_print_date($db->jdate($val["date"]), '%d%m%Y'); - print $date . $sep; - print $conf->global->ACCOUNTING_SELL_JOURNAL . $sep; - print length_accountg($conf->global->ACCOUNTING_ACCOUNT_CUSTOMER) . $sep; foreach ( $tabttc[$key] as $k => $mt ) { + print $date . $sep; + print $sell_journal . $sep; + print length_accountg($conf->global->ACCOUNTING_ACCOUNT_CUSTOMER) . $sep; print length_accounta(html_entity_decode($k)) . $sep; print ($mt < 0 ? 'C' : 'D') . $sep; print ($mt <= 0 ? price(- $mt) : $mt) . $sep; print utf8_decode($companystatic->name) . $sep; + print $val["ref"]; + print "\n"; } - print $val["ref"]; - print "\n"; // Product / Service foreach ( $tabht[$key] as $k => $mt ) { if ($mt) { print $date . $sep; - print $conf->global->ACCOUNTING_SELL_JOURNAL . $sep; + print $sell_journal . $sep; print length_accountg(html_entity_decode($k)) . $sep; print $sep; print ($mt < 0 ? 'D' : 'C') . $sep; @@ -289,11 +292,12 @@ if ($action == 'export_csv') { print "\n"; } } + // TVA foreach ( $tabtva[$key] as $k => $mt ) { if ($mt) { print $date . $sep; - print $conf->global->ACCOUNTING_SELL_JOURNAL . $sep; + print $sell_journal . $sep; print length_accountg(html_entity_decode($k)) . $sep; print $sep; print ($mt < 0 ? 'D' : 'C') . $sep; @@ -304,7 +308,7 @@ if ($action == 'export_csv') { } } } - } else // Modèle Export Classique + } else // Model Classic Export { foreach ( $tabfac as $key => $val ) { $companystatic->id = $tabcompany[$key]['id']; @@ -312,15 +316,16 @@ if ($action == 'export_csv') { $companystatic->client = $tabcompany[$key]['code_client']; $date = dol_print_date($db->jdate($val["date"]), 'day'); - print '"' . $date . '"' . $sep; - print '"' . $val["ref"] . '"' . $sep; + foreach ( $tabttc[$key] as $k => $mt ) { + print '"' . $date . '"' . $sep; + print '"' . $val["ref"] . '"' . $sep; print '"' . length_accounta(html_entity_decode($k)) . '"' . $sep; print '"' . utf8_decode($companystatic->name) . '"' . $sep; print '"' . ($mt >= 0 ? price($mt) : '') . '"' . $sep; print '"' . ($mt < 0 ? price(- $mt) : '') . '"'; + print "\n"; } - print "\n"; // Product / Service foreach ( $tabht[$key] as $k => $mt ) { @@ -339,7 +344,6 @@ if ($action == 'export_csv') { } // VAT - // var_dump($tabtva); foreach ( $tabtva[$key] as $k => $mt ) { if ($mt) { print '"' . $date . '"' . $sep; @@ -372,7 +376,7 @@ if ($action == 'export_csv') { $period = $form->select_date($date_start, 'date_start', 0, 0, 0, '', 1, 0, 1) . ' - ' . $form->select_date($date_end, 'date_end', 0, 0, 0, '', 1, 0, 1); report_header($nom, $nomlink, $period, $periodlink, $description, $builddate, $exportlink, array('action' => '')); - print ''; + print ''; print ''; @@ -420,12 +424,11 @@ if ($action == 'export_csv') { $date = dol_print_date($db->jdate($val["date"]), 'day'); - print "
" . $date . "" . $invoicestatic->getNomUrl(1) . "
" . $date . "" . $invoicestatic->getNomUrl(1) . "
"; + + // End of page + llxFooter(); } -// End of page -llxFooter(); - $db->close(); \ No newline at end of file diff --git a/htdocs/core/modules/modAccounting.class.php b/htdocs/core/modules/modAccounting.class.php index d683d4bb271..70a52dc90e1 100644 --- a/htdocs/core/modules/modAccounting.class.php +++ b/htdocs/core/modules/modAccounting.class.php @@ -129,7 +129,7 @@ class modAccounting extends DolibarrModules $this->const[9] = array( "ACCOUNTING_EXPORT_MODELCSV", "chaine", - "0" + "1" ); $this->const[10] = array( "ACCOUNTING_LENGTH_GACCOUNT", diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index e1713acd57c..b09dab7f764 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -13,7 +13,9 @@ ConfigAccountingExpert=Configuration of the module accounting expert Journaux=Journals JournalFinancial=Financial journals Exports=Exports +Export=Export Modelcsv=Model of export +OptionsDeactivatedForThisExportModel=For this export model, options are deactivated Selectmodelcsv=Select a model of export Modelcsv_normal=Classic export Modelcsv_CEGID=Export towards CEGID Expert @@ -66,7 +68,7 @@ Lineofinvoice=Line of invoice VentilatedinAccount=Ventilated successfully in the accounting account NotVentilatedinAccount=Not ventilated in the accounting account -ACCOUNTING_SEPARATORCSV=Separator CSV +ACCOUNTING_SEPARATORCSV=Column separator in export file ACCOUNTING_LIMIT_LIST_VENTILATION=Number of elements to be breakdown shown by page (maximum recommended : 50) ACCOUNTING_LIST_SORT_VENTILATION_TODO=Begin the sorting of the breakdown pages "Has to breakdown" by the most recent elements From fe674f8fd58c9d9bd39c469bb0c4417585ecb5f3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 3 Feb 2015 12:21:30 +0100 Subject: [PATCH 010/173] Fix pb into date management. Added phpunit to avoid this in future. --- htdocs/core/datepicker.php | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/htdocs/core/datepicker.php b/htdocs/core/datepicker.php index 03264601624..893b3929e2e 100644 --- a/htdocs/core/datepicker.php +++ b/htdocs/core/datepicker.php @@ -26,13 +26,13 @@ * \brief File to manage popup date selector */ -//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); // Not disabled cause need to load personalized language -//if (! defined('NOREQUIREDB')) define('NOREQUIREDB','1'); // Not disabled cause need to load personalized language +if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); // disabled +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB','1'); // Not disabled cause need to load global conf for START_WEEK if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1'); -//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); // Not disabled cause need to do translations +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); // Not disabled cause need to do translations if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK',1); if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL',1); -if (! defined('NOLOGIN')) define('NOLOGIN',1); // Not disabled cause need to load personalized language +if (! defined('NOLOGIN')) define('NOLOGIN',1); // disabled if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU',1); if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML',1); @@ -188,26 +188,12 @@ function displayBox($selectedDate,$month,$year) global->MAIN_START_WEEK)?$conf->global->MAIN_START_WEEK:1; - if($startday==1) - {?> - trans("ShortMonday") ?> - trans("ShortTuesday") ?> - trans("ShortWednesday") ?> - trans("ShortThursday") ?> - trans("ShortFriday") ?> - trans("ShortSaturday") ?> - trans("ShortSunday") ?> - - trans("ShortSunday") ?> - trans("ShortMonday") ?> - trans("ShortTuesday") ?> - trans("ShortWednesday") ?> - trans("ShortThursday") ?> - trans("ShortFriday") ?> - trans("ShortSaturday") ?> - + $day_names = array('ShortSunday', 'ShortMonday', 'ShortTuesday', 'ShortWednesday', 'ShortThursday', 'ShortFriday', 'ShortSaturday'); + for( $i=0; $i < 7; $i++ ) + { + echo '', $langs->trans($day_names[($i + $startday) % 7]), '', "\n"; + } + ?> Date: Tue, 3 Feb 2015 12:40:49 +0100 Subject: [PATCH 011/173] Fix pb into date management. Added phpunit to avoid this in future. --- htdocs/core/datepicker.php | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/htdocs/core/datepicker.php b/htdocs/core/datepicker.php index 893b3929e2e..03264601624 100644 --- a/htdocs/core/datepicker.php +++ b/htdocs/core/datepicker.php @@ -26,13 +26,13 @@ * \brief File to manage popup date selector */ -if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); // disabled -//if (! defined('NOREQUIREDB')) define('NOREQUIREDB','1'); // Not disabled cause need to load global conf for START_WEEK +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); // Not disabled cause need to load personalized language +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB','1'); // Not disabled cause need to load personalized language if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1'); -//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); // Not disabled cause need to do translations +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); // Not disabled cause need to do translations if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK',1); if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL',1); -if (! defined('NOLOGIN')) define('NOLOGIN',1); // disabled +if (! defined('NOLOGIN')) define('NOLOGIN',1); // Not disabled cause need to load personalized language if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU',1); if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML',1); @@ -188,12 +188,26 @@ function displayBox($selectedDate,$month,$year) global->MAIN_START_WEEK)?$conf->global->MAIN_START_WEEK:1; - $day_names = array('ShortSunday', 'ShortMonday', 'ShortTuesday', 'ShortWednesday', 'ShortThursday', 'ShortFriday', 'ShortSaturday'); - for( $i=0; $i < 7; $i++ ) - { - echo '', $langs->trans($day_names[($i + $startday) % 7]), '', "\n"; - } - ?> + if($startday==1) + {?> + trans("ShortMonday") ?> + trans("ShortTuesday") ?> + trans("ShortWednesday") ?> + trans("ShortThursday") ?> + trans("ShortFriday") ?> + trans("ShortSaturday") ?> + trans("ShortSunday") ?> + + trans("ShortSunday") ?> + trans("ShortMonday") ?> + trans("ShortTuesday") ?> + trans("ShortWednesday") ?> + trans("ShortThursday") ?> + trans("ShortFriday") ?> + trans("ShortSaturday") ?> + Date: Tue, 3 Feb 2015 13:05:28 +0100 Subject: [PATCH 012/173] Fix bad operator for and --- htdocs/admin/tools/export.php | 4 ++-- htdocs/core/class/rssparser.class.php | 2 +- htdocs/core/filemanagerdol/connectors/php/commands.php | 2 +- htdocs/core/modules/member/doc/pdf_standard.class.php | 2 +- .../core/modules/printsheet/doc/pdf_standardlabel.class.php | 2 +- htdocs/expedition/card.php | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/htdocs/admin/tools/export.php b/htdocs/admin/tools/export.php index 0831571ace1..721692145a1 100644 --- a/htdocs/admin/tools/export.php +++ b/htdocs/admin/tools/export.php @@ -480,10 +480,10 @@ function backup_tables($outputfile, $tables='*') if ($row[$j] == null and !is_string($row[$j])) { // IMPORTANT: if the field is NULL we set it NULL $row[$j] = 'NULL'; - } elseif(is_string($row[$j]) and $row[$j] == '') { + } elseif(is_string($row[$j]) && $row[$j] == '') { // if it's an empty string, we set it as an empty string $row[$j] = "''"; - } elseif(is_numeric($row[$j]) and !strcmp($row[$j], $row[$j]+0) ) { // test if it's a numeric type and the numeric version ($nb+0) == string version (eg: if we have 01, it's probably not a number but rather a string, else it would not have any leading 0) + } elseif(is_numeric($row[$j]) && !strcmp($row[$j], $row[$j]+0) ) { // test if it's a numeric type and the numeric version ($nb+0) == string version (eg: if we have 01, it's probably not a number but rather a string, else it would not have any leading 0) // if it's a number, we return it as-is // $row[$j] = $row[$j]; } else { // else for all other cases we escape the value and put quotes around diff --git a/htdocs/core/class/rssparser.class.php b/htdocs/core/class/rssparser.class.php index 5a156b1eda7..349b32d5104 100644 --- a/htdocs/core/class/rssparser.class.php +++ b/htdocs/core/class/rssparser.class.php @@ -550,7 +550,7 @@ class RssParser // elseif ($this->_format == 'atom' and $el == 'link' ) { - if ( isset($attrs['rel']) and $attrs['rel'] == 'alternate' ) + if ( isset($attrs['rel']) && $attrs['rel'] == 'alternate' ) { $link_el = 'link'; } diff --git a/htdocs/core/filemanagerdol/connectors/php/commands.php b/htdocs/core/filemanagerdol/connectors/php/commands.php index 6369ac9d3ae..333717d810d 100644 --- a/htdocs/core/filemanagerdol/connectors/php/commands.php +++ b/htdocs/core/filemanagerdol/connectors/php/commands.php @@ -174,7 +174,7 @@ function FileUpload($resourceType, $currentFolder, $sCommand, $CKEcallback = '') if ( isset( $_FILES['NewFile'] ) && !is_null($_FILES['NewFile']['tmp_name']) // This is for the QuickUpload tab box - or (isset($_FILES['upload']) and !is_null($_FILES['upload']['tmp_name']))) + or (isset($_FILES['upload']) && !is_null($_FILES['upload']['tmp_name']))) { global $Config ; diff --git a/htdocs/core/modules/member/doc/pdf_standard.class.php b/htdocs/core/modules/member/doc/pdf_standard.class.php index cef4155c607..9268a10f3c4 100644 --- a/htdocs/core/modules/member/doc/pdf_standard.class.php +++ b/htdocs/core/modules/member/doc/pdf_standard.class.php @@ -137,7 +137,7 @@ class pdf_standard $imgscaleheight=(empty($forceimgscalewidth)?0.5:$forceimgscalewidth); // Scale of image for height (1=Full height of sticker) // We are in a new page, then we must add a page - if (($this->_COUNTX ==0) and ($this->_COUNTY==0) and (!$this->_First==1)) { + if (($this->_COUNTX ==0) && ($this->_COUNTY==0) and (!$this->_First==1)) { $pdf->AddPage(); } $this->_First=0; diff --git a/htdocs/core/modules/printsheet/doc/pdf_standardlabel.class.php b/htdocs/core/modules/printsheet/doc/pdf_standardlabel.class.php index 8ae45bdc681..193de960bb8 100644 --- a/htdocs/core/modules/printsheet/doc/pdf_standardlabel.class.php +++ b/htdocs/core/modules/printsheet/doc/pdf_standardlabel.class.php @@ -135,7 +135,7 @@ class pdf_standardlabel $imgscaleheight=(empty($forceimgscalewidth)?0.5:$forceimgscalewidth); // Scale of image for height (1=Full height of sticker) // We are in a new page, then we must add a page - if (($this->_COUNTX ==0) and ($this->_COUNTY==0) and (!$this->_First==1)) { + if (($this->_COUNTX ==0) && ($this->_COUNTY==0) and (!$this->_First==1)) { $pdf->AddPage(); } $this->_First=0; diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index f4a270cca00..d9539f17eb4 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -882,7 +882,7 @@ if ($action == 'create') if (($line->product_type == 1 && empty($conf->global->STOCK_SUPPORTS_SERVICES)) || $defaultqty < 0) $defaultqty=0; } - if (empty($conf->productbatch->enabled) || ! ($product->hasbatch() and is_object($product->stock_warehouse[$warehouse_id]))) + if (empty($conf->productbatch->enabled) || ! ($product->hasbatch() && is_object($product->stock_warehouse[$warehouse_id]))) { // Quantity to send print ''; From f865534b4cdda41282891a2735a720b061474ae8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 3 Feb 2015 13:43:37 +0100 Subject: [PATCH 013/173] Fix some pdf differences --- .../commande/doc/pdf_einstein.modules.php | 14 ++-- .../fichinter/doc/pdf_soleil.modules.php | 66 +++++++++++++------ htdocs/fichinter/class/fichinter.class.php | 2 +- 3 files changed, 51 insertions(+), 31 deletions(-) diff --git a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php index 510a1bd88a1..f6d28a4f135 100644 --- a/htdocs/core/modules/commande/doc/pdf_einstein.modules.php +++ b/htdocs/core/modules/commande/doc/pdf_einstein.modules.php @@ -154,6 +154,8 @@ class pdf_einstein extends ModelePDFCommandes $outputlangs->load("orders"); $outputlangs->load("deliveries"); + $nblignes = count($object->lines); + if ($conf->commande->dir_output) { $object->fetch_thirdparty(); @@ -195,8 +197,6 @@ class pdf_einstein extends ModelePDFCommandes global $action; $reshook=$hookmanager->executeHooks('beforePDFCreation',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks - $nblignes = count($object->lines); - // Create pdf instance $pdf=pdf_getInstance($this->format); $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance @@ -328,6 +328,7 @@ class pdf_einstein extends ModelePDFCommandes //print $pageposafter.'-'.$pageposbefore;exit; $pdf->setPageOrientation('', 1, $heightforfooter); // The only function to edit the bottom margin of current page to set it. pdf_writelinedesc($pdf,$object,$i,$outputlangs,$this->posxtva-$curX,4,$curX,$curY,$hideref,$hidedesc); + $pageposafter=$pdf->getPage(); $posyafter=$pdf->GetY(); if ($posyafter > ($this->page_hauteur - ($heightforfooter+$heightforfreetext+$heightforinfotot))) // There is no space left for total+free text { @@ -511,11 +512,6 @@ class pdf_einstein extends ModelePDFCommandes $pdf->Output($file,'F'); // Add pdfgeneration hook - if (! is_object($hookmanager)) - { - include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; - $hookmanager=new HookManager($this->db); - } $hookmanager->initHooks(array('pdfgeneration')); $parameters=array('file'=>$file,'object'=>$object,'outputlangs'=>$outputlangs); global $action; @@ -797,7 +793,7 @@ class pdf_einstein extends ModelePDFCommandes //{ foreach( $this->localtax1 as $localtax_type => $localtax_rate ) { - if (in_array((string) $localtax_type, array('1','3','5','7'))) continue; + if (in_array((string) $localtax_type, array('1','3','5'))) continue; foreach( $localtax_rate as $tvakey => $tvaval ) { if ($tvakey!=0) // On affiche pas taux 0 @@ -828,7 +824,7 @@ class pdf_einstein extends ModelePDFCommandes //{ foreach( $this->localtax2 as $localtax_type => $localtax_rate ) { - if (in_array((string) $localtax_type, array('1','3','5','7'))) continue; + if (in_array((string) $localtax_type, array('1','3','5'))) continue; foreach( $localtax_rate as $tvakey => $tvaval ) { if ($tvakey!=0) // On affiche pas taux 0 diff --git a/htdocs/core/modules/fichinter/doc/pdf_soleil.modules.php b/htdocs/core/modules/fichinter/doc/pdf_soleil.modules.php index bd6ec1b60e9..9f2bf42c98d 100644 --- a/htdocs/core/modules/fichinter/doc/pdf_soleil.modules.php +++ b/htdocs/core/modules/fichinter/doc/pdf_soleil.modules.php @@ -96,7 +96,7 @@ class pdf_soleil extends ModelePDFFicheinter /** * Function to build pdf onto disk * - * @param CommonObject $object Id of object to generate + * @param Object $object Object to generate * @param Translate $outputlangs Lang output object * @param string $srctemplatepath Full path of source filename for generator using a template file * @param int $hidedetails Do not show line details @@ -106,7 +106,7 @@ class pdf_soleil extends ModelePDFFicheinter */ function write_file($object,$outputlangs,$srctemplatepath='',$hidedetails=0,$hidedesc=0,$hideref=0) { - global $user,$langs,$conf,$mysoc; + global $user,$langs,$conf,$mysoc,$db,$hookmanager; if (! is_object($outputlangs)) $outputlangs=$langs; // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO @@ -121,16 +121,24 @@ class pdf_soleil extends ModelePDFFicheinter { $object->fetch_thirdparty(); - $objectref = dol_sanitizeFileName($object->ref); - $dir = $conf->ficheinter->dir_output; - if (! preg_match('/specimen/i',$objectref)) $dir.= "/" . $objectref; - $file = $dir . "/" . $objectref . ".pdf"; - + // Definition of $dir and $file + if ($object->specimen) + { + $dir = $conf->ficheinter->dir_output; + $file = $dir . "/SPECIMEN.pdf"; + } + else + { + $objectref = dol_sanitizeFileName($object->ref); + $dir = $conf->ficheinter->dir_output . "/" . $objectref; + $file = $dir . "/" . $objectref . ".pdf"; + } + if (! file_exists($dir)) { if (dol_mkdir($dir) < 0) { - $this->error=$outputlangs->trans("ErrorCanNotCreateDir",$dir); + $this->error=$langs->transnoentities("ErrorCanNotCreateDir",$dir); return 0; } } @@ -149,6 +157,9 @@ class pdf_soleil extends ModelePDFFicheinter global $action; $reshook=$hookmanager->executeHooks('beforePDFCreation',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks + $nblignes = count($object->lines); + + // Create pdf instance $pdf=pdf_getInstance($this->format); $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance $heightforinfotot = 50; // Height reserved to output the info and total part @@ -196,12 +207,13 @@ class pdf_soleil extends ModelePDFFicheinter $tab_height_newpage = 150; // Affiche notes - if (! empty($object->note_public)) + $notetoshow=empty($object->note_public)?'':$object->note_public; + if ($notetoshow) { $tab_top = 88; $pdf->SetFont('','', $default_font_size - 1); - $pdf->writeHTMLCell(190, 3, $this->posxdesc-1, $tab_top, dol_htmlentitiesbr($object->note_public), 0, 1); + $pdf->writeHTMLCell(190, 3, $this->posxdesc-1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1); $nexY = $pdf->GetY(); $height_note=$nexY-$tab_top; @@ -252,15 +264,17 @@ class pdf_soleil extends ModelePDFFicheinter $valide = empty($objectligne->id) ? 0 : $objectligne->fetch($objectligne->id); if ($valide > 0 || $object->specimen) { - $curX = $this->posxdesc-1; $curY = $nexY; $pdf->SetFont('','', $default_font_size - 1); // Into loop to work with multipage $pdf->SetTextColor(0,0,0); $pdf->setTopMargin($tab_top_newpage); - $pdf->setPageOrientation('', 1, $heightforfooter+$heightforfreetext/*+$heightforinfotot*/); // The only function to edit the bottom margin of current page to set it. + $pdf->setPageOrientation('', 1, $heightforfooter+$heightforfreetext+$heightforinfotot); // The only function to edit the bottom margin of current page to set it. $pageposbefore=$pdf->getPage(); + // Description of product line + $curX = $this->posxdesc-1; + // Description of product line $txt=$outputlangs->transnoentities("Date")." : ".dol_print_date($objectligne->datei,'dayhour',false,$outputlangs,true); if ($objectligne->duration > 0) @@ -288,6 +302,8 @@ class pdf_soleil extends ModelePDFFicheinter if ($i == ($nblines-1)) // No more lines, and no space left to show total, so we create a new page { $pdf->AddPage('','',true); + if (! empty($tplidx)) $pdf->useTemplate($tplidx); + if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs); $pdf->setPage($pageposafter+1); } } @@ -316,33 +332,34 @@ class pdf_soleil extends ModelePDFFicheinter $pdf->setPage($pagenb); if ($pagenb == 1) { - $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter - $heightforfreetext, 0, $outputlangs, 0, 1); + $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1); } else { - $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter - $heightforfreetext, 0, $outputlangs, 1); + $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1); } $this->_pagefoot($pdf,$object,$outputlangs,1); $pagenb++; $pdf->setPage($pagenb); - $this->_pagehead($pdf, $object, 0, $outputlangs); $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it. + if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs); } if (isset($object->lines[$i+1]->pagebreak) && $object->lines[$i+1]->pagebreak) { if ($pagenb == 1) { - $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter - $heightforfreetext, 0, $outputlangs, 0, 1); + $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1); } else { - $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter - $heightforfreetext, 0, $outputlangs, 1, 1); + $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1); } $this->_pagefoot($pdf,$object,$outputlangs,1); // New page $pdf->AddPage(); if (! empty($tplidx)) $pdf->useTemplate($tplidx); $pagenb++; + if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs); } } } @@ -350,13 +367,13 @@ class pdf_soleil extends ModelePDFFicheinter // Show square if ($pagenb == 1) { - $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfreetext - $heightforfooter - 50, 0, $outputlangs, 0, 0); - $bottomlasttab=$this->page_hauteur - $heightforfooter - $heightforfooter + 1; + $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0); + $bottomlasttab=$this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1; } else { - $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfreetext - $heightforfooter - 50, 0, $outputlangs, 1, 0); - $bottomlasttab=$this->page_hauteur - $heightforfooter - $heightforfooter + 1; + $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0); + $bottomlasttab=$this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1; } $this->_pagefoot($pdf,$object,$outputlangs); @@ -364,6 +381,13 @@ class pdf_soleil extends ModelePDFFicheinter $pdf->Close(); $pdf->Output($file,'F'); + + // Add pdfgeneration hook + $hookmanager->initHooks(array('pdfgeneration')); + $parameters=array('file'=>$file,'object'=>$object,'outputlangs'=>$outputlangs); + global $action; + $reshook=$hookmanager->executeHooks('afterPDFCreation',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks + if (! empty($conf->global->MAIN_UMASK)) @chmod($file, octdec($conf->global->MAIN_UMASK)); diff --git a/htdocs/fichinter/class/fichinter.class.php b/htdocs/fichinter/class/fichinter.class.php index 1209debde92..9748f9a4fc8 100644 --- a/htdocs/fichinter/class/fichinter.class.php +++ b/htdocs/fichinter/class/fichinter.class.php @@ -960,7 +960,7 @@ class Fichinter extends CommonObject $this->note_private='Private note'; $this->note_public='SPECIMEN'; $this->duree = 0; - $nbp = 20; + $nbp = 25; $xnbp = 0; while ($xnbp < $nbp) { From 6fca75c977f5ea599ffedd89179c92ff6796c2ab Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 3 Feb 2015 13:57:05 +0100 Subject: [PATCH 014/173] Sync doc files --- INSTALL | 4 ++-- README-FR.md | 15 +++++---------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/INSTALL b/INSTALL index 56866a05d4e..584c3f04713 100644 --- a/INSTALL +++ b/INSTALL @@ -1,6 +1,6 @@ INSTALL ------- -English: See README file. +English: See README.md file. -French: Voir fichier README-FR. +French: Voir fichier README-FR.md. diff --git a/README-FR.md b/README-FR.md index aa8c3c1f5da..8d3d7f36aa9 100644 --- a/README-FR.md +++ b/README-FR.md @@ -1,21 +1,16 @@ # DOLIBARR ERP & CRM -## INTRODUCTION - Dolibarr ERP & CRM est un logiciel moderne pour gérer votre activité (société, association, auto-entrepreneurs, artisans). Il est simple d'utilisation et modulaire, vous permettant de n'activez que les fonctions dont vous avez besoin (contacts, fournisseurs, factures, commandes, stocks, agenda, ...). ![ScreenShot](http://www.dolibarr.org/images/dolibarr_screenshot1_640x480.png) --------------------------------- -Documentation démarrage rapide --------------------------------- -1) Installer Dolibarr -2) Mettre à jour Dolibarr depuis une ancienne version -3) Ce qui est nouveau dans cette version -4) Ce que peux faire Dolibarr -5) Ce que ne peux pas faire Dolibarr (pas encore) + +## LICENCE + +Dolibarr est distribué sous les termes de la licence GNU General Public License v3+ ou supérieure. + ## INSTALLER DOLIBARR From 4477a712d646910a082d3e019db65eb5c8b35a64 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 3 Feb 2015 14:02:36 +0100 Subject: [PATCH 015/173] Fix: calendar was not using option START_WEEK. --- htdocs/core/datepicker.php | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/htdocs/core/datepicker.php b/htdocs/core/datepicker.php index 03264601624..c8ffd4bef7d 100644 --- a/htdocs/core/datepicker.php +++ b/htdocs/core/datepicker.php @@ -26,13 +26,13 @@ * \brief File to manage popup date selector */ -//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); // Not disabled cause need to load personalized language +if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); // disabled //if (! defined('NOREQUIREDB')) define('NOREQUIREDB','1'); // Not disabled cause need to load personalized language if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1'); //if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); // Not disabled cause need to do translations if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK',1); if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL',1); -if (! defined('NOLOGIN')) define('NOLOGIN',1); // Not disabled cause need to load personalized language +if (! defined('NOLOGIN')) define('NOLOGIN',1); // disabled if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU',1); if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML',1); @@ -188,26 +188,13 @@ function displayBox($selectedDate,$month,$year) global->MAIN_START_WEEK)?$conf->global->MAIN_START_WEEK:1; - if($startday==1) - {?> - trans("ShortMonday") ?> - trans("ShortTuesday") ?> - trans("ShortWednesday") ?> - trans("ShortThursday") ?> - trans("ShortFriday") ?> - trans("ShortSaturday") ?> - trans("ShortSunday") ?> - - trans("ShortSunday") ?> - trans("ShortMonday") ?> - trans("ShortTuesday") ?> - trans("ShortWednesday") ?> - trans("ShortThursday") ?> - trans("ShortFriday") ?> - trans("ShortSaturday") ?> - + $day_names = array('ShortSunday', 'ShortMonday', 'ShortTuesday', 'ShortWednesday', 'ShortThursday', 'ShortFriday', 'ShortSaturday'); + for( $i=0; $i < 7; $i++ ) + { + echo '', $langs->trans($day_names[($i + $startday) % 7]), '', "\n"; + } + ?> + Date: Wed, 4 Feb 2015 00:45:52 +0100 Subject: [PATCH 016/173] Update 3.6.0-3.7.0.sql update url in llx_bank_url for remplacement of fiche.php by card.php Need to made it on 3.7 branch urgently --- htdocs/install/mysql/migration/3.6.0-3.7.0.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/install/mysql/migration/3.6.0-3.7.0.sql b/htdocs/install/mysql/migration/3.6.0-3.7.0.sql index 4421ad032eb..f278adb298f 100755 --- a/htdocs/install/mysql/migration/3.6.0-3.7.0.sql +++ b/htdocs/install/mysql/migration/3.6.0-3.7.0.sql @@ -1155,3 +1155,5 @@ ALTER TABLE llx_resource MODIFY COLUMN entity integer DEFAULT 1 NOT NULL; -- This request make mysql drop (mysql bug, so we add it at end): ALTER TABLE llx_product ADD CONSTRAINT fk_product_barcode_type FOREIGN KEY (fk_barcode_type) REFERENCES llx_c_barcode_type(rowid); +-- this update change the old formated url on llx_bank_url +UPDATE llx_bank_url set url = replace( url, 'fiche.php', 'card.php'); From 50ff9d2d0cb85f9bec2219c668cbcde51fca28bd Mon Sep 17 00:00:00 2001 From: BENKE Charles Date: Wed, 4 Feb 2015 02:17:37 +0100 Subject: [PATCH 017/173] Update paiement.class.php in case of sql query add error message in log instead of the screen --- htdocs/compta/paiement/class/paiement.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/paiement/class/paiement.class.php b/htdocs/compta/paiement/class/paiement.class.php index b73eb490296..e3ec12af6b5 100644 --- a/htdocs/compta/paiement/class/paiement.class.php +++ b/htdocs/compta/paiement/class/paiement.class.php @@ -488,7 +488,7 @@ class Paiement extends CommonObject $fac->thirdparty->name, 'company' ); - if ($result <= 0) dol_print_error($this->db); + if ($result <= 0) dol_syslog(get_class($this).'::addPaymentToBank '.$this->db->lasterror()); $linkaddedforthirdparty[$fac->thirdparty->id]=$fac->thirdparty->id; // Mark as done for this thirdparty } } @@ -506,7 +506,7 @@ class Paiement extends CommonObject $fac->thirdparty->name, 'company' ); - if ($result <= 0) dol_print_error($this->db); + if ($result <= 0) dol_syslog(get_class($this).'::addPaymentToBank '.$this->db->lasterror()); $linkaddedforthirdparty[$fac->thirdparty->id]=$fac->thirdparty->id; // Mark as done for this thirdparty } } From eb2c5c29b787b8aa9c2a9669006ae83ab0f1f83c Mon Sep 17 00:00:00 2001 From: Arnaud Aujon Chevallier Date: Thu, 5 Feb 2015 13:33:58 +0100 Subject: [PATCH 018/173] FIXES Webservice : fk_delivery_address not saved --- htdocs/webservices/server_order.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/webservices/server_order.php b/htdocs/webservices/server_order.php index d70725b468f..8cd69b352a7 100644 --- a/htdocs/webservices/server_order.php +++ b/htdocs/webservices/server_order.php @@ -640,6 +640,7 @@ function createOrder($authentication,$order) $newobject->statut=0; // We start with status draft $newobject->facturee=$order['facturee']; $newobject->fk_project=$order['project_id']; + $newObject->fk_delivery_address=$order['fk_delivery_address']; $newobject->cond_reglement_id=$order['cond_reglement_id']; $newobject->demand_reason_id=$order['demand_reason_id']; $newobject->date_creation=$now; From 65efa7ddf76d442264c9aff8c995fecd78a6df00 Mon Sep 17 00:00:00 2001 From: Arnaud Aujon Date: Thu, 5 Feb 2015 12:05:34 +0100 Subject: [PATCH 019/173] FIXED #1824 Add ref_ext for Contact webservices Add possibility to use ref_ext to reference contact using webservice, field was present but not saved and not used to fetch object --- htdocs/contact/class/contact.class.php | 9 +++++++-- htdocs/webservices/server_contact.php | 22 ++++++++++++---------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index 4187de7136c..a5c3764fd28 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -140,6 +140,7 @@ class Contact extends CommonObject $sql.= ", statut"; $sql.= ", canvas"; $sql.= ", entity"; + $sql.= ",ref_ext"; $sql.= ", import_key"; $sql.= ") VALUES ("; $sql.= "'".$this->db->idate($now)."',"; @@ -152,6 +153,7 @@ class Contact extends CommonObject $sql.= " ".$this->statut.","; $sql.= " ".(! empty($this->canvas)?"'".$this->canvas."'":"null").","; $sql.= " ".$conf->entity.","; + $sql.= "'".$this->db->escape($this->ref_ext)."',"; $sql.= " ".(! empty($this->import_key)?"'".$this->import_key."'":"null"); $sql.= ")"; @@ -496,10 +498,12 @@ class Contact extends CommonObject * * @param int $id id du contact * @param User $user Utilisateur (abonnes aux alertes) qui veut les alertes de ce contact + * @param string $ref_ext External reference, not given by Dolibarr * @return int -1 if KO, 0 if OK but not found, 1 if OK */ - function fetch($id, $user=0) + function fetch($id, $user=0, $ref_ext='') { + dol_syslog(get_class($this)."::fetch ".$this->error, LOG_ERR); global $langs; $langs->load("companies"); @@ -521,7 +525,8 @@ class Contact extends CommonObject $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as d ON c.fk_departement = d.rowid"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."user as u ON c.rowid = u.fk_socpeople"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON c.fk_soc = s.rowid"; - $sql.= " WHERE c.rowid = ". $id; + if ($id) $sql.= " WHERE c.rowid = ". $id; + elseif ($ref_ext) $sql .= " WHERE c.ref_ext = '".$this->db->escape($ref_ext)."'"; dol_syslog(get_class($this)."::fetch sql=".$sql); $resql=$this->db->query($sql); diff --git a/htdocs/webservices/server_contact.php b/htdocs/webservices/server_contact.php index eb05665ea04..edd95566287 100644 --- a/htdocs/webservices/server_contact.php +++ b/htdocs/webservices/server_contact.php @@ -83,6 +83,7 @@ $server->wsdl->addComplexType( $contact_fields = array( 'id' => array('name'=>'id','type'=>'xsd:string'), + 'ref_ext' => array('name'=>'ref_ext','type'=>'xsd:string'), 'lastname' => array('name'=>'lastname','type'=>'xsd:string'), 'firstname' => array('name'=>'firstname','type'=>'xsd:string'), 'address' => array('name'=>'address','type'=>'xsd:string'), @@ -176,14 +177,14 @@ $styleuse='encoded'; // encoded/literal/literal wrapped $server->register( 'getContact', // Entry values - array('authentication'=>'tns:authentication','id'=>'xsd:string','ref'=>'xsd:string','ref_ext'=>'xsd:string'), + array('authentication'=>'tns:authentication','id'=>'xsd:string','ref_ext'=>'xsd:string'), // Exit values array('result'=>'tns:result','contact'=>'tns:contact'), $ns, $ns.'#getContact', $styledoc, $styleuse, - 'WS to get contact' + 'WS to get a contact' ); // Register WSDL @@ -232,16 +233,15 @@ $server->register( * Get Contact * * @param array $authentication Array of authentication information - * @param int $id Id of object - * @param string $ref Ref of object - * @param ref_ext $ref_ext Ref external of object + * @param int $id Id of object + * @param string $ref_ext Ref external of object * @return mixed */ -function getContact($authentication,$id,$ref='',$ref_ext='') +function getContact($authentication,$id,$ref_ext) { global $db,$conf,$langs; - dol_syslog("Function: getContact login=".$authentication['login']." id=".$id." ref=".$ref." ref_ext=".$ref_ext); + dol_syslog("Function: getContact login=".$authentication['login']." id=".$id." ref_ext=".$ref_ext); if ($authentication['entity']) $conf->entity=$authentication['entity']; @@ -251,10 +251,10 @@ function getContact($authentication,$id,$ref='',$ref_ext='') $error=0; $fuser=check_authentication($authentication,$error,$errorcode,$errorlabel); // Check parameters - if (! $error && (($id && $ref) || ($id && $ref_ext) || ($ref && $ref_ext))) + if (! $error && ($id && $ref_ext)) { $error++; - $errorcode='BAD_PARAMETERS'; $errorlabel="Parameter id, ref and ref_ext can't be both provided. You must choose one or other but not both."; + $errorcode='BAD_PARAMETERS'; $errorlabel="Parameter id and ref_ext can't be both provided. You must choose one or other but not both."; } if (! $error) @@ -262,7 +262,7 @@ function getContact($authentication,$id,$ref='',$ref_ext='') $fuser->getrights(); $contact=new Contact($db); - $result=$contact->fetch($id,$ref,$ref_ext); + $result=$contact->fetch($id,0,$ref_ext); if ($result > 0) { // Only internal user who have contact read permission @@ -273,6 +273,7 @@ function getContact($authentication,$id,$ref='',$ref_ext='') ){ $contact_result_fields =array( 'id' => $contact->id, + 'ref_ext' => $contact->ref_ext, 'lastname' => $contact->lastname, 'firstname' => $contact->firstname, 'address' => $contact->address, @@ -383,6 +384,7 @@ function createContact($authentication,$contact) $newobject=new Contact($db); $newobject->id=$contact['id']; + $newobject->ref_ext=$contact['ref_ext']; $newobject->civility_id=$contact['civility_id']; $newobject->lastname=$contact['lastname']; $newobject->firstname=$contact['firstname']; From b8b9df7b953e6e8ba5226cd7096433c3e57a1813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Fri, 6 Feb 2015 12:36:09 +0100 Subject: [PATCH 020/173] Fix: [ bug #1827 ] Tax reports gives incorrect amounts when using external modules that create lines with special codes --- ChangeLog | 1 + htdocs/core/lib/tax.lib.php | 26 +++++++++----------------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index ace6a13363d..f5faea819fe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -18,6 +18,7 @@ English Dolibarr ChangeLog - Fix: [ bug #1717 ] Sorting unpaid invoices by amount received brings due amount - Fix: [ bug #1784 ] MOTD doesn't show up in Amarok theme - Fix: Tracking number not visible on shipment pdf +- Fix: [ bug #1827 ] Tax reports gives incorrect amounts when using external modules that create lines with special codes ***** ChangeLog for 3.6.2 compared to 3.6.1 ***** - Fix: fix ErrorBadValueForParamNotAString error message in price customer multiprice. diff --git a/htdocs/core/lib/tax.lib.php b/htdocs/core/lib/tax.lib.php index a52aeb37345..3b7e4044227 100644 --- a/htdocs/core/lib/tax.lib.php +++ b/htdocs/core/lib/tax.lib.php @@ -3,6 +3,7 @@ * Copyright (C) 2006-2007 Yannick Warnier * Copyright (C) 2011 Regis Houssin * Copyright (C) 2012 Juanjo Menent + * Copyright (C) 2015 Marcos García * * 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 @@ -86,26 +87,18 @@ function vat_by_thirdparty($db, $y, $date_start, $date_end, $modetax, $direction global $conf; $list=array(); - //print "xx".$conf->global->MAIN_MODULE_ACCOUNTING; - //print "xx".$conf->global->MAIN_MODULE_COMPTABILITE; if ($direction == 'sell') { $invoicetable='facture'; - $invoicedettable='facturedet'; - $fk_facture='fk_facture'; - $total_tva='total_tva'; - $total_localtax1='total_localtax1'; - $total_localtax2='total_localtax2'; + $total_ht='total'; + $total_tva='tva'; } if ($direction == 'buy') { $invoicetable='facture_fourn'; - $invoicedettable='facture_fourn_det'; - $fk_facture='fk_facture_fourn'; - $total_tva='tva'; - $total_localtax1='total_localtax1'; - $total_localtax2='total_localtax2'; + $total_ht='total_ht'; + $total_tva='total_tva'; } // Define sql request @@ -125,11 +118,10 @@ function vat_by_thirdparty($db, $y, $date_start, $date_end, $modetax, $direction if (! empty($conf->global->MAIN_MODULE_COMPTABILITE)) { $sql = "SELECT s.rowid as socid, s.nom as nom, s.siren as tva_intra, s.tva_assuj as assuj,"; - $sql.= " sum(fd.total_ht) as amount, sum(fd.".$total_tva.") as tva,"; - $sql.= " sum(fd.".$total_localtax1.") as localtax1,"; - $sql.= " sum(fd.".$total_localtax2.") as localtax2"; + $sql.= " sum(f.$total_ht) as amount, sum(f.".$total_tva.") as tva,"; + $sql.= " sum(f.localtax1) as localtax1,"; + $sql.= " sum(f.localtax2) as localtax2"; $sql.= " FROM ".MAIN_DB_PREFIX.$invoicetable." as f,"; - $sql.= " ".MAIN_DB_PREFIX.$invoicedettable." as fd,"; $sql.= " ".MAIN_DB_PREFIX."societe as s"; $sql.= " WHERE f.entity = " . $conf->entity; $sql.= " AND f.fk_statut in (1,2)"; // Validated or paid (partially or completely) @@ -146,7 +138,7 @@ function vat_by_thirdparty($db, $y, $date_start, $date_end, $modetax, $direction $sql.= " AND f.datef <= '".$db->idate(dol_get_last_day($y,12,false))."'"; } if ($date_start && $date_end) $sql.= " AND f.datef >= '".$db->idate($date_start)."' AND f.datef <= '".$db->idate($date_end)."'"; - $sql.= " AND s.rowid = f.fk_soc AND f.rowid = fd.".$fk_facture; + $sql.= " AND s.rowid = f.fk_soc"; $sql.= " GROUP BY s.rowid, s.nom, s.tva_intra, s.tva_assuj"; } } From 35d41d6f7c3780ac09a31ac1071249292d773736 Mon Sep 17 00:00:00 2001 From: phf Date: Fri, 6 Feb 2015 16:07:22 +0100 Subject: [PATCH 021/173] =?UTF-8?q?[CORE]=20Ajout=20d'un=20attribut=20(del?= =?UTF-8?q?ai=5Flivraison=5Fjours)=20=C3=A0=20l'objet=20ProductFournisseur?= =?UTF-8?q?,=20param=C3=A9trable=20lors=20d'un=20ajout/modification=20d'un?= =?UTF-8?q?=20prix=20fournisseur=20et=20s'affiche=20sur=20une=20commande?= =?UTF-8?q?=20fournisseur=20avec=20le=20plus=20grand=20d=C3=A9lai=20parmis?= =?UTF-8?q?=20la=20liste=20des=20produits=20dans=20la=20commande=20(#deliv?= =?UTF-8?q?erytime).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../class/fournisseur.commande.class.php | 28 ++++++++++++++++++- .../fourn/class/fournisseur.product.class.php | 26 +++++++++++------ htdocs/fourn/commande/card.php | 7 +++++ htdocs/langs/en_US/suppliers.lang | 4 ++- htdocs/langs/fr_FR/suppliers.lang | 2 ++ htdocs/product/fournisseurs.php | 15 +++++++--- 6 files changed, 67 insertions(+), 15 deletions(-) diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 7f2237859ea..035386ad9f0 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -2106,7 +2106,33 @@ class CommandeFournisseur extends CommonOrder return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref); } - + /** + * Return the max number delivery delay in day + * + * @return string + */ + function getMaxDelaiLivraisonJours($langs) + { + if (empty($this->lines)) + return $langs->trans('Undefined'); + + $nb = 0; + foreach ($this->lines as $line) { + $obj = new ProductFournisseur($this->db); + $idp = $obj->find_min_price_product_fournisseur($line->fk_product, $line->qty); + if ($idp) { + $obj->fetch($idp); + if ($obj->delai_livraison_jours > $nb) + $nb = $obj->delai_livraison_jours; + } + + } + + if ($nb === 0) + return $langs->trans('Undefined'); + else + return $nb.' '.$langs->trans('Days'); + } } diff --git a/htdocs/fourn/class/fournisseur.product.class.php b/htdocs/fourn/class/fournisseur.product.class.php index cdfee4c2398..4ca15b5ade1 100755 --- a/htdocs/fourn/class/fournisseur.product.class.php +++ b/htdocs/fourn/class/fournisseur.product.class.php @@ -42,6 +42,7 @@ class ProductFournisseur extends Product var $id; // product id var $fourn_ref; // deprecated + var $delai_livraison_jours; var $ref_supplier; // ref supplier (can be set by get_buyprice) var $vatrate_supplier; // default vat rate for this supplier/qty/product (can be set by get_buyprice) @@ -155,7 +156,7 @@ class ProductFournisseur extends Product * @param int $newnpr Set NPR or not * @return int <0 if KO, >=0 if OK */ - function update_buyprice($qty, $buyprice, $user, $price_base_type, $fourn, $availability, $ref_fourn, $tva_tx, $charges=0, $remise_percent=0, $remise=0, $newnpr=0) + function update_buyprice($qty, $buyprice, $user, $price_base_type, $fourn, $availability, $ref_fourn, $tva_tx, $charges=0, $remise_percent=0, $remise=0, $newnpr=0, $delai_livraison_jours=0) { global $conf; @@ -165,6 +166,7 @@ class ProductFournisseur extends Product if (empty($charges)) $charges=0; if (empty($availability)) $availability=0; if (empty($remise_percent)) $remise_percent=0; + if (empty($delai_livraison_jours)) $delai_livraison_jours=0; if ($price_base_type == 'TTC') { //$ttx = get_default_tva($fourn,$mysoc,$this->id); // We must use the VAT rate defined by user and not calculate it @@ -198,7 +200,8 @@ class ProductFournisseur extends Product $sql.= " fk_availability = ".$availability.","; $sql.= " entity = ".$conf->entity.","; $sql.= " info_bits = ".$newnpr.","; - $sql.= " charges = ".$charges; + $sql.= " charges = ".$charges.","; + $sql.= " delai_livraison_jours = ".$delai_livraison_jours; $sql.= " WHERE rowid = ".$this->product_fourn_price_id; // TODO Add price_base_type and price_ttc @@ -241,7 +244,7 @@ class ProductFournisseur extends Product { // Add price for this quantity to supplier $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_fournisseur_price("; - $sql.= "datec, fk_product, fk_soc, ref_fourn, fk_user, price, quantity, remise_percent, remise, unitprice, tva_tx, charges, unitcharges, fk_availability, info_bits, entity)"; + $sql.= "datec, fk_product, fk_soc, ref_fourn, fk_user, price, quantity, remise_percent, remise, unitprice, tva_tx, charges, unitcharges, fk_availability, info_bits, entity, delai_livraison_jours)"; $sql.= " values('".$this->db->idate($now)."',"; $sql.= " ".$this->id.","; $sql.= " ".$fourn->id.","; @@ -257,7 +260,8 @@ class ProductFournisseur extends Product $sql.= " ".$unitCharges.","; $sql.= " ".$availability.","; $sql.= " ".$newnpr.","; - $sql.= $conf->entity; + $sql.= $conf->entity.","; + $sql.= $this->delai_livraison_jours; $sql.=")"; dol_syslog(get_class($this)."::update_buyprice", LOG_DEBUG); @@ -330,7 +334,7 @@ class ProductFournisseur extends Product function fetch_product_fournisseur_price($rowid, $ignore_expression = 0) { $sql = "SELECT pfp.rowid, pfp.price, pfp.quantity, pfp.unitprice, pfp.remise_percent, pfp.remise, pfp.tva_tx, pfp.fk_availability,"; - $sql.= " pfp.fk_soc, pfp.ref_fourn, pfp.fk_product, pfp.charges, pfp.unitcharges, pfp.fk_supplier_price_expression"; // , pfp.recuperableonly as fourn_tva_npr"; FIXME this field not exist in llx_product_fournisseur_price + $sql.= " pfp.fk_soc, pfp.ref_fourn, pfp.fk_product, pfp.charges, pfp.unitcharges, pfp.fk_supplier_price_expression, pfp.delai_livraison_jours"; // , pfp.recuperableonly as fourn_tva_npr"; FIXME this field not exist in llx_product_fournisseur_price $sql.= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price as pfp"; $sql.= " WHERE pfp.rowid = ".$rowid; @@ -354,6 +358,7 @@ class ProductFournisseur extends Product $this->product_id = $obj->fk_product; // deprecated $this->fk_product = $obj->fk_product; $this->fk_availability = $obj->fk_availability; + $this->delai_livraison_jours = $obj->delai_livraison_jours; //$this->fourn_tva_npr = $obj->fourn_tva_npr; // FIXME this field not exist in llx_product_fournisseur_price $this->fk_supplier_price_expression = $obj->fk_supplier_price_expression; @@ -403,7 +408,7 @@ class ProductFournisseur extends Product $sql = "SELECT s.nom as supplier_name, s.rowid as fourn_id,"; $sql.= " pfp.rowid as product_fourn_pri_id, pfp.ref_fourn, pfp.fk_product as product_fourn_id, pfp.fk_supplier_price_expression,"; - $sql.= " pfp.price, pfp.quantity, pfp.unitprice, pfp.remise_percent, pfp.remise, pfp.tva_tx, pfp.fk_availability, pfp.charges, pfp.unitcharges, pfp.info_bits"; + $sql.= " pfp.price, pfp.quantity, pfp.unitprice, pfp.remise_percent, pfp.remise, pfp.tva_tx, pfp.fk_availability, pfp.charges, pfp.unitcharges, pfp.info_bits, pfp.delai_livraison_jours"; $sql.= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price as pfp"; $sql.= ", ".MAIN_DB_PREFIX."societe as s"; $sql.= " WHERE pfp.entity IN (".getEntity('product', 1).")"; @@ -431,12 +436,13 @@ class ProductFournisseur extends Product $prodfourn->fourn_remise_percent = $record["remise_percent"]; $prodfourn->fourn_remise = $record["remise"]; $prodfourn->fourn_unitprice = $record["unitprice"]; - $prodfourn->fourn_charges = $record["charges"]; - $prodfourn->fourn_unitcharges = $record["unitcharges"]; + $prodfourn->fourn_charges = $record["charges"]; + $prodfourn->fourn_unitcharges = $record["unitcharges"]; $prodfourn->fourn_tva_tx = $record["tva_tx"]; $prodfourn->fourn_id = $record["fourn_id"]; $prodfourn->fourn_name = $record["supplier_name"]; $prodfourn->fk_availability = $record["fk_availability"]; + $prodfourn->delai_livraison_jours = $record["delai_livraison_jours"]; $prodfourn->id = $prodid; $prodfourn->fourn_tva_npr = $record["info_bits"]; $prodfourn->fk_supplier_price_expression = $record["fk_supplier_price_expression"]; @@ -496,12 +502,13 @@ class ProductFournisseur extends Product $this->fourn_unitprice = ''; $this->fourn_id = ''; $this->fourn_name = ''; + $this->delai_livraison_jours = ''; $this->id = ''; $sql = "SELECT s.nom as supplier_name, s.rowid as fourn_id,"; $sql.= " pfp.rowid as product_fourn_price_id, pfp.ref_fourn,"; $sql.= " pfp.price, pfp.quantity, pfp.unitprice, pfp.tva_tx, pfp.charges, pfp.unitcharges, "; - $sql.= " pfp.remise, pfp.remise_percent, pfp.fk_supplier_price_expression"; + $sql.= " pfp.remise, pfp.remise_percent, pfp.fk_supplier_price_expression, pfp.delai_livraison_jours"; $sql.= " FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."product_fournisseur_price as pfp"; $sql.= " WHERE s.entity IN (".getEntity('societe', 1).")"; $sql.= " AND pfp.fk_product = ".$prodid; @@ -562,6 +569,7 @@ class ProductFournisseur extends Product $this->fourn_tva_tx = $record["tva_tx"]; $this->fourn_id = $record["fourn_id"]; $this->fourn_name = $record["supplier_name"]; + $this->delai_livraison_jours = $record["delai_livraison_jours"]; $this->fk_supplier_price_expression = $record["fk_supplier_price_expression"]; $this->id = $prodid; $min = $this->fourn_unitprice; diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index fe22a154251..abdf90c60d0 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -1601,6 +1601,13 @@ elseif (! empty($object->id)) } print ''; + + // Delai livraison jours + print ''; + print ''.$langs->trans('NbDaysToDelivery').' '.img_picto($langs->trans('DescNbDaysToDelivery'), 'info', 'style="cursor:help"').''; + print ''.$object->getMaxDelaiLivraisonJours($langs).''; + print ''; + // Project if (! empty($conf->projet->enabled)) { diff --git a/htdocs/langs/en_US/suppliers.lang b/htdocs/langs/en_US/suppliers.lang index ca3a81639bf..5919ffea61e 100644 --- a/htdocs/langs/en_US/suppliers.lang +++ b/htdocs/langs/en_US/suppliers.lang @@ -41,4 +41,6 @@ ListOfSupplierProductForSupplier=List of products and prices for supplier %s< NoneOrBatchFileNeverRan=None or batch %s not ran recently SentToSuppliers=Sent to suppliers ListOfSupplierOrders=List of supplier orders -MenuOrdersSupplierToBill=Supplier orders to invoice \ No newline at end of file +MenuOrdersSupplierToBill=Supplier orders to invoice +NbDaysToDelivery=Delivery delay in days +DescNbDaysToDelivery=The biggest delay is display among order product list \ No newline at end of file diff --git a/htdocs/langs/fr_FR/suppliers.lang b/htdocs/langs/fr_FR/suppliers.lang index dab237aeb2d..5ff72bb8d83 100644 --- a/htdocs/langs/fr_FR/suppliers.lang +++ b/htdocs/langs/fr_FR/suppliers.lang @@ -42,3 +42,5 @@ NoneOrBatchFileNeverRan=Aucun ou traitement par lot %s non exécuté réc SentToSuppliers=Envoyés aux fournisseurs ListOfSupplierOrders=Liste des commandes fournisseurs MenuOrdersSupplierToBill=Commandes fournisseurs en facture +NbDaysToDelivery=Delai de livraison en jours +DescNbDaysToDelivery=Le délai le plus long est affiché parmis la liste des produits de la commande \ No newline at end of file diff --git a/htdocs/product/fournisseurs.php b/htdocs/product/fournisseurs.php index 85e323cca51..05c5d1b652b 100644 --- a/htdocs/product/fournisseurs.php +++ b/htdocs/product/fournisseurs.php @@ -109,6 +109,7 @@ if ($action == 'updateprice' && GETPOST('cancel') <> $langs->trans("Cancel")) $tva_tx = str_replace('*','', GETPOST('tva_tx','alpha')); $tva_tx = price2num($tva_tx); $price_expression = GETPOST('eid', 'int') ? GETPOST('eid', 'int') : ''; // Discard expression if not in expression mode + $delai_livraison_jours = GETPOST('delai_livraison_jours', 'int') ? GETPOST('delai_livraison_jours', 'int') : ''; if ($tva_tx == '') { @@ -181,7 +182,7 @@ if ($action == 'updateprice' && GETPOST('cancel') <> $langs->trans("Cancel")) if (isset($_POST['ref_fourn_price_id'])) $product->fetch_product_fournisseur_price($_POST['ref_fourn_price_id']); - $ret=$product->update_buyprice($quantity, $_POST["price"], $user, $_POST["price_base_type"], $supplier, $_POST["oselDispo"], $ref_fourn, $tva_tx, $_POST["charges"], $remise_percent, $npr); + $ret=$product->update_buyprice($quantity, $_POST["price"], $user, $_POST["price_base_type"], $supplier, $_POST["oselDispo"], $ref_fourn, $tva_tx, $_POST["charges"], $remise_percent, 0, $npr, $delai_livraison_jours); if ($ret < 0) { @@ -322,7 +323,7 @@ if ($id || $ref) $supplier->fetch($socid); print $supplier->getNomUrl(1); print ''; - print ''; + print ''; print ''; } else @@ -379,8 +380,7 @@ if ($id || $ref) { print ''; } - print ''; - + print ''; // Vat rate $default_vat=''; @@ -450,6 +450,13 @@ if ($id || $ref) print ''; print ''; + + // Delai livraison jours + print ''; + print ''.$langs->trans('NbDaysToDelivery').''; + print ' '.$langs->trans('days').''; + print ''; + // Charges ???? if ($conf->global->PRODUCT_CHARGES) { From 35129f2192dff3f47d740c6ab80a7b8905dd0ffe Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 6 Feb 2015 16:33:33 +0100 Subject: [PATCH 022/173] Fix PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS option not correctly supported. Fix: No limit on ldap search on dolibarr side. --- htdocs/core/class/ldap.class.php | 3 +++ htdocs/fourn/facture/card.php | 11 ++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/htdocs/core/class/ldap.class.php b/htdocs/core/class/ldap.class.php index 95436a51e29..dc844ee3f02 100644 --- a/htdocs/core/class/ldap.class.php +++ b/htdocs/core/class/ldap.class.php @@ -176,7 +176,10 @@ class Ldap if (is_resource($this->connection)) { + // Execute the ldap_set_option here (after connect and before bind) $this->setVersion(); + ldap_set_option($this->connection, LDAP_OPT_SIZELIMIT, 0); // no limit here. should return true. + if ($this->serverType == "activedirectory") { diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index f3e752ed9d4..26aeffad655 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -1270,14 +1270,14 @@ if ($action == 'create') print ''.$langs->trans('Supplier').''; print ''; - if ($_REQUEST['socid'] > 0) + if (GETPOST('socid') > 0) { print $societe->getNomUrl(1); - print ''; + print ''; } else { - print $form->select_company((empty($_GET['socid'])?'':$_GET['socid']),'socid','s.fournisseur = 1',1); + print $form->select_company(GETPOST('socid','int'),'socid','s.fournisseur = 1',1); } print ''; @@ -1392,12 +1392,13 @@ if ($action == 'create') print ''; // Project - if (! empty($conf->projet->enabled)) { + if (! empty($conf->projet->enabled)) + { $formproject = new FormProjets($db); $langs->load('projects'); print '' . $langs->trans('Project') . ''; - $formproject->select_projects($soc->id, $projectid, 'projectid'); + $formproject->select_projects((empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS)?$soc->id:-1), $projectid, 'projectid'); print ''; } From 12c7e52b7e0f016150c5e9d32b054380832b08f9 Mon Sep 17 00:00:00 2001 From: phf Date: Fri, 6 Feb 2015 16:33:58 +0100 Subject: [PATCH 023/173] [CORE] Fix : rename de la variable "delai_livraison_jours" en "delivery_time_days" (#deliverytime). --- .../class/fournisseur.commande.class.php | 12 +++------ .../fourn/class/fournisseur.product.class.php | 26 +++++++++---------- htdocs/product/fournisseurs.php | 6 ++--- 3 files changed, 20 insertions(+), 24 deletions(-) diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 035386ad9f0..b04e258311f 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -2113,8 +2113,7 @@ class CommandeFournisseur extends CommonOrder */ function getMaxDelaiLivraisonJours($langs) { - if (empty($this->lines)) - return $langs->trans('Undefined'); + if (empty($this->lines)) return $langs->trans('Undefined'); $nb = 0; foreach ($this->lines as $line) { @@ -2122,16 +2121,13 @@ class CommandeFournisseur extends CommonOrder $idp = $obj->find_min_price_product_fournisseur($line->fk_product, $line->qty); if ($idp) { $obj->fetch($idp); - if ($obj->delai_livraison_jours > $nb) - $nb = $obj->delai_livraison_jours; + if ($obj->delivery_time_days > $nb) $nb = $obj->delivery_time_days; } } - if ($nb === 0) - return $langs->trans('Undefined'); - else - return $nb.' '.$langs->trans('Days'); + if ($nb === 0) return $langs->trans('Undefined'); + else return $nb.' '.$langs->trans('Days'); } } diff --git a/htdocs/fourn/class/fournisseur.product.class.php b/htdocs/fourn/class/fournisseur.product.class.php index 4ca15b5ade1..b78d7f2db60 100755 --- a/htdocs/fourn/class/fournisseur.product.class.php +++ b/htdocs/fourn/class/fournisseur.product.class.php @@ -42,7 +42,7 @@ class ProductFournisseur extends Product var $id; // product id var $fourn_ref; // deprecated - var $delai_livraison_jours; + var $delivery_time_days; var $ref_supplier; // ref supplier (can be set by get_buyprice) var $vatrate_supplier; // default vat rate for this supplier/qty/product (can be set by get_buyprice) @@ -156,7 +156,7 @@ class ProductFournisseur extends Product * @param int $newnpr Set NPR or not * @return int <0 if KO, >=0 if OK */ - function update_buyprice($qty, $buyprice, $user, $price_base_type, $fourn, $availability, $ref_fourn, $tva_tx, $charges=0, $remise_percent=0, $remise=0, $newnpr=0, $delai_livraison_jours=0) + function update_buyprice($qty, $buyprice, $user, $price_base_type, $fourn, $availability, $ref_fourn, $tva_tx, $charges=0, $remise_percent=0, $remise=0, $newnpr=0, $delivery_time_days=0) { global $conf; @@ -166,7 +166,7 @@ class ProductFournisseur extends Product if (empty($charges)) $charges=0; if (empty($availability)) $availability=0; if (empty($remise_percent)) $remise_percent=0; - if (empty($delai_livraison_jours)) $delai_livraison_jours=0; + if (empty($delivery_time_days)) $delivery_time_days=0; if ($price_base_type == 'TTC') { //$ttx = get_default_tva($fourn,$mysoc,$this->id); // We must use the VAT rate defined by user and not calculate it @@ -201,7 +201,7 @@ class ProductFournisseur extends Product $sql.= " entity = ".$conf->entity.","; $sql.= " info_bits = ".$newnpr.","; $sql.= " charges = ".$charges.","; - $sql.= " delai_livraison_jours = ".$delai_livraison_jours; + $sql.= " delivery_time_days = ".$delivery_time_days; $sql.= " WHERE rowid = ".$this->product_fourn_price_id; // TODO Add price_base_type and price_ttc @@ -244,7 +244,7 @@ class ProductFournisseur extends Product { // Add price for this quantity to supplier $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_fournisseur_price("; - $sql.= "datec, fk_product, fk_soc, ref_fourn, fk_user, price, quantity, remise_percent, remise, unitprice, tva_tx, charges, unitcharges, fk_availability, info_bits, entity, delai_livraison_jours)"; + $sql.= "datec, fk_product, fk_soc, ref_fourn, fk_user, price, quantity, remise_percent, remise, unitprice, tva_tx, charges, unitcharges, fk_availability, info_bits, entity, delivery_time_days)"; $sql.= " values('".$this->db->idate($now)."',"; $sql.= " ".$this->id.","; $sql.= " ".$fourn->id.","; @@ -261,7 +261,7 @@ class ProductFournisseur extends Product $sql.= " ".$availability.","; $sql.= " ".$newnpr.","; $sql.= $conf->entity.","; - $sql.= $this->delai_livraison_jours; + $sql.= $this->delivery_time_days; $sql.=")"; dol_syslog(get_class($this)."::update_buyprice", LOG_DEBUG); @@ -334,7 +334,7 @@ class ProductFournisseur extends Product function fetch_product_fournisseur_price($rowid, $ignore_expression = 0) { $sql = "SELECT pfp.rowid, pfp.price, pfp.quantity, pfp.unitprice, pfp.remise_percent, pfp.remise, pfp.tva_tx, pfp.fk_availability,"; - $sql.= " pfp.fk_soc, pfp.ref_fourn, pfp.fk_product, pfp.charges, pfp.unitcharges, pfp.fk_supplier_price_expression, pfp.delai_livraison_jours"; // , pfp.recuperableonly as fourn_tva_npr"; FIXME this field not exist in llx_product_fournisseur_price + $sql.= " pfp.fk_soc, pfp.ref_fourn, pfp.fk_product, pfp.charges, pfp.unitcharges, pfp.fk_supplier_price_expression, pfp.delivery_time_days"; // , pfp.recuperableonly as fourn_tva_npr"; FIXME this field not exist in llx_product_fournisseur_price $sql.= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price as pfp"; $sql.= " WHERE pfp.rowid = ".$rowid; @@ -358,7 +358,7 @@ class ProductFournisseur extends Product $this->product_id = $obj->fk_product; // deprecated $this->fk_product = $obj->fk_product; $this->fk_availability = $obj->fk_availability; - $this->delai_livraison_jours = $obj->delai_livraison_jours; + $this->delivery_time_days = $obj->delivery_time_days; //$this->fourn_tva_npr = $obj->fourn_tva_npr; // FIXME this field not exist in llx_product_fournisseur_price $this->fk_supplier_price_expression = $obj->fk_supplier_price_expression; @@ -408,7 +408,7 @@ class ProductFournisseur extends Product $sql = "SELECT s.nom as supplier_name, s.rowid as fourn_id,"; $sql.= " pfp.rowid as product_fourn_pri_id, pfp.ref_fourn, pfp.fk_product as product_fourn_id, pfp.fk_supplier_price_expression,"; - $sql.= " pfp.price, pfp.quantity, pfp.unitprice, pfp.remise_percent, pfp.remise, pfp.tva_tx, pfp.fk_availability, pfp.charges, pfp.unitcharges, pfp.info_bits, pfp.delai_livraison_jours"; + $sql.= " pfp.price, pfp.quantity, pfp.unitprice, pfp.remise_percent, pfp.remise, pfp.tva_tx, pfp.fk_availability, pfp.charges, pfp.unitcharges, pfp.info_bits, pfp.delivery_time_days"; $sql.= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price as pfp"; $sql.= ", ".MAIN_DB_PREFIX."societe as s"; $sql.= " WHERE pfp.entity IN (".getEntity('product', 1).")"; @@ -442,7 +442,7 @@ class ProductFournisseur extends Product $prodfourn->fourn_id = $record["fourn_id"]; $prodfourn->fourn_name = $record["supplier_name"]; $prodfourn->fk_availability = $record["fk_availability"]; - $prodfourn->delai_livraison_jours = $record["delai_livraison_jours"]; + $prodfourn->delivery_time_days = $record["delivery_time_days"]; $prodfourn->id = $prodid; $prodfourn->fourn_tva_npr = $record["info_bits"]; $prodfourn->fk_supplier_price_expression = $record["fk_supplier_price_expression"]; @@ -502,13 +502,13 @@ class ProductFournisseur extends Product $this->fourn_unitprice = ''; $this->fourn_id = ''; $this->fourn_name = ''; - $this->delai_livraison_jours = ''; + $this->delivery_time_days = ''; $this->id = ''; $sql = "SELECT s.nom as supplier_name, s.rowid as fourn_id,"; $sql.= " pfp.rowid as product_fourn_price_id, pfp.ref_fourn,"; $sql.= " pfp.price, pfp.quantity, pfp.unitprice, pfp.tva_tx, pfp.charges, pfp.unitcharges, "; - $sql.= " pfp.remise, pfp.remise_percent, pfp.fk_supplier_price_expression, pfp.delai_livraison_jours"; + $sql.= " pfp.remise, pfp.remise_percent, pfp.fk_supplier_price_expression, pfp.delivery_time_days"; $sql.= " FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."product_fournisseur_price as pfp"; $sql.= " WHERE s.entity IN (".getEntity('societe', 1).")"; $sql.= " AND pfp.fk_product = ".$prodid; @@ -569,7 +569,7 @@ class ProductFournisseur extends Product $this->fourn_tva_tx = $record["tva_tx"]; $this->fourn_id = $record["fourn_id"]; $this->fourn_name = $record["supplier_name"]; - $this->delai_livraison_jours = $record["delai_livraison_jours"]; + $this->delivery_time_days = $record["delivery_time_days"]; $this->fk_supplier_price_expression = $record["fk_supplier_price_expression"]; $this->id = $prodid; $min = $this->fourn_unitprice; diff --git a/htdocs/product/fournisseurs.php b/htdocs/product/fournisseurs.php index 05c5d1b652b..97ee64092a2 100644 --- a/htdocs/product/fournisseurs.php +++ b/htdocs/product/fournisseurs.php @@ -109,7 +109,7 @@ if ($action == 'updateprice' && GETPOST('cancel') <> $langs->trans("Cancel")) $tva_tx = str_replace('*','', GETPOST('tva_tx','alpha')); $tva_tx = price2num($tva_tx); $price_expression = GETPOST('eid', 'int') ? GETPOST('eid', 'int') : ''; // Discard expression if not in expression mode - $delai_livraison_jours = GETPOST('delai_livraison_jours', 'int') ? GETPOST('delai_livraison_jours', 'int') : ''; + $delivery_time_days = GETPOST('delivery_time_days', 'int') ? GETPOST('delivery_time_days', 'int') : ''; if ($tva_tx == '') { @@ -182,7 +182,7 @@ if ($action == 'updateprice' && GETPOST('cancel') <> $langs->trans("Cancel")) if (isset($_POST['ref_fourn_price_id'])) $product->fetch_product_fournisseur_price($_POST['ref_fourn_price_id']); - $ret=$product->update_buyprice($quantity, $_POST["price"], $user, $_POST["price_base_type"], $supplier, $_POST["oselDispo"], $ref_fourn, $tva_tx, $_POST["charges"], $remise_percent, 0, $npr, $delai_livraison_jours); + $ret=$product->update_buyprice($quantity, $_POST["price"], $user, $_POST["price_base_type"], $supplier, $_POST["oselDispo"], $ref_fourn, $tva_tx, $_POST["charges"], $remise_percent, 0, $npr, $delivery_time_days); if ($ret < 0) { @@ -454,7 +454,7 @@ if ($id || $ref) // Delai livraison jours print ''; print ''.$langs->trans('NbDaysToDelivery').''; - print ' '.$langs->trans('days').''; + print ' '.$langs->trans('days').''; print ''; // Charges ???? From 0e74dd4b95c662f621f978487b547d9f3a7916e3 Mon Sep 17 00:00:00 2001 From: phf Date: Fri, 6 Feb 2015 16:35:19 +0100 Subject: [PATCH 024/173] [CORE] ajout de la colonne "delivery_time_days" en bdd (#deliverytime). --- htdocs/install/mysql/migration/3.7.0-3.8.0.sql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql index 60d0e0660da..3c58af858a4 100755 --- a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql +++ b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql @@ -96,3 +96,5 @@ create table llx_contratdet_extrafields )ENGINE=innodb; ALTER TABLE llx_contratdet_extrafields ADD INDEX idx_contratdet_extrafields (fk_object); + +ALTER TABLE llx_product_fournisseur_price ADD COLUMN delivery_time_days integer; From 1d9a3e0ce2c7b009a622768669aa7d59bfa52f96 Mon Sep 17 00:00:00 2001 From: phf Date: Fri, 6 Feb 2015 16:39:54 +0100 Subject: [PATCH 025/173] [CORE] Fix : renommage d'une fonction (#deliverytime). --- htdocs/fourn/class/fournisseur.commande.class.php | 4 ++-- htdocs/fourn/commande/card.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index b04e258311f..d33c20189b0 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -2110,8 +2110,8 @@ class CommandeFournisseur extends CommonOrder * Return the max number delivery delay in day * * @return string - */ - function getMaxDelaiLivraisonJours($langs) + */ + function getMaxDeliveryTimeDay($langs) { if (empty($this->lines)) return $langs->trans('Undefined'); diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index abdf90c60d0..ed276d7b328 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -1605,7 +1605,7 @@ elseif (! empty($object->id)) // Delai livraison jours print ''; print ''.$langs->trans('NbDaysToDelivery').' '.img_picto($langs->trans('DescNbDaysToDelivery'), 'info', 'style="cursor:help"').''; - print ''.$object->getMaxDelaiLivraisonJours($langs).''; + print ''.$object->getMaxDeliveryTimeDay($langs).''; print ''; // Project From 553181a5d92a52bd3b2d22ddaac8525fc8290540 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 6 Feb 2015 21:26:41 +0100 Subject: [PATCH 026/173] Fixed: Location for file storage from tab attached files was not at same place than from tab images. --- htdocs/core/lib/product.lib.php | 14 +++++++------- htdocs/product/class/product.class.php | 25 ++++++++++++++++++++----- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/htdocs/core/lib/product.lib.php b/htdocs/core/lib/product.lib.php index 741dd98de6d..1aea8f9e37b 100644 --- a/htdocs/core/lib/product.lib.php +++ b/htdocs/core/lib/product.lib.php @@ -57,11 +57,6 @@ function product_prepare_head($object, $user) $h++; } - $head[$h][0] = DOL_URL_ROOT."/product/photos.php?id=".$object->id; - $head[$h][1] = $langs->trans("Photos"); - $head[$h][2] = 'photos'; - $h++; - // Show category tab if (! empty($conf->categorie->enabled) && $user->rights->categorie->lire) { @@ -116,14 +111,19 @@ function product_prepare_head($object, $user) // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf,$langs,$object,$head,$h,'product'); - // Attachments + $head[$h][0] = DOL_URL_ROOT."/product/photos.php?id=".$object->id; + $head[$h][1] = $langs->trans("Photos"); + $head[$h][2] = 'photos'; + $h++; + + // Attachments require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; if (! empty($conf->product->enabled)) $upload_dir = $conf->product->multidir_output[$object->entity].'/'.dol_sanitizeFileName($object->ref); elseif (! empty($conf->service->enabled)) $upload_dir = $conf->service->multidir_output[$object->entity].'/'.dol_sanitizeFileName($object->ref); $nbFiles = count(dol_dir_list($upload_dir,'files',0,'','(\.meta|_preview\.png)$')); $head[$h][0] = DOL_URL_ROOT.'/product/document.php?id='.$object->id; $head[$h][1] = $langs->trans('Documents'); - if($nbFiles > 0) $head[$h][1].= ' ('.$nbFiles.')'; + if($nbFiles > 0) $head[$h][1].= ' '.$nbFiles.''; $head[$h][2] = 'documents'; $h++; diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index ba179aef616..0778046c431 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -3101,10 +3101,14 @@ class Product extends CommonObject */ function add_photo($sdir, $file, $maxWidth = 160, $maxHeight = 120) { + global $conf; + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; $result = 0; - $dir = $sdir .'/'. get_exdir($this->id,2) . $this->id ."/photos"; + + $dir = $sdir; + if (! empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) $dir .= '/'. get_exdir($this->id,2) . $this->id ."/photos"; dol_mkdir($dir); @@ -3156,8 +3160,8 @@ class Product extends CommonObject { include_once DOL_DOCUMENT_ROOT .'/core/lib/files.lib.php'; - $pdir = get_exdir($this->id,2) . $this->id ."/photos/"; - $dir = $sdir . '/'. $pdir; + $dir = $sdir; + if (! empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) $dir .= '/'. get_exdir($this->id,2) . $this->id ."/photos"; $nbphoto=0; @@ -3199,8 +3203,19 @@ class Product extends CommonObject include_once DOL_DOCUMENT_ROOT .'/core/lib/files.lib.php'; include_once DOL_DOCUMENT_ROOT .'/core/lib/images.lib.php'; - $pdir = get_exdir($this->id,2) . $this->id ."/photos/"; - $dir = $sdir . '/'. $pdir; + $dir = $sdir . '/'; + $pdir = '/'; + if (! empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) + { + $dir .= get_exdir($this->id,2) . $this->id ."/photos/"; + $pdir .= get_exdir($this->id,2) . $this->id ."/photos/"; + } + else + { + $dir .= $this->ref.'/'; + $pdir .= $this->ref.'/'; + } + $dirthumb = $dir.'thumbs/'; $pdirthumb = $pdir.'thumbs/'; From 9d57f5b957086e5788fd6af18b2ff570a14daceb Mon Sep 17 00:00:00 2001 From: Juanjo Menent Date: Fri, 6 Feb 2015 22:55:43 +0100 Subject: [PATCH 027/173] Trad: update es_ES from Transifex --- htdocs/langs/es_ES/admin.lang | 20 +++++++++++++------- htdocs/langs/es_ES/agenda.lang | 6 +++--- htdocs/langs/es_ES/banks.lang | 1 + htdocs/langs/es_ES/bills.lang | 22 ++++++++++++++++++++-- htdocs/langs/es_ES/ecm.lang | 2 ++ htdocs/langs/es_ES/errors.lang | 2 ++ htdocs/langs/es_ES/install.lang | 2 ++ htdocs/langs/es_ES/languages.lang | 1 + htdocs/langs/es_ES/main.lang | 4 ++++ htdocs/langs/es_ES/margins.lang | 1 + 10 files changed, 49 insertions(+), 12 deletions(-) diff --git a/htdocs/langs/es_ES/admin.lang b/htdocs/langs/es_ES/admin.lang index e2c2f124b2e..77d1e695132 100644 --- a/htdocs/langs/es_ES/admin.lang +++ b/htdocs/langs/es_ES/admin.lang @@ -294,7 +294,7 @@ DoNotUseInProduction=No usar en producción ThisIsProcessToFollow=He aquí el procedimiento a seguir: StepNb=Paso %s FindPackageFromWebSite=Buscar el paquete que responde a su necesidad (por ejemplo en el sitio web %s) -DownloadPackageFromWebSite=Descargar el paquete desde el sitio %s. +DownloadPackageFromWebSite=Descargar paquete %s. UnpackPackageInDolibarrRoot=Descomprimir el paquete en el directorio raíz de Dolibarr %s sobre los archivos existentes (sin desplazar o borrar los existentes, so pena de perder su configuración o los módulos no oficiales instalados) SetupIsReadyForUse=La instalación ha finalizado y Dolibarr está disponible con el nuevo componente. NotExistsDirect=No existe el directorio alternativo.
@@ -304,6 +304,7 @@ YouCanSubmitFile=Seleccione paquete: CurrentVersion=Versión actual de Dolibarr CallUpdatePage=Llamar a la página de actualización de la estructura y datos de la base de datos %s. LastStableVersion=Última versión estable disponible +UpdateServerOffline=Actualizar servidor offline GenericMaskCodes=Puede introducir cualquier máscara numérica. En esta máscara, puede utilizar las siguientes etiquetas:
{000000} corresponde a un número que se incrementa en cada uno de %s. Introduzca tantos ceros como longitud desee mostrar. El contador se completará a partir de ceros por la izquierda con el fin de tener tantos ceros como la máscara.
{000000+000} Igual que el anterior, con una compensación correspondiente al número a la derecha del signo + se aplica a partir del primer %s.
{000000@x} igual que el anterior, pero el contador se restablece a cero cuando se llega a x meses (x entre 1 y 12). Si esta opción se utiliza y x es de 2 o superior, entonces la secuencia {yy}{mm} o {yyyy}{mm} también es necesaria.
{dd} días (01 a 31).
{mm} mes (01 a 12).
{yy}, {yyyy} ou {y} año en 2, 4 ó 1 cifra.
GenericMaskCodes2={cccc} código de cliente con n caracteres
{cccc000} código de cliente con n caracteres es seguido por un contador dedicado a clientes. Este contador dedicado a clientes se reseteará al mismo tiempo que el contador global.
{tttt} El código del tipo de empresa con n caracteres (vea diccionarios->tipos de empresa).
GenericMaskCodes3=Cualquier otro carácter en la máscara se quedará sin cambios.
No se permiten espacios
@@ -382,10 +383,12 @@ ExtrafieldSelectList = Lista desde una tabla ExtrafieldSeparator=Separador ExtrafieldCheckBox=Casilla de verificación ExtrafieldRadio=Botón de selección excluyente +ExtrafieldCheckBoxFromList= Casilla de selección de tabla ExtrafieldParamHelpselect=El listado de parámetros tiene que ser key,valor

por ejemplo:\n
1,value1
2,value2
3,value3
...

Para tener la lista en función de otra:
1,value1|parent_list_code:parent_key
2,value2|parent_list_code:parent_key ExtrafieldParamHelpcheckbox=El listado de parámetros tiene que ser key,valor

por ejemplo:\n
1,value1
2,value2
3,value3
... ExtrafieldParamHelpradio=El listado de parámetros tiene que ser key,valor

por ejemplo:\n
1,value1
2,value2
3,value3
... ExtrafieldParamHelpsellist=Lista Parámetros viene de una tabla
Sintaxis: nombre_tabla: etiqueta_campo: identificador_campo :: filtro
Ejemplo: c_typent: libelle: id :: filtro
filtro puede ser una prueba simple (por ejemplo, activo = 1) para mostrar el valor sólo se activa
si desea filtrar un campo extra utilizar la sintáxis extra.fieldcode = ... (donde el código de campo es el código del campo extra)
para tener la lista en función de otra:
c_typent: libelle: id: parent_list_code | parent_column: filtro +ExtrafieldParamHelpchkbxlst=Lista de parámetros viene de una tabla
Sintaxis: nombre_tabla: etiqueta_campo: identificador_campo :: filtro
Ejemplo: c_typent: libelle: id :: filtro
filtro puede ser una prueba simple (por ejemplo, activo = 1) para mostrar el valor sólo se activa
si desea filtrar un campo extra utilizar la sintáxis extra.fieldcode = ... (donde el código de campo es el código del campo extra)
para tener la lista en función de otra:
c_typent: libelle: id: parent_list_code | parent_column: filtro LibraryToBuildPDF=Librería usada para la creación de archivos PDF WarningUsingFPDF=Atención: Su archivo conf.php contiene la directiva dolibarr_pdf_force_fpdf=1. Esto hace que se use la librería FPDF para generar sus archivos PDF. Esta librería es antigua y no cubre algunas funcionalidades (Unicode, transparencia de imágenes, idiomas cirílicos, árabes o asiáticos, etc.), por lo que puede tener problemas en la generación de los PDF.
Para resolverlo, y disponer de un soporte completo de PDF, puede descargar la librería TCPDF , y a continuación comentar o eliminar la línea $dolibarr_pdf_force_fpdf=1, y añadir en su lugar $dolibarr_lib_TCPDF_PATH='ruta_a_TCPDF' LocalTaxDesc=Algunos países aplican 2 o 3 tasas a cada línea de factura. Si es el caso, escoja el tipo de la segunda y tercera tasa y su valor. Los posibles tipos son:
1 : tasa local aplicable a productos y servicios sin IVA (IVA no se aplica en la tasa local)
2 : tasa local se aplica a productos y servicios antes del IVA (IVA se calcula sobre importe+tasa local)
3 : tasa local se aplica a productos sin IVA (IVA no se aplica en la tasa local)
4 : tasa local se aplica a productos antes del IVA (IVA se calcula sobre el importe+tasa local)
5 : tasa local se aplica a servicios sin IVA (IVA no se aplica a la tasa local)
6 : tasa local se aplica a servicios antes del IVA (IVA se calcula sobre importe + tasa local) @@ -572,7 +575,7 @@ Permission67=Exportar intervenciones Permission71=Consultar miembros Permission72=Crear/modificar miembros Permission74=Eliminar miembros -Permission75=Configurar tipos y atributos de los miembros +Permission75=Configurar tipos de los miembros Permission76=Exportar miembros Permission78=Consultar cotizaciones Permission79=Crear/modificar cotizaciones @@ -596,7 +599,7 @@ Permission109=Eliminar expediciones Permission111=Consultar cuentas financieras (cuentas bancarias, cajas) Permission112=Crear/modificar cantidad/eliminar registros bancarios Permission113=Configurar cuentas financieras (crear, controlar las categorías) -Permission114=Exportar transacciones y registros bancarios +Permission114=Reconciliar transacciones Permission115=Exportar transacciones y extractos Permission116=Captar transferencias entre cuentas Permission117=Gestionar envío de cheques @@ -761,6 +764,7 @@ Permission55001=Leer encuestas Permission55002=Crear/modificar encuestas Permission59001=Leer márgenes comerciales Permission59002=Definir márgenes comerciales +Permission59003=Leer cualquier margen de usuario DictionaryCompanyType=Tipos de terceros DictionaryCompanyJuridicalType=Tipos jurídicos de terceros DictionaryProspectLevel=Perspectiva nivel cliente potencial @@ -1038,7 +1042,7 @@ SendingMailSetup=Configuración del envío por mail SendmailOptionNotComplete=Atención, en algunos sistemas Linux, con este método de envio, para poder enviar mails en su nombre, la configuración de sendmail debe contener la opción -ba (parámetro mail.force_extra_parameters en el archivo php.ini). Si algunos de sus destinatarios no reciben sus mensajes, pruebe a modificar este parámetro PHP con mail.force_extra_parameters=-ba. PathToDocuments=Rutas de acceso a documentos PathDirectory=Directorio -SendmailOptionMayHurtBuggedMTA=La funcionalidad de enviar correo electrónico a través del "correo directo PHP" genera una solicitud que puede ser mal interpretado por algunos servidores de correo. Esto se traduce en mensajes de correo electrónico ilegibles para las personas alojadas en estas plataformas. Este es el caso de clientes en ciertos proveedores de servicios de Internet (Ej: Orange). Esto no es un problema ni de Dolibarr ni de PHP, pero sí del servidor de correo. Sin embargo, puede agregar la opción MAIN_FIX_FOR_BUGGED_MTA con valor 1 en configuración-varios para tratar que Dolibarr evite el error. Otra solución (recomendada) es utilizar el método de envío por SMTP que no tiene este inconveniente. +SendmailOptionMayHurtBuggedMTA=La funcionalidad de enviar correo electrónico a través del "correo directo PHP" genera una solicitud que puede ser mal interpretado por algunos servidores de correo. Esto se traduce en mensajes de correo electrónico ilegibles para las personas alojadas en estas plataformas. Este es el caso de clientes en ciertos proveedores de servicios de Internet (Ej: Orange). Esto no es un problema ni de Dolibarr ni de PHP, pero sí del servidor de correo. Sin embargo, puede agregar la opción MAIN_FIX_FOR_BUGGED_MTA con valor 1 en configuración-varios para tratar que Dolibarr evite el error. Otra solución (recomendada) es utilizar el método de envío por SMTP que no tiene este inconveniente. TranslationSetup=Configuración traducción TranslationDesc=La elección del idioma mostrado en pantalla se modifica:
* A nivel global desde el menú Inicio - Configuración - Entorno
* De manera específica al usuario desde la pestaña Interfaz usuario de su ficha de usuario (hacer clic en su login en la parte superior izquierda de la pantalla). TotalNumberOfActivatedModules=Número total de módulos activados: %s @@ -1057,7 +1061,7 @@ BrowserIsOK=Usa el navegador web %s. Este navegador está optimizado para la seg BrowserIsKO=Usa el navegador web %s. Este navegador es una mala opción para la seguridad, rendimiento y fiabilidad. Aconsejamos utilizar Firefox, Chrome, Opera o Safari. XDebugInstalled=XDebug está cargado. XCacheInstalled=XCache está cargado -AddRefInList=Mostrar el código de cliente/proveedor en los listados (lista desplegable o autoselección) en la mayoría de enlaces +AddRefInList=Mostrar código de cliente/proveedor en los listados (y selectores) y enlaces. Los terceros aparecerán con el nombre "CC12345 - SC45678 - The big company coorp", en lugar de "The big company coorp". FieldEdition=Edición del campo %s FixTZ=Corrección de zona horaria FillThisOnlyIfRequired=Ejemplo: +2 (Complete sólo si se registra una desviación del tiempo en la exportación) @@ -1157,6 +1161,7 @@ ValidOrderAfterPropalClosed=Validar el pedido después del cierre del presupuest FreeLegalTextOnOrders=Texto libre en pedidos WatermarkOnDraftOrders=Marca de agua en pedidos borrador (en caso de estar vacío) ShippableOrderIconInList=Añadir un icono en el listado de pedidos que indica si el pedido es enviable +BANK_ASK_PAYMENT_BANK_DURING_ORDER=Preguntar por cuenta bancaria a usar en el pedido ##### Clicktodial ##### ClickToDialSetup=Configuración del módulo Click To Dial ClickToDialUrlDesc=URL de llamada haciendo click en el icono teléfono.
La URL completa de llamada será: URL?login=...&password=...&caller=...&called=telellamada @@ -1392,6 +1397,7 @@ RSSUrlExample=Un flujo RSS interesante MailingSetup=Configuración del módulo E-Mailing MailingEMailFrom=E-Mail emisor (From) de los correos enviados por E-Mailing MailingEMailError=E-Mail de respuesta (Errors-to) para las respuestas acerca de envíos por e-mailing con error. +MailingDelay=Segundos de espera después de enviar el mensaje siguiente ##### Notification ##### NotificationSetup=Configuración del módulo notificaciones NotificationEMailFrom=E-Mail emisor (From) de los correos enviados a través de notificaciones @@ -1403,7 +1409,7 @@ SendingsReceiptModel=Modelo de notas de entrega SendingsNumberingModules=Módulos de numeración de notas de entrega SendingsAbility=Uso de notas de entrega para los envíos a clientes NoNeedForDeliveryReceipts=En la mayoría de los casos, las notas de entrega (lista de productos enviados) también actúan como notas de recepción y son firmadas por el cliente. La gestión de las notas de recepción es por lo tanto redundante y rara vez se activará. -FreeLegalTextOnShippings=Mención complementaria en las notas de entrega +FreeLegalTextOnShippings=Texto libre en envíos ##### Deliveries ##### DeliveryOrderNumberingModules=Módulos de numeración de las notas de recepción DeliveryOrderModel=Modelo de notas de recepción @@ -1414,7 +1420,7 @@ AdvancedEditor=Editor avanzado ActivateFCKeditor=Activar editor avanzado para : FCKeditorForCompany=Creación/edición WYSIWIG de la descripción y notas de los terceros FCKeditorForProduct=Creación/edición WYSIWIG de la descripción y notas de los productos/servicios -FCKeditorForProductDetails=Creación/edición WYSIWIG de las líneas de detalle de los productos (en pedidos, presupuestos, facturas, etc.) +FCKeditorForProductDetails=Creación/edición WYSIWIG de las líneas de detalle de los productos (pedidos, presupuestos, facturas, etc.). Atención: El uso de esta opción no es recomendable ya que puede crear problemas con los caracteres especiales y el formateo de página al generar archivos PDF. FCKeditorForMailing= Creación/edición WYSIWIG de los E-Mails (Utilidades->E-Mailings) FCKeditorForUserSignature=Creación/edición WYSIWIG de la firma de usuarios FCKeditorForMail=Creación/edición WYSIWIG de todos los E-Mails (excepto Utilidades->E-Mailings) diff --git a/htdocs/langs/es_ES/agenda.lang b/htdocs/langs/es_ES/agenda.lang index 078045f4c14..60cdf0fb530 100644 --- a/htdocs/langs/es_ES/agenda.lang +++ b/htdocs/langs/es_ES/agenda.lang @@ -58,8 +58,8 @@ OrderSentByEMail=Pedido de cliente %s enviado por e-mail InvoiceSentByEMail=Factura a cliente %s enviada por e-mail SupplierOrderSentByEMail=Pedido a proveedor %s enviada por e-mail SupplierInvoiceSentByEMail=Factura de proveedor %s enviada por e-mail -ShippingSentByEMail=Expedición %s enviada por e-mail -ShippingValidated= Envío %s validado +ShippingSentByEMail=Expedición %s enviada por email +ShippingValidated= Expedición %s validada NewCompanyToDolibarr= Tercero creado DateActionPlannedStart= Fecha de inicio prevista DateActionPlannedEnd= Fecha de fin prevista @@ -68,7 +68,7 @@ DateActionDoneEnd= Fecha real de finalización DateActionStart= Fecha de inicio DateActionEnd= Fecha finalización AgendaUrlOptions1=Puede también añadir estos parámetros al filtro de salida: -AgendaUrlOptions2=login=%s para restringir inserciones a acciones creadas , que afecten o realizadas por el usuario %s. +AgendaUrlOptions2=login=%s para restringir inserciones a acciones creadas o asignadas al usuario %s. AgendaUrlOptions3=logina=%s para restringir inserciones a acciones creadas por el usuario %s. AgendaUrlOptions4=logint=%s para restringir inserciones a acciones que afecten al usuario %s. AgendaUrlOptionsProject=project=PROJECT_ID para restringir inserciones a acciones asociadas al proyecto PROJECT_ID. diff --git a/htdocs/langs/es_ES/banks.lang b/htdocs/langs/es_ES/banks.lang index 2c7516b555b..647e7987293 100644 --- a/htdocs/langs/es_ES/banks.lang +++ b/htdocs/langs/es_ES/banks.lang @@ -8,6 +8,7 @@ FinancialAccount=Cuenta FinancialAccounts=Cuentas BankAccount=Cuenta bancaria BankAccounts=Cuentas Bancarias +ShowAccount=Mostrar cuenta AccountRef=Ref. cuenta financiera AccountLabel=Etiqueta cuenta financiera CashAccount=Cuenta caja/efectivo diff --git a/htdocs/langs/es_ES/bills.lang b/htdocs/langs/es_ES/bills.lang index 7e4a1e1376d..782efdf26e2 100644 --- a/htdocs/langs/es_ES/bills.lang +++ b/htdocs/langs/es_ES/bills.lang @@ -2,7 +2,7 @@ Bill=Factura Bills=Facturas BillsCustomers=Facturas a clientes -BillsCustomer=Facturas al cliente +BillsCustomer=Facturas a clientes BillsSuppliers=Facturas de proveedores BillsCustomersUnpaid=Facturas a clientes pendientes de cobro BillsCustomersUnpaidForCompany=Facturas a clientes pendientes de cobro de %s @@ -348,6 +348,7 @@ ChequeNumber=Cheque nº ChequeOrTransferNumber=Cheque/Transferencia nº ChequeMaker=Emisor del cheque ChequeBank=Banco del cheque +CheckBank=Verificar NetToBePaid=Neto a pagar PhoneNumber=Tel. FullPhoneNumber=Teléfono @@ -388,7 +389,7 @@ DisabledBecausePayments=No disponible ya que existen pagos CantRemovePaymentWithOneInvoicePaid=Eliminación imposible cuando existe al menos una factura clasificada como pagada. ExpectedToPay=Esperando el pago PayedByThisPayment=Pagada por este pago -ClosePaidInvoicesAutomatically=Clasificar como "Pagadas" las facturas y facturas rectificativas completamente pagadas. +ClosePaidInvoicesAutomatically=Clasificar como "Pagadas" las facturas, facturas de situación y facturas rectificativas completamente pagadas. ClosePaidCreditNotesAutomatically=Clasificar automáticamente como "Pagados" los abonos completamente reembolsados AllCompletelyPayedInvoiceWillBeClosed=Todas las facturas con un resto a pagar 0 serán automáticamente cerradas al estado "Pagada". ToMakePayment=Pagar @@ -410,3 +411,20 @@ TypeContact_invoice_supplier_internal_SALESREPFOLL=Responsable seguimiento factu TypeContact_invoice_supplier_external_BILLING=Contacto proveedor facturación TypeContact_invoice_supplier_external_SHIPPING=Contacto proveedor entregas TypeContact_invoice_supplier_external_SERVICE=Contacto proveedor servicios +# Situation invoices +InvoiceFirstSituationAsk=Factura de primera situación +InvoiceFirstSituationDesc=Las facturas de situación están ligadas a situaciones relacionadas con una progresión, por ejemplo, la progresión de una construcción. Cada situación está ligada a una factura. +InvoiceSituation=Factura de situación +InvoiceSituationAsk=Factura de seguimiento de situación +InvoiceSituationDesc=Creación de una nueva situación que seguirá a una posición ya abierta. +SituationAmount=Importe Factura situación (Sin IVA) +SituationDeduction=Deducción situación +Progress=Progreso +ModifyAllLines=Modificar todas las líneas +CreateNextSituationInvoice=Crear próxima situación +NotLastInCycle=Esta factura no la última en el ciclo y no debe ser modificada. +DisabledBecauseNotLastInCycle=La próxima situación ya existe. +DisabledBecauseFinal=Esta situación es la última. +CantBeLessThanMinPercent=El progreso de una línea no puede ser inferior a su valor a la situación anterior. +NoSituations=Sin situaciones abiertas +InvoiceSituationLast=Factura final y general diff --git a/htdocs/langs/es_ES/ecm.lang b/htdocs/langs/es_ES/ecm.lang index 6f2cf618ff9..ea37f35c3ef 100644 --- a/htdocs/langs/es_ES/ecm.lang +++ b/htdocs/langs/es_ES/ecm.lang @@ -43,6 +43,8 @@ ECMDocsByContracts=Documentos asociados a contratos ECMDocsByInvoices=Documentos asociados a facturas ECMDocsByProducts=Documentos enlazados a productos ECMDocsByProjects=Documentos enlazados a proyectos +ECMDocsByUsers=Documentos enlazados a usuarios +ECMDocsByInterventions=Documentos enlazados a intervenciones ECMNoDirectoryYet=No se ha creado el directorio ShowECMSection=Mostrar directorio DeleteSection=Eliminación directorio diff --git a/htdocs/langs/es_ES/errors.lang b/htdocs/langs/es_ES/errors.lang index 71715c703db..dc59e37fd03 100644 --- a/htdocs/langs/es_ES/errors.lang +++ b/htdocs/langs/es_ES/errors.lang @@ -91,6 +91,8 @@ ErrorModuleSetupNotComplete=La configuración del módulo parece incompleta. Vay ErrorBadMask=Error en la máscara ErrorBadMaskFailedToLocatePosOfSequence=Error, sin número de secuencia en la máscara ErrorBadMaskBadRazMonth=Error, valor de vuelta a 0 incorrecto +ErrorMaxNumberReachForThisMask=Número máximo alcanzado para esta máscara +ErrorCounterMustHaveMoreThan3Digits=El contador debe contener más de 3 dígitos ErrorSelectAtLeastOne=Error. Seleccione al menos una entrada. ErrorProductWithRefNotExist=La referencia de producto '%s' no existe ErrorDeleteNotPossibleLineIsConsolidated=Eliminación imposible ya que el registro está enlazado a una transacción bancaria conciliada diff --git a/htdocs/langs/es_ES/install.lang b/htdocs/langs/es_ES/install.lang index 2cb12467d66..a93ded0ce8e 100644 --- a/htdocs/langs/es_ES/install.lang +++ b/htdocs/langs/es_ES/install.lang @@ -155,6 +155,7 @@ MigrationFinished=Actualización terminada LastStepDesc=Último paso: Indique aquí la cuenta y la contraseña del primer usuario que usted utilizará para conectarse a la aplicación. No pierda estos identificadores, es la cuenta que permite administrar el resto. ActivateModule=Activación del módulo %s ShowEditTechnicalParameters=Pulse aquí para ver/editar los parámetros técnicos (modo experto) +WarningUpgrade=Atención:\nHa pensado en hacer una copia de seguridad de la base de datos?\nEs muy recomendable: por ejemplo, debido a algunos fallos en los sistemas de bases de datos (por ejemplo MySQL versión 5.5.40), algunos datos o tablas se pueden perder durante este proceso, por lo que es muy recomendable tener una copia completa de su base de datos antes de iniciar la migración.\n\nHaga clic en OK para iniciar el proceso de migración... ######### # upgrade @@ -206,6 +207,7 @@ MigrationProjectTaskTime=Actualización de tiempo dedicado en segundos MigrationActioncommElement=Actualización de los datos de acciones sobre elementos MigrationPaymentMode=Actualización de los modos de pago MigrationCategorieAssociation=Actualización de las categorías +MigrationEvents=Migración de eventos para agregar propietario de evento en la tabla de asignacion ShowNotAvailableOptions=Mostrar opciones no disponibles HideNotAvailableOptions=Ocultar opciones no disponibles diff --git a/htdocs/langs/es_ES/languages.lang b/htdocs/langs/es_ES/languages.lang index 88fba3e586f..db80bec8869 100644 --- a/htdocs/langs/es_ES/languages.lang +++ b/htdocs/langs/es_ES/languages.lang @@ -13,6 +13,7 @@ Language_de_AT=Alemán (Austria) Language_de_CH=Alemán (Suiza) Language_el_GR=Griego Language_en_AU=Inglés (Australia) +Language_en_CA=Inglés (Canadá) Language_en_GB=Inglés (Reino Unido) Language_en_IN=Inglés (India) Language_en_NZ=Inglés (Nueva Zelanda) diff --git a/htdocs/langs/es_ES/main.lang b/htdocs/langs/es_ES/main.lang index 0f13a2540a2..67d542d8881 100644 --- a/htdocs/langs/es_ES/main.lang +++ b/htdocs/langs/es_ES/main.lang @@ -61,6 +61,7 @@ ErrorFailedToSaveFile=Error, el registro del archivo falló. SetDate=Fijar fecha SelectDate=Seleccione una fecha SeeAlso=Ver también %s +SeeHere=Vea aquí BackgroundColorByDefault=Color de fondo FileNotUploaded=No se ha subido el archivo FileUploaded=El archivo se ha subido correctamente @@ -169,6 +170,7 @@ User=Usuario Users=Usuarios Group=Grupo Groups=Grupos +NoUserGroupDefined=No hay definido grupo de usuarios Password=Contraseña PasswordRetype=Repetir contraseña NoteSomeFeaturesAreDisabled=Atención, sólo unos pocos módulos/funcionalidades han sido activados en esta demo. @@ -258,6 +260,7 @@ days=días Hours=Horas Minutes=Minutos Seconds=Segundos +Weeks=Semanas Today=Hoy Yesterday=Ayer Tomorrow=Mañana @@ -683,6 +686,7 @@ XMoreLines=%s línea(s) ocultas PublicUrl=URL pública AddBox=Añadir caja SelectElementAndClickRefresh=Seleccione un elemento y haga clic en Refrescar +PrintFile=Imprimir Archivo %s # Week day Monday=Lunes Tuesday=Martes diff --git a/htdocs/langs/es_ES/margins.lang b/htdocs/langs/es_ES/margins.lang index 2094ff8761a..7b585ad9630 100644 --- a/htdocs/langs/es_ES/margins.lang +++ b/htdocs/langs/es_ES/margins.lang @@ -16,6 +16,7 @@ MarginDetails=Detalles de márgenes realizados ProductMargins=Márgenes por producto CustomerMargins=Márgenes por cliente SalesRepresentativeMargins=Margenes por comercial +UserMargins=Márgenes del usuario ProductService=Producto o servicio AllProducts=Todos los productos y servicios ChooseProduct/Service=Elija el producto o servicio From 79ac620ab59b6956947dfe5ec7eff1ffed61ea12 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 7 Feb 2015 01:32:21 +0100 Subject: [PATCH 028/173] Fix label of status --- htdocs/projet/class/project.class.php | 2 +- htdocs/projet/list.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index d738256e7d4..796aa1fa89d 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -768,7 +768,7 @@ class Project extends CommonObject if ($statut == 0) return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut0'); if ($statut == 1) - return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut1'); + return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut4'); if ($statut == 2) return img_picto($langs->trans($this->statuts_short[$statut]), 'statut6') . ' ' . $langs->trans($this->statuts_short[$statut]); } diff --git a/htdocs/projet/list.php b/htdocs/projet/list.php index b4260e8ea91..d52ba362532 100644 --- a/htdocs/projet/list.php +++ b/htdocs/projet/list.php @@ -198,7 +198,7 @@ if ($resql) // Status $projectstatic->statut = $objp->fk_statut; - print ''.$projectstatic->getLibStatut(3).''; + print ''.$projectstatic->getLibStatut(5).''; print "\n"; From 53453a63f535ac1b7ea4b676f44aeb91bb2a0602 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 7 Feb 2015 01:45:09 +0100 Subject: [PATCH 029/173] Fix: pb when posting page due to apache limit --- htdocs/admin/const.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/htdocs/admin/const.php b/htdocs/admin/const.php index a64e3856dbc..fc7fbc74f4d 100644 --- a/htdocs/admin/const.php +++ b/htdocs/admin/const.php @@ -230,7 +230,7 @@ $sql.= ", entity"; $sql.= " FROM ".MAIN_DB_PREFIX."const"; $sql.= " WHERE entity IN (".$user->entity.",".$conf->entity.")"; if (empty($user->entity) && $debug) {} // to force for superadmin -elseif ($user->entity || empty($conf->multicompany->enabled)) $sql.= " AND visible = 1"; +else $sql.= " AND visible = 1"; // We must always have this. Otherwise, array is too large and submitting data fails due to apache POST or GET limits $sql.= " ORDER BY entity, name ASC"; dol_syslog("Const::listConstant", LOG_DEBUG); @@ -280,7 +280,6 @@ if ($result) if ($conf->use_javascript_ajax) { print ''; - print '   '; } else { From ba5d355eb3b499f5b1a66e31bf5331a0d55c2ad7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 7 Feb 2015 02:14:45 +0100 Subject: [PATCH 030/173] Fix bad property --- htdocs/core/lib/project.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/project.lib.php b/htdocs/core/lib/project.lib.php index 2fa69959e33..27f0a5fe63f 100644 --- a/htdocs/core/lib/project.lib.php +++ b/htdocs/core/lib/project.lib.php @@ -498,7 +498,7 @@ function projectLinesb(&$inc, $parent, $lines, &$level, &$projectsrole, &$tasksr // Ref print ''; $taskstatic->id=$lines[$i]->id; - $taskstatic->ref=$lines[$i]->id; + $taskstatic->ref=($lines[$i]->ref?$lines[$i]->ref:$lines[$i]->id); print $taskstatic->getNomUrl(1); print ''; From 2f388949f63d92550dcda7421356e56a79c1ddc2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 7 Feb 2015 03:11:35 +0100 Subject: [PATCH 031/173] Make a test with jsganttimproved --- htdocs/langs/en_US/main.lang | 1 + htdocs/projet/ganttchart.inc.php | 106 +++++++++++++++++++++---------- htdocs/projet/ganttview.php | 3 +- 3 files changed, 76 insertions(+), 34 deletions(-) diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 0f41a43c90f..1bc5b2a8c36 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -14,6 +14,7 @@ FormatDateShortJava=MM/dd/yyyy FormatDateShortJavaInput=MM/dd/yyyy FormatDateShortJQuery=mm/dd/yy FormatDateShortJQueryInput=mm/dd/yy +FormatHourShortJQuery=HH:MI FormatHourShort=%I:%M %p FormatHourShortDuration=%H:%M FormatDateTextShort=%b %d, %Y diff --git a/htdocs/projet/ganttchart.inc.php b/htdocs/projet/ganttchart.inc.php index 7b4249a0128..849e89ba16c 100644 --- a/htdocs/projet/ganttchart.inc.php +++ b/htdocs/projet/ganttchart.inc.php @@ -24,8 +24,7 @@ ?>
-
+
'; diff --git a/htdocs/install/upgrade.php b/htdocs/install/upgrade.php index e93b27ab6e9..3fe51cc8192 100644 --- a/htdocs/install/upgrade.php +++ b/htdocs/install/upgrade.php @@ -83,7 +83,7 @@ if (! $versionfrom && ! $versionto) $sapi_type = php_sapi_name(); $script_file = basename(__FILE__); $path=dirname(__FILE__).'/'; - if (substr($sapi_type, 0, 3) == 'cli') + if (substr($sapi_type, 0, 3) == 'cli') { print 'Syntax from command line: '.$script_file." x.y.z a.b.c\n"; } @@ -178,7 +178,7 @@ if (! GETPOST("action") || preg_match('/upgrade/i',GETPOST('action'))) print ''.$version.''; dolibarr_install_syslog("upgrade: ".$langs->transnoentities("ServerVersion")." : $version"); - // Test database version + // Test database version requirement $versionmindb=$db::VERSIONMIN; //print join('.',$versionarray).' - '.join('.',$versionmindb); if (count($versionmindb) && count($versionarray) @@ -190,6 +190,32 @@ if (! GETPOST("action") || preg_match('/upgrade/i',GETPOST('action'))) $ok=0; } + // Test database version is not forbidden for migration + $dbversion_disallowed=array( + array('type'=>'mysql','version'=>array(5,5,40)), + array('type'=>'mysqli','version'=>array(5,5,40)), + array('type'=>'mysql','version'=>array(5,5,41)), + array('type'=>'mysqli','version'=>array(5,5,41)) + ); + $listofforbiddenversion=''; + foreach ($dbversion_disallowed as $dbversion_totest) + { + if ($dbversion_totest['type'] == $db->type) $listofforbiddenversion.=($listofforbiddenversion?', ':'').join('.',$dbversion_totest['version']); + } + foreach ($dbversion_disallowed as $dbversion_totest) + { + print $db->type.' - '.join('.',$versionarray).' - '.versioncompare($dbversion_totest['version'],$versionarray)."
\n"; + if ($dbversion_totest['type'] == $db->type + && (versioncompare($dbversion_totest['version'],$versionarray) == 0 || versioncompare($dbversion_totest['version'],$versionarray)<=-4 || versioncompare($dbversion_totest['version'],$versionarray)>=4) + ) + { + // Warning: database version too low. + print '
'.$langs->trans("ErrorDatabaseVersionForbiddenForMigration",join('.',$versionarray),$listofforbiddenversion)."
".$langs->trans("Error")."\n"; + dolibarr_install_syslog("upgrade: ".$langs->transnoentities("ErrorDatabaseVersionForbiddenForMigration",join('.',$versionarray),$listofforbiddenversion)); + $ok=0; + break; + } + } } // Force l'affichage de la progression diff --git a/htdocs/langs/en_US/install.lang b/htdocs/langs/en_US/install.lang index ef5b7e20ca6..7de123d5ea3 100644 --- a/htdocs/langs/en_US/install.lang +++ b/htdocs/langs/en_US/install.lang @@ -156,6 +156,7 @@ LastStepDesc=Last step: Define here login and password you plan ActivateModule=Activate module %s ShowEditTechnicalParameters=Click here to show/edit advanced parameters (expert mode) WarningUpgrade=Warning:\nDid your run a database backup first ?\nThis is highly recommanded: for example, due to some bugs into databases systems (for example mysql version 5.5.40), some data or tables may be lost during this process, so it is highly recommanded to have a complete dump of your database before starting migration.\n\nClick OK to start migration process... +ErrorDatabaseVersionForbiddenForMigration=Your database version is %s. It has a critical bug making data loss if you make structure change on your database, like it is required by the migration process. For his reason, migration will not be allowed until you upgrade your database to a higher fixed version (list of known bugged version: %s) ######### # upgrade diff --git a/htdocs/theme/eldy/img/menus/README.md b/htdocs/theme/eldy/img/menus/README.md index 1b3942d1913..12cd9da537a 100644 --- a/htdocs/theme/eldy/img/menus/README.md +++ b/htdocs/theme/eldy/img/menus/README.md @@ -3,7 +3,7 @@ Tutorial to create a new image for menu: 1) First find an image. 2) With Gimp, open image and check there is a alpha channel. If not add one. -3) Convert image into back and white. +3) Convert image into back and white (Menu Image - Mode - Grey levels). 4) Use the degrade tool with option: * Erase color * Opacity: 50 +/- From 7cf115cc8786770affafe7c96086aa0aab773bd7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 14 Feb 2015 12:26:39 +0100 Subject: [PATCH 106/173] Introduce a protection to avoid migration if database has critical bugs making data lost. --- htdocs/install/upgrade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/install/upgrade.php b/htdocs/install/upgrade.php index 3fe51cc8192..8f62a755518 100644 --- a/htdocs/install/upgrade.php +++ b/htdocs/install/upgrade.php @@ -204,7 +204,7 @@ if (! GETPOST("action") || preg_match('/upgrade/i',GETPOST('action'))) } foreach ($dbversion_disallowed as $dbversion_totest) { - print $db->type.' - '.join('.',$versionarray).' - '.versioncompare($dbversion_totest['version'],$versionarray)."
\n"; + //print $db->type.' - '.join('.',$versionarray).' - '.versioncompare($dbversion_totest['version'],$versionarray)."
\n"; if ($dbversion_totest['type'] == $db->type && (versioncompare($dbversion_totest['version'],$versionarray) == 0 || versioncompare($dbversion_totest['version'],$versionarray)<=-4 || versioncompare($dbversion_totest['version'],$versionarray)>=4) ) From 2a9ba93712b0480c174f04650c3dc38de4b89340 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 14 Feb 2015 12:32:22 +0100 Subject: [PATCH 107/173] Update test of module inits --- test/phpunit/ModulesTest.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/phpunit/ModulesTest.php b/test/phpunit/ModulesTest.php index eff4b85c698..3c8b96ffe2a 100755 --- a/test/phpunit/ModulesTest.php +++ b/test/phpunit/ModulesTest.php @@ -128,11 +128,12 @@ class ModulesTest extends PHPUnit_Framework_TestCase $db=$this->savdb; $modulelist=array('Accounting','Adherent','Agenda','Banque','Barcode','Bookmark', - 'CashDesk','Categorie','ClickToDial','Commande','Comptabilite','Contrat','Cron','Deplacement','Document','Don', - 'ECM','Expedition','Export','ExternalRss','ExternalSite','Facture', - 'Fckeditor','Ficheinter','Fournisseur','FTP','GeoIPMaxmind','Gravatar','Holiday','Import','Label','Ldap','Mailing', - 'Notification','OpenSurvey','Paybox','Paypal','Prelevement','Product','Projet','Propale', - 'Service','Societe','Stock','Syslog','Tax','User','WebServices','Workflow'); + 'CashDesk','Categorie','ClickToDial','Commande','Comptabilite','Contrat','Cron','Deplacement','DocumentGeneration','Don','DynamicPrices', + 'ECM','Expedition','Export','ExternalRss','ExternalSite', + 'Facture','Fckeditor','Ficheinter','Fournisseur','FTP','GeoIPMaxmind','Gravatar','Holiday','Import','Label','Ldap', + 'Mailing','MailmanSpip','Margin', + 'Notification','OpenSurvey','Paybox','Paypal','Prelevement','Product','ProductBatch','Projet','Propale', + 'Salaries','Service','Skype','Societe','Stock','SyncSupplierWebServices','Syslog','Tax','User','WebServices','Workflow'); foreach($modulelist as $modlabel) { require_once(DOL_DOCUMENT_ROOT.'/core/modules/mod'.$modlabel.'.class.php'); From bd4b4012812639de9e8fc7130d943fa27ac1d6dc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 14 Feb 2015 15:10:06 +0100 Subject: [PATCH 108/173] New: Introduce "_deprecated" keyword into module version when module has been superseed by another one. --- dev/skeletons/modMyModule.class.php | 2 +- htdocs/core/modules/DolibarrModules.class.php | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/dev/skeletons/modMyModule.class.php b/dev/skeletons/modMyModule.class.php index 4c09e379d9b..e9abfb38bc4 100644 --- a/dev/skeletons/modMyModule.class.php +++ b/dev/skeletons/modMyModule.class.php @@ -57,7 +57,7 @@ class modMyModule extends DolibarrModules $this->name = preg_replace('/^mod/i','',get_class($this)); // Module description, used if translation string 'ModuleXXXDesc' not found (where XXX is value of numeric property 'numero' of module) $this->description = "Description of module MyModule"; - // Possible values for version are: 'development', 'experimental', 'dolibarr' or version + // Possible values for version are: 'development', 'experimental', 'dolibarr' or 'dolibarr_deprecated' or version $this->version = '1.0'; // Key used in llx_const table to save module status enabled/disabled (where MYMODULE is value of property name of module in uppercase) $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index e78e24c316a..0e9b24bb22b 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -416,11 +416,17 @@ abstract class DolibarrModules global $langs; $langs->load("admin"); - if ($this->version == 'experimental') return $langs->trans("VersionExperimental"); - elseif ($this->version == 'development') return $langs->trans("VersionDevelopment"); - elseif ($this->version == 'dolibarr') return DOL_VERSION; - elseif ($this->version) return $this->version; - else return $langs->trans("VersionUnknown"); + $ret=''; + + $newversion=preg_replace('/_deprecated/','',$this->version); + if ($newversion == 'experimental') $ret=$langs->trans("VersionExperimental"); + elseif ($newversion == 'development') $ret=$langs->trans("VersionDevelopment"); + elseif ($newversion == 'dolibarr') $ret=DOL_VERSION; + elseif ($newversion) $ret=$newversion; + else $ret=$langs->trans("VersionUnknown"); + + if (preg_match('/_deprecated/',$this->version)) $ret.=' ('.$langs->trans("Deprecated").')'; + return $ret; } @@ -431,7 +437,7 @@ abstract class DolibarrModules */ function isCoreOrExternalModule() { - if ($this->version == 'dolibarr') return 'core'; + if ($this->version == 'dolibarr' || $this->version == 'dolibarr_deprecated') return 'core'; if (! empty($this->version) && ! in_array($this->version,array('experimental','development'))) return 'external'; if (! empty($this->editor_name) || ! empty($this->editor_web)) return 'external'; return 'unknown'; From 674585136e2f47a47ca3d1f97da574322ef894cb Mon Sep 17 00:00:00 2001 From: KreizIT Date: Sat, 14 Feb 2015 16:16:01 +0100 Subject: [PATCH 109/173] Fix inconsistent data --- htdocs/install/mysql/data/llx_00_c_country.sql | 2 +- htdocs/install/mysql/data/llx_10_c_regions.sql | 2 -- htdocs/install/mysql/data/llx_c_tva.sql | 4 ++-- htdocs/install/mysql/tables/llx_c_regions.sql | 2 +- htdocs/install/mysql/tables/llx_rights_def.sql | 2 +- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/htdocs/install/mysql/data/llx_00_c_country.sql b/htdocs/install/mysql/data/llx_00_c_country.sql index a6c0efc77a6..9c83b70502a 100644 --- a/htdocs/install/mysql/data/llx_00_c_country.sql +++ b/htdocs/install/mysql/data/llx_00_c_country.sql @@ -270,4 +270,4 @@ INSERT INTO llx_c_country (rowid,code,code_iso,label,active,favorite) VALUES (24 INSERT INTO llx_c_country (rowid,code,code_iso,label,active,favorite) VALUES (244,'ME','MNE','Monténégro',1,0); INSERT INTO llx_c_country (rowid,code,code_iso,label,active,favorite) VALUES (245,'BL','BLM','Saint-Barthélemy',1,0); INSERT INTO llx_c_country (rowid,code,code_iso,label,active,favorite) VALUES (246,'MF','MAF','Saint-Martin',1,0); -INSERT INTO llx_c_country (rowid,code,code_iso,label,active,favorite) VALUES (247,'BU', null, 'Burundi',1,0); + diff --git a/htdocs/install/mysql/data/llx_10_c_regions.sql b/htdocs/install/mysql/data/llx_10_c_regions.sql index 4415f5711bf..e1664384323 100644 --- a/htdocs/install/mysql/data/llx_10_c_regions.sql +++ b/htdocs/install/mysql/data/llx_10_c_regions.sql @@ -270,5 +270,3 @@ INSERT INTO llx_c_regions (fk_pays, code_region, cheflieu, tncc, nom, active) v INSERT INTO llx_c_regions (fk_pays, code_region, cheflieu, tncc, nom, active) values ( 12, 1215, '', 0, 'Laâyoune-Boujdour-Sakia el Hamra', 1); INSERT INTO llx_c_regions (fk_pays, code_region, cheflieu, tncc, nom, active) values ( 12, 1216, '', 0, 'Oued Ed-Dahab Lagouira', 1); --- Regions Tunisia (id country=10) -INSERT INTO llx_c_regions (fk_pays, code_region, cheflieu, tncc, nom, active) values ( 10, 1001, '', 0, 'Algerie', 1); diff --git a/htdocs/install/mysql/data/llx_c_tva.sql b/htdocs/install/mysql/data/llx_c_tva.sql index e3f7e56cdc6..7b42efdae0e 100644 --- a/htdocs/install/mysql/data/llx_c_tva.sql +++ b/htdocs/install/mysql/data/llx_c_tva.sql @@ -187,8 +187,8 @@ insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (17 insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (1734, 173, '0','0','VAT Rate 0', 1); -- PERU (id country=181) -insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (1841, 181, '18','0','VAT standard rate',1); -insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (1843, 181, '0','0','VAT Rate 0',1); +insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (1811, 181, '18','0','VAT standard rate',1); +insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (1812, 181, '0','0','VAT Rate 0',1); -- POLAND (id country=184) insert into llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) values (1841, 184, '20','0','VAT standard rate',1); diff --git a/htdocs/install/mysql/tables/llx_c_regions.sql b/htdocs/install/mysql/tables/llx_c_regions.sql index 9c677ee44f7..768a234dbbd 100644 --- a/htdocs/install/mysql/tables/llx_c_regions.sql +++ b/htdocs/install/mysql/tables/llx_c_regions.sql @@ -24,7 +24,7 @@ create table llx_c_regions fk_pays integer NOT NULL, cheflieu varchar(50), tncc integer, - nom varchar(50), + nom varchar(100), active tinyint DEFAULT 1 NOT NULL )ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_rights_def.sql b/htdocs/install/mysql/tables/llx_rights_def.sql index 8bf85add124..297772730c7 100644 --- a/htdocs/install/mysql/tables/llx_rights_def.sql +++ b/htdocs/install/mysql/tables/llx_rights_def.sql @@ -19,7 +19,7 @@ create table llx_rights_def ( - id integer, + id integer NOT NULL, libelle varchar(255), module varchar(64), entity integer DEFAULT 1 NOT NULL, From 0c0c442248c42717cd5bf806fe9e98d4609ebf47 Mon Sep 17 00:00:00 2001 From: KreizIT Date: Sat, 14 Feb 2015 16:27:00 +0100 Subject: [PATCH 110/173] Make MS SQL working --- htdocs/core/db/mssql.class.php | 305 ++++++++++++++----- htdocs/install/etape1.php | 4 +- htdocs/install/etape2.php | 8 +- htdocs/install/mssql/functions/functions.sql | Bin 5010 -> 0 bytes 4 files changed, 241 insertions(+), 76 deletions(-) delete mode 100644 htdocs/install/mssql/functions/functions.sql diff --git a/htdocs/core/db/mssql.class.php b/htdocs/core/db/mssql.class.php index 0f86f01693c..55f5dbe1458 100644 --- a/htdocs/core/db/mssql.class.php +++ b/htdocs/core/db/mssql.class.php @@ -89,6 +89,7 @@ class DoliDBMssql extends DoliDB // (La base Dolibarr a ete forcee en this->forcecharset a l'install) $this->connected = 1; $this->ok = 1; + } else { @@ -146,7 +147,7 @@ class DoliDBMssql extends DoliDB */ function select_db($database) { - return mssql_select_db($database, $this->db); + return @mssql_select_db($database, $this->db); } /** @@ -171,6 +172,18 @@ class DoliDBMssql extends DoliDB // les nouvelles version de Dolibarr car force par l'install Dolibarr. //$this->query('SET NAMES '.$this->forcecharset); //print "Resultat fonction connect: ".$this->db; + $set_options=array('SET ANSI_PADDING ON;', + "SET ANSI_NULLS ON;", + "SET ANSI_WARNINGS ON;", + "SET ARITHABORT ON;", + "SET CONCAT_NULL_YIELDS_NULL ON;", + "SET QUOTED_IDENTIFIER ON;" + ); + mssql_query(implode(' ',$set_options),$this->db); + + + + return $this->db; } @@ -224,19 +237,22 @@ class DoliDBMssql extends DoliDB */ function begin() { - if (! $this->transaction_opened) + + $res=mssql_query('select @@TRANCOUNT'); + $this->transaction_opened=mssql_result($res, 0, 0); + + if ($this->transaction_opened == 0) { - $ret=$this->query("BEGIN TRANSACTION"); + //return 1; //There is a mess with auto_commit and 'SET IMPLICIT_TRANSACTIONS ON' generate also a mess + $ret=mssql_query("SET IMPLICIT_TRANSACTIONS OFF;BEGIN TRANSACTION;",$this->db); if ($ret) { - $this->transaction_opened++; dol_syslog("BEGIN Transaction",LOG_DEBUG); } return $ret; } else { - $this->transaction_opened++; return 1; } } @@ -249,12 +265,15 @@ class DoliDBMssql extends DoliDB */ function commit($log='') { - if ($this->transaction_opened <= 1) + $res=mssql_query('select @@TRANCOUNT'); + $this->transaction_opened=mssql_result($res, 0, 0); + + if ($this->transaction_opened == 1) { - $ret=$this->query("COMMIT TRANSACTION"); + //return 1; //There is a mess with auto_commit and 'SET IMPLICIT_TRANSACTION ON' generate also a mess + $ret=mssql_query("COMMIT TRANSACTION",$this->db); if ($ret) { - $this->transaction_opened=0; dol_syslog("COMMIT Transaction",LOG_DEBUG); return 1; } @@ -263,11 +282,11 @@ class DoliDBMssql extends DoliDB return 0; } } - else + elseif ($this->transaction_opened > 1) { - $this->transaction_opened--; return 1; - } + } else + trigger_error("Commit requested but no transaction remain"); } /** @@ -278,18 +297,20 @@ class DoliDBMssql extends DoliDB */ function rollback($log='') { - if ($this->transaction_opened<=1) + $res=mssql_query('select @@TRANCOUNT'); + $this->transaction_opened=mssql_result($res, 0, 0); + + if ($this->transaction_opened == 1) { - $ret=$this->query("ROLLBACK TRANSACTION"); - $this->transaction_opened=0; + $ret=mssql_query("ROLLBACK TRANSACTION",$this->db); dol_syslog("ROLLBACK Transaction".($log?' '.$log:''),LOG_DEBUG); return $ret; } - else + elseif ($this->transaction_opened > 1) { - $this->transaction_opened--; return 1; - } + } else + trigger_error("Rollback requested but no transaction remain"); } /** @@ -304,54 +325,98 @@ class DoliDBMssql extends DoliDB function query($query,$usesavepoint=0,$type='auto') { $query = trim($query); + + if (preg_match('/^--/',$query)) return true; // Conversion syntaxe MySql vers MSDE. $query = str_ireplace("now()", "getdate()", $query); // Erreur SQL: cannot update timestamp field $query = str_ireplace(", tms = tms", "", $query); - // Voir si l'on peut directement utiliser $query = str_ireplace("file", "[file]", $query); - // au lieu des 3 lignes ci-dessous - $query = str_ireplace(".file", ".[file]", $query); - $query = str_ireplace(" file ", " [file] ", $query); - $query = str_ireplace(" file,", " [file],", $query); - // Idem file - $query = str_ireplace(".percent", ".[percent]", $query); - $query = str_ireplace(" percent ", " [percent] ", $query); - $query = str_ireplace("percent,", "[percent],", $query); - $query = str_ireplace("percent=", "[percent]=", $query); - $query = str_ireplace("\'", "''", $query); - - $itemfound = stripos($query, " limit "); - if ($itemfound !== false) { - // Extraire le nombre limite - $number = stristr($query, " limit "); - $number = substr($number, 7); - // Inserer l'instruction TOP et le nombre limite - $query = str_ireplace("select ", "select top ".$number." ", $query); - // Supprimer l'instruction MySql - $query = str_ireplace(" limit ".$number, "", $query); + $query=preg_replace("/([. ,\t(])(percent|file|public)([. ,=\t)])/","$1[$2]$3",$query); + + if ($type=="auto" || $type='dml') + { + $query=preg_replace('/AUTO_INCREMENT/i','IDENTITY',$query); + $query=preg_replace('/double/i','float',$query); + $query=preg_replace('/float\((.*)\)/','numeric($1)',$query); + $query=preg_replace('/([ \t])unsigned|IF NOT EXISTS[ \t]/i','$1',$query); + $query=preg_replace('/([ \t])(MEDIUM|TINY|LONG){0,1}TEXT([ \t,])/i',"$1VARCHAR(MAX)$3",$query); + + $matches=array(); + $original_query=''; + if (preg_match('/ALTER TABLE\h+(\w+?)\h+ADD\h+(?:(UNIQUE)|INDEX)\h+(?:INDEX)?\h*(\w+?)\h*\((.+)\)/is', $query,$matches)) + { + $original_query=$query; + $query="CREATE ".trim($matches[2])." INDEX [".trim($matches[3])."] ON [".trim($matches[1])."] (".trim($matches[4]).")"; + if ($matches[2]) { + //check if columun is nullable cause Sql server only allow 1 null value if unique index. + $fields=explode(",",trim($matches[4])); + $fields_clear=array_map('trim',$fields); + $infos=$this->GetFieldInformation(trim($matches[1]), $fields_clear); + $query_comp=array(); + foreach($infos as $fld) { + if ($fld->IS_NULLABLE == 'YES') { + $query_comp[]=$fld->COLUMN_NAME." IS NOT NULL"; + } + } + if ($query_comp) + $query.=" WHERE ".implode(" AND ",$query_comp); + } + } + else + { + if (preg_match('/ALTER TABLE\h+(\w+?)\h+ADD\h+PRIMARY\h+KEY\h+(\w+?)\h*\((.+)\)/is', $query, $matches)) + { + $original_query=$query; + $query="ALTER TABLE [".$matches[1]."] ADD CONSTRAINT [".$matches[2]."] PRIMARY KEY CLUSTERED (".$matches[3].")"; + } + } + } - $itemfound = stripos($query, " week("); - if ($itemfound !== false) { - // Recreer une requete sans instruction Mysql - $positionMySql = stripos($query, " week("); - $newquery = substr($query, 0, $positionMySql); - - // Recuperer la date passee en parametre - $extractvalue = stristr($query, " week("); - $extractvalue = substr($extractvalue, 6); - $positionMySql = stripos($extractvalue, ")"); - // Conserver la fin de la requete - $endofquery = substr($extractvalue, $positionMySql); - $extractvalue = substr($extractvalue, 0, $positionMySql); - - // Remplacer l'instruction MySql en Sql Server - // Inserer la date en parametre et le reste de la requete - $query = $newquery." DATEPART(week, ".$extractvalue.$endofquery; + if ($type=="auto" || $type='ddl') + { + $itemfound = stripos($query, " limit "); + if ($itemfound !== false) { + // Extraire le nombre limite + $number = stristr($query, " limit "); + $number = substr($number, 7); + // Inserer l'instruction TOP et le nombre limite + $query = str_ireplace("select ", "select top ".$number." ", $query); + // Supprimer l'instruction MySql + $query = str_ireplace(" limit ".$number, "", $query); + } + + $itemfound = stripos($query, " week("); + if ($itemfound !== false) { + // Recreer une requete sans instruction Mysql + $positionMySql = stripos($query, " week("); + $newquery = substr($query, 0, $positionMySql); + + // Recuperer la date passee en parametre + $extractvalue = stristr($query, " week("); + $extractvalue = substr($extractvalue, 6); + $positionMySql = stripos($extractvalue, ")"); + // Conserver la fin de la requete + $endofquery = substr($extractvalue, $positionMySql); + $extractvalue = substr($extractvalue, 0, $positionMySql); + + // Remplacer l'instruction MySql en Sql Server + // Inserer la date en parametre et le reste de la requete + $query = $newquery." DATEPART(week, ".$extractvalue.$endofquery; + } + if (preg_match('/^insert\h+(?:INTO)?\h*(\w+?)\h*\(.*\b(?:row)?id\b.*\)\h+VALUES/i',$query,$matches)) + { + //var_dump($query); + //var_dump($matches); + if (stripos($query,'llx_c_departements') !== false) var_dump($query); + $sql='SET IDENTITY_INSERT ['.trim($matches[1]).'] ON;'; + @mssql_query($sql, $this->db); + $post_query='SET IDENTITY_INSERT ['.trim($matches[1]).'] OFF;'; + + } } - //print ""; if (! in_array($query,array('BEGIN','COMMIT','ROLLBACK'))) dol_syslog('sql='.$query, LOG_DEBUG); @@ -365,6 +430,11 @@ class DoliDBMssql extends DoliDB { $ret = mssql_query($query, $this->db); } + + if (!empty($post_query)) + { + @mssql_query($post_query, $this->db); + } if (! preg_match("/^COMMIT/i",$query) && ! preg_match("/^ROLLBACK/i",$query)) { @@ -379,12 +449,13 @@ class DoliDBMssql extends DoliDB $this->lasterrno = $row["code"]; dol_syslog(get_class($this)."::query SQL Error query: ".$query, LOG_ERR); + if ($original_query) dol_syslog(get_class($this)."::query SQL Original query: ".$original_query, LOG_ERR); dol_syslog(get_class($this)."::query SQL Error message: ".$this->lasterror." (".$this->lasterrno.")", LOG_ERR); } $this->lastquery=$query; $this->_results = $ret; } - + return $ret; } @@ -539,7 +610,8 @@ class DoliDBMssql extends DoliDB 1146 => 'DB_ERROR_NOSUCHTABLE', 1216 => 'DB_ERROR_NO_PARENT', 1217 => 'DB_ERROR_CHILD_EXISTS', - 1451 => 'DB_ERROR_CHILD_EXISTS' + 1451 => 'DB_ERROR_CHILD_EXISTS', + 1913 => 'DB_ERROR_KEY_NAME_ALREADY_EXISTS' ); if (isset($errorcode_map[$this->lasterrno])) @@ -563,7 +635,7 @@ class DoliDBMssql extends DoliDB return 'Not connected. Check setup parameters in conf/conf.php file and your mssql client and server versions'; } else { - return mssql_get_last_message($this->db); + return mssql_get_last_message(); } } @@ -655,20 +727,35 @@ class DoliDBMssql extends DoliDB */ function DDLCreateDb($database,$charset='',$collation='',$owner='') { - if (empty($charset)) $charset=$this->forcecharset; + /*if (empty($charset)) $charset=$this->forcecharset; if (empty($collation)) $collation=$this->forcecollate; + */ +<<<<<<< Updated upstream // ALTER DATABASE dolibarr_db DEFAULT CHARACTER SET latin DEFAULT COLLATE latin1_swedish_ci $sql = 'CREATE DATABASE '.$database; $sql.= ' DEFAULT CHARACTER SET '.$charset.' DEFAULT COLLATE '.$collation; +======= + $sql = 'CREATE DATABASE '.$this->EscapeFieldName($database); + //TODO: Check if we need to force a charset + //$sql.= ' DEFAULT CHARACTER SET '.$charset.' DEFAULT COLLATE '.$collation; +>>>>>>> Stashed changes $ret=$this->query($sql); - if (! $ret) - { - // On reessaie pour compatibilite avec mssql < 5.0 - $sql = 'CREATE DATABASE '.$database; - $ret=$this->query($sql); - } - + + + $this->select_db($database); + $sql="CREATE USER [$owner] FOR LOGIN [$owner]"; + mssql_query($sql,$this->db); + $sql="ALTER ROLE [db_owner] ADD MEMBER [$owner]"; + mssql_query($sql,$this->db); + + //For version >=2008 + $sql="ALTER DATABASE [$database] SET ANSI_NULL_DEFAULT ON;"; + @mssql_query($sql,$this->db); + $sql="ALTER DATABASE [$database] SET ANSI_NULL ON;"; + @mssql_query($sql,$this->db); + + return $ret; } @@ -884,12 +971,40 @@ class DoliDBMssql extends DoliDB */ function DDLCreateUser($dolibarr_main_db_host,$dolibarr_main_db_user,$dolibarr_main_db_pass,$dolibarr_main_db_name) { - // FIXME: Dummy method - // TODO: Implement - // May help: http://msdn.microsoft.com/fr-fr/library/ms173463.aspx - - // Always fail for now - return -1; + $sql = "CREATE LOGIN ".$this->EscapeFieldName($dolibarr_main_db_user)." WITH PASSWORD='$dolibarr_main_db_pass'"; + dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG); // No sql to avoid password in log + $resql=$this->query($sql); + if (! $resql) + { + if ($this->lasterrno != '15025') + { + return -1; + } + else + { + // If user already exists, we continue to set permissions + dol_syslog(get_class($this)."::DDLCreateUser sql=".$sql, LOG_WARNING); + } + } + $sql="SELECT name from sys.databases where name='".$dolibarr_main_db_name."'"; + $ressql=$this->query($sql); + if (! $ressql) + { + dol_syslog(get_class($this)."::DDLCreateUser sql=".$sql, LOG_WARNING); + return -1; + } + else + { + if ($num) + { + $this->select_db($dolibarr_main_db_name); + $sql="CREATE USER [$dolibarr_main_db_user] FOR LOGIN [$dolibarr_main_db_user]"; + $this->query($sql); + $sql="ALTER ROLE [db_owner] ADD MEMBER [$dolibarr_main_db_user]"; + $this->query($sql); + } + } + return 1; } /** @@ -1003,5 +1118,49 @@ class DoliDBMssql extends DoliDB return array(); } + + /** + * Escape a field name according to escape's syntax + * + * @param string $fieldname Field's name to escape + * @return string field's name escaped + */ + function EscapeFieldName($fieldname) { + return "[".$fieldname."]"; + } + + + /** + * Get information on field + * + * @param string $table Table name which contains fields + * @param mixed $fields String for one field or array of string for multiple field + * @return boolean|multitype:object + */ + function GetFieldInformation($table,$fields) { + $sql="SELECT * from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='".$this->escape($table)."' AND COLUMN_NAME"; + if (is_array($fields)) + { + $where=" IN ('".implode("','",$fields)."')"; + } + else + { + $where="='".$this->escape($fields)."'"; + } + $result=array(); + $ret=mssql_query($sql.$where,$this->db); + if ($ret) + { + while($obj=mssql_fetch_object($ret)) + { + $result[]=$obj; + } + } + else + return false; + + return $result; + } + } diff --git a/htdocs/install/etape1.php b/htdocs/install/etape1.php index 20450760127..50d5ee27b55 100644 --- a/htdocs/install/etape1.php +++ b/htdocs/install/etape1.php @@ -175,7 +175,7 @@ if (! $error) } else { - $databasefortest='mssql'; + $databasefortest='master'; } } //print $_POST["db_type"].",".$_POST["db_host"].",$userroot,$passroot,$databasefortest,".$_POST["db_port"]; @@ -486,7 +486,7 @@ if (! $error && $db->connected && $action == "set") } else if ($conf->db->type == 'mssql') { - $databasefortest='mssql'; + $databasefortest='master'; } // Creation handler de base, verification du support et connexion diff --git a/htdocs/install/etape2.php b/htdocs/install/etape2.php index f97f1afaa9c..1f6c5244d84 100644 --- a/htdocs/install/etape2.php +++ b/htdocs/install/etape2.php @@ -1,6 +1,7 @@ * Copyright (C) 2004-2010 Laurent Destailleur + * Copyright (C) 2015 Cedric GROSS * * 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 @@ -192,6 +193,11 @@ if ($action == "set") { $buffer=preg_replace('/type=innodb/i','ENGINE=innodb',$buffer); } + else if ($conf->db->type == 'mssql') + { + $buffer=preg_replace('/type=innodb/i','',$buffer); + $buffer=preg_replace('/ENGINE=innodb/i','',$buffer); + } // Replace the prefix tables if ($dolibarr_main_db_prefix != 'llx_') @@ -219,7 +225,7 @@ if ($action == "set") else { print "".$langs->trans("CreateTableAndPrimaryKey",$name); - print "
\n".$langs->trans("Request").' '.$requestnb.' : '.$buffer; + print "
\n".$langs->trans("Request").' '.$requestnb.' : '.$buffer.'
Executed query : '.$db->lastquery; print "\n"; print ''.$langs->trans("ErrorSQL")." ".$db->errno()." ".$db->error().''; $error++; diff --git a/htdocs/install/mssql/functions/functions.sql b/htdocs/install/mssql/functions/functions.sql deleted file mode 100644 index 1c2c76996dc312cc2440a2329d46530adb815d7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5010 zcmd^@T~8ZF6o%)P{S|wMX%i@|s;DiAaBNIn5uC!KHu}P{PFwK@HC|1`A7Om&`$a_!Z=LAeVB$}xC+-{#$JuxEq=cY zU+{Ux>P^Tv9fq9s_uQDX%6T5~yvN;mx*sk$z2W364A`HB?QqH87vbN@>%!p{PU7E$ zd(JmwtMnn(Pc(8Lql;8pDB0b zYuTh7KRFD?;e_WyC`Lv#z}IPbjr23~`Z-TWNIEwPc`Zd_ahfb>a^rTv-r15qQAP{d z?uV{PpM~g$G_=@pjR)v7x%a(Q}U-Ay1qoU!Ip&GV`x67`0NSOpr6= zOgekKgzgbE@{_zDJ@G0WAfbVDmr@Te(dNiBk`9j8mOURs+vTIkceo`@g*Iu~gQ9`{ zNA{%M6Lw!i*X7nWbSW!Gl4}|@cpQo^3(b^ELTHMu8TJj#^Encof0XhTI%TZTuGNkC zMo|+!J%g1cLwlCr27FaJR1H@V`xu?0CdyG|!WCR&G(CFj>XAIxwyYmh$tk4KxVlvQo8+-5B_ci2g&rXBtYwJ{gFQ1m$yx{o-iQi?;$sko=y`U&bTYthw= z&k?%~JN=Bk7P30w6{{R%38`Z$?=QskoLJ`UpOTHz=z#U|Ss!!?na}xl$kQJRzHUzq z9X5&k2&&)ER~7OWt~o1pwh5=Imdf)czp4cj&SO>c`z_-ll!=>c+ceDSsaJVwVOx3D z;#B;%@ZC%FI^?drnW2j;i~aBdTgTX(BfGzHnulM(Y8v(noz?kdf$El9EiDp!Dc{tQ zC=a!W%dz>ljaQD@`8yvZ#3TtD$Y|mf@6i{w~QbwpmIb;K=OAjFjzjP$Cw zj^cG(n}r9P7UdT9K(OW`R$w^PU zHdk)Z-4e7FHpP8;UCqc(C6hIQYI5x_@Eq~^spRord!WqX1M0}wva-x6;d2?A%8mDP zd|lQq-%3HE*O)r1<|04#L1~mJ{BH75C8%bMVkAT_w2)qRFY+rzX`AQsjsc4 zyM$7c{Q?j1uKIHMKa!eN0sVKxKdK37_?)l)Lm(?^6+CGQQ&n0gdy6 Date: Sat, 14 Feb 2015 16:33:05 +0100 Subject: [PATCH 111/173] Fix typo --- htdocs/core/db/mssql.class.php | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/htdocs/core/db/mssql.class.php b/htdocs/core/db/mssql.class.php index 55f5dbe1458..e2d938da710 100644 --- a/htdocs/core/db/mssql.class.php +++ b/htdocs/core/db/mssql.class.php @@ -3,6 +3,7 @@ * Copyright (C) 2004-2008 Laurent Destailleur * Copyright (C) 2005-2007 Regis Houssin * Copyright (C) 2007 Simon Desee + * Copyright (C) 2015 Cedric GROSS * * 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 @@ -89,7 +90,6 @@ class DoliDBMssql extends DoliDB // (La base Dolibarr a ete forcee en this->forcecharset a l'install) $this->connected = 1; $this->ok = 1; - } else { @@ -180,10 +180,7 @@ class DoliDBMssql extends DoliDB "SET QUOTED_IDENTIFIER ON;" ); mssql_query(implode(' ',$set_options),$this->db); - - - - + return $this->db; } @@ -455,7 +452,7 @@ class DoliDBMssql extends DoliDB $this->lastquery=$query; $this->_results = $ret; } - + return $ret; } @@ -731,17 +728,10 @@ class DoliDBMssql extends DoliDB if (empty($collation)) $collation=$this->forcecollate; */ -<<<<<<< Updated upstream - // ALTER DATABASE dolibarr_db DEFAULT CHARACTER SET latin DEFAULT COLLATE latin1_swedish_ci - $sql = 'CREATE DATABASE '.$database; - $sql.= ' DEFAULT CHARACTER SET '.$charset.' DEFAULT COLLATE '.$collation; -======= $sql = 'CREATE DATABASE '.$this->EscapeFieldName($database); //TODO: Check if we need to force a charset //$sql.= ' DEFAULT CHARACTER SET '.$charset.' DEFAULT COLLATE '.$collation; ->>>>>>> Stashed changes $ret=$this->query($sql); - $this->select_db($database); $sql="CREATE USER [$owner] FOR LOGIN [$owner]"; @@ -749,14 +739,12 @@ class DoliDBMssql extends DoliDB $sql="ALTER ROLE [db_owner] ADD MEMBER [$owner]"; mssql_query($sql,$this->db); - //For version >=2008 $sql="ALTER DATABASE [$database] SET ANSI_NULL_DEFAULT ON;"; @mssql_query($sql,$this->db); $sql="ALTER DATABASE [$database] SET ANSI_NULL ON;"; @mssql_query($sql,$this->db); - - - return $ret; + + return $ret; } /** From 448655ea45cd394750fa14203efffaed03b2f476 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 14 Feb 2015 18:39:45 +0100 Subject: [PATCH 112/173] First work on a new module for expense report matching dolibarr standard to replace current one. --- htdocs/core/class/commonobject.class.php | 5 + htdocs/core/lib/functions.lib.php | 19 +- .../expensereport/modules_deplacement.php | 93 + .../expensereport/pdf_teclib.modules.php | 759 +++++++ htdocs/core/modules/modDeplacement.class.php | 2 +- .../core/modules/modExpenseReport.class.php | 347 ++++ htdocs/expensereport/ajax/ajaxprojet.php | 88 + htdocs/expensereport/card.php | 1776 +++++++++++++++++ .../class/expensereport.class.php | 1496 ++++++++++++++ .../class/expensereportstats.class.php | 163 ++ htdocs/expensereport/document.php | 131 ++ htdocs/expensereport/export_csv.php | 199 ++ htdocs/expensereport/index.php | 208 ++ htdocs/expensereport/info.php | 63 + htdocs/expensereport/list.php | 316 +++ htdocs/expensereport/stats/index.php | 297 +++ htdocs/expensereport/synchro_compta.php | 196 ++ .../install/mysql/migration/3.7.0-3.8.0.sql | 74 + .../mysql/tables/llx_expensereport.sql | 54 + .../mysql/tables/llx_expensereport_det.sql | 46 + .../install/mysql/tables/llx_facturedet.sql | 10 +- htdocs/langs/en_US/admin.lang | 11 + htdocs/langs/en_US/trips.lang | 135 +- htdocs/langs/fr_FR/expensereport.lang | 137 ++ 24 files changed, 6595 insertions(+), 30 deletions(-) create mode 100755 htdocs/core/modules/expensereport/modules_deplacement.php create mode 100755 htdocs/core/modules/expensereport/pdf_teclib.modules.php create mode 100755 htdocs/core/modules/modExpenseReport.class.php create mode 100755 htdocs/expensereport/ajax/ajaxprojet.php create mode 100755 htdocs/expensereport/card.php create mode 100755 htdocs/expensereport/class/expensereport.class.php create mode 100644 htdocs/expensereport/class/expensereportstats.class.php create mode 100644 htdocs/expensereport/document.php create mode 100755 htdocs/expensereport/export_csv.php create mode 100644 htdocs/expensereport/index.php create mode 100644 htdocs/expensereport/info.php create mode 100755 htdocs/expensereport/list.php create mode 100755 htdocs/expensereport/stats/index.php create mode 100755 htdocs/expensereport/synchro_compta.php create mode 100755 htdocs/install/mysql/tables/llx_expensereport.sql create mode 100644 htdocs/install/mysql/tables/llx_expensereport_det.sql create mode 100755 htdocs/langs/fr_FR/expensereport.lang diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 79f509225f6..6d464cceb29 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -1656,6 +1656,10 @@ abstract class CommonObject $fieldtva='tva'; $fieldup='pu_ht'; } + if ($this->element == 'expensereport') + { + $fieldup='value_unit'; + } $sql = 'SELECT rowid, qty, '.$fieldup.' as up, remise_percent, total_ht, '.$fieldtva.' as total_tva, total_ttc, '.$fieldlocaltax1.' as total_localtax1, '.$fieldlocaltax2.' as total_localtax2,'; $sql.= ' tva_tx as vatrate, localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, info_bits, product_type'; @@ -1770,6 +1774,7 @@ abstract class CommonObject if ($this->element == 'facture' || $this->element == 'facturerec') $fieldht='total'; if ($this->element == 'facture_fourn' || $this->element == 'invoice_supplier') $fieldtva='total_tva'; if ($this->element == 'propal') $fieldttc='total'; + if ($this->element == 'expensereport') $fieldtva='total_tva'; if (empty($nodatabaseupdate)) { diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 0d247cdb181..10acc6a8c10 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -4172,13 +4172,14 @@ function print_date_range($date_start,$date_end,$format = '',$outputlangs='') /** * Format output for start and end date * - * @param timestamp $date_start Start date - * @param timestamp $date_end End date - * @param string $format Output format - * @param Translate $outputlangs Output language - * @return string String + * @param timestamp $date_start Start date + * @param timestamp $date_end End date + * @param string $format Output format + * @param Translate $outputlangs Output language + * @param string $withparenthesis 1=Add parenthesis, 0=non parenthesis + * @return string String */ -function get_date_range($date_start,$date_end,$format = '',$outputlangs='') +function get_date_range($date_start,$date_end,$format = '',$outputlangs='', $withparenthesis=1) { global $langs; @@ -4188,15 +4189,15 @@ function get_date_range($date_start,$date_end,$format = '',$outputlangs='') if ($date_start && $date_end) { - $out.= ' ('.$outputlangs->trans('DateFromTo',dol_print_date($date_start, $format, false, $outputlangs),dol_print_date($date_end, $format, false, $outputlangs)).')'; + $out.= ($withparenthesis?' (':'').$outputlangs->trans('DateFromTo',dol_print_date($date_start, $format, false, $outputlangs),dol_print_date($date_end, $format, false, $outputlangs)).($withparenthesis?')':''); } if ($date_start && ! $date_end) { - $out.= ' ('.$outputlangs->trans('DateFrom',dol_print_date($date_start, $format, false, $outputlangs)).')'; + $out.= ($withparenthesis?' (':'').$outputlangs->trans('DateFrom',dol_print_date($date_start, $format, false, $outputlangs)).($withparenthesis?')':''); } if (! $date_start && $date_end) { - $out.= ' ('.$outputlangs->trans('DateUntil',dol_print_date($date_end, $format, false, $outputlangs)).')'; + $out.= ($withparenthesis?' (':'').$outputlangs->trans('DateUntil',dol_print_date($date_end, $format, false, $outputlangs)).($withparenthesis?')':''); } return $out; diff --git a/htdocs/core/modules/expensereport/modules_deplacement.php b/htdocs/core/modules/expensereport/modules_deplacement.php new file mode 100755 index 00000000000..707eaad54b8 --- /dev/null +++ b/htdocs/core/modules/expensereport/modules_deplacement.php @@ -0,0 +1,93 @@ +load("trips"); + + // Increase limit for PDF build + $err=error_reporting(); + error_reporting(0); + @set_time_limit(120); + error_reporting($err); + + $dir = dol_buildpath('/expensereport/core/modules/expensereport/'); + + // Positionne modele sur le nom du modele a utiliser + if (! strlen($modele)) + { + if ($conf->global->DEPLACEMENT_ADDON_PDF) + { + $modele = $conf->global->DEPLACEMENT_ADDON_PDF; + } + else + { + print $langs->trans("Error")." ".$langs->trans("Error_DEPLACEMENT_ADDON_PDF_NotDefined"); + return 0; + } + } + + // Charge le modele + $file = "pdf_".$modele.".modules.php"; + if (file_exists($dir.$file)) + { + $classname = "pdf_".$modele; + require_once($dir.$file); + + $obj = new $classname($db); + $obj->message = $message; + + // We save charset_output to restore it because write_file can change it if needed for + // output format that does not support UTF8. + $sav_charset_output=$outputlangs->charset_output; + if ($obj->write_file($id, $outputlangs) > 0) + { + $outputlangs->charset_output=$sav_charset_output; + return 1; + } + else + { + $outputlangs->charset_output=$sav_charset_output; + dol_print_error($db,"expensereport_pdf_create Error: ".$obj->error); + return -1; + } + + } + else + { + dol_print_error('',$langs->trans("Error")." ".$langs->trans("ErrorFileDoesNotExists",$dir.$file)); + return -1; + } +} diff --git a/htdocs/core/modules/expensereport/pdf_teclib.modules.php b/htdocs/core/modules/expensereport/pdf_teclib.modules.php new file mode 100755 index 00000000000..6b3b59639e5 --- /dev/null +++ b/htdocs/core/modules/expensereport/pdf_teclib.modules.php @@ -0,0 +1,759 @@ + + * Copyright (C) 2005-2010 Regis Houssin + * Copyright (C) 2008 Raphael Bertrand + * Copyright (C) 2010 Juanjo Menent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * or see http://www.gnu.org/ + */ + +/** + * \file htdocs/expensereport/core/modules/expensereport/pdf_.modules.php + * \ingroup facture + * \brief File of class to generate invoices from crab model + * \author Laurent Destailleur + */ + +dol_include_once("/expensereport/core/modules/expensereport/modules_expensereport.php"); +require_once(DOL_DOCUMENT_ROOT."/product/class/product.class.php"); +require_once(DOL_DOCUMENT_ROOT."/core/lib/functions2.lib.php"); +require_once(DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php'); +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; + + + +/** + * Classe permettant de generer les factures au modele Crabe + */ +class pdf_ extends ModeleExpenseReport +{ + var $emetteur; // Objet societe qui emet + + + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + function __construct($db) + { + global $conf,$langs,$mysoc; + + $langs->load("main"); + $langs->load("trips"); + $langs->load("project"); + $langs->load("expensereport@expensereport"); + + $this->db = $db; + $this->name = ""; + $this->description = $langs->trans('PDFDescription'); + + // Dimension page pour format A4 + $this->type = 'pdf'; + $formatarray=pdf_getFormat(); + $this->page_largeur = $formatarray['width']; + $this->page_hauteur = $formatarray['height']; + $this->format = array($this->page_largeur,$this->page_hauteur); + $this->marge_gauche=isset($conf->global->MAIN_PDF_MARGIN_LEFT)?$conf->global->MAIN_PDF_MARGIN_LEFT:10; + $this->marge_droite=isset($conf->global->MAIN_PDF_MARGIN_RIGHT)?$conf->global->MAIN_PDF_MARGIN_RIGHT:10; + $this->marge_haute =isset($conf->global->MAIN_PDF_MARGIN_TOP)?$conf->global->MAIN_PDF_MARGIN_TOP:10; + $this->marge_basse =isset($conf->global->MAIN_PDF_MARGIN_BOTTOM)?$conf->global->MAIN_PDF_MARGIN_BOTTOM:10; + + $this->option_logo = 1; // Affiche logo + $this->option_tva = 1; // Gere option tva FACTURE_TVAOPTION + $this->option_modereg = 1; // Affiche mode reglement + $this->option_condreg = 1; // Affiche conditions reglement + $this->option_codeproduitservice = 1; // Affiche code produit-service + $this->option_multilang = 1; // Dispo en plusieurs langues + $this->option_escompte = 1; // Affiche si il y a eu escompte + $this->option_credit_note = 1; // Support credit notes + $this->option_freetext = 1; // Support add of a personalised text + $this->option_draft_watermark = 1; // Support add of a watermark on drafts + + $this->franchise=!$mysoc->tva_assuj; + + // Get source company + $this->emetteur=$mysoc; + if (empty($this->emetteur->country_code)) $this->emetteur->country_code=substr($langs->defaultlang,-2); // By default, if was not defined + + // Defini position des colonnes + // Defini position des colonnes + $this->posxpiece=$this->marge_gauche+1; + $this->posxdesc=20; + $this->posxdate=85; + $this->posxtype=105; + $this->posxprojet=125; + $this->posxtva=145; + $this->posxup=158; + $this->posxqty=170; + $this->postotalttc=176; + if ($this->page_largeur < 210) // To work with US executive format + { + $this->posxdate-=20; + $this->posxtype-=20; + $this->posxprojet-=20; + $this->posxtva-=20; + $this->posxup-=20; + $this->posxqty-=20; + $this->postotalttc-=20; + } + + $this->tva=array(); + $this->localtax1=array(); + $this->localtax2=array(); + $this->atleastoneratenotnull=0; + $this->atleastonediscount=0; + } + + + /** + * Function to build pdf onto disk + * + * @param Object $object Object to generate + * @param Translate $outputlangs Lang output object + * @param string $srctemplatepath Full path of source filename for generator using a template file + * @param int $hidedetails Do not show line details + * @param int $hidedesc Do not show desc + * @param int $hideref Do not show ref + */ + function write_file($object,$outputlangs,$srctemplatepath='',$hidedetails=0,$hidedesc=0,$hideref=0) + { + global $user,$langs,$conf,$mysoc,$db,$hookmanager; + + if (! is_object($outputlangs)) $outputlangs=$langs; + // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO + if (! empty($conf->global->MAIN_USE_FPDF)) $outputlangs->charset_output='ISO-8859-1'; + + + // Hack to use expensereport dir + $rootfordata = DOL_DATA_ROOT; + $rootforuser = DOL_DATA_ROOT; + // If multicompany module is enabled, we redefine the root of data + //if (! empty($this->multicompany->enabled) && ! empty($this->entity) && $this->entity > 1) + //{ + // $rootfordata.='/'.$this->entity; + //} + $conf->expensereport->dir_output = $rootfordata.'/expensereport'; + $conf->expensereport_->dir_output = $rootfordata.'/expensereport'; + + + $outputlangs->load("main"); + $outputlangs->load("dict"); + $outputlangs->load("trips"); + $outputlangs->load("project"); + $outputlangs->load("expensereport@expensereport"); + + $default_font_size = pdf_getPDFFontSize($outputlangs); + + if ($conf->expensereport_->dir_output) + { + // Definition de l'objet $object (pour compatibilite ascendante) + if (! is_object($object)) + { + $id = $object; + $object = new ExpenseReport($db); + $ret=$object->fetch($id,$user); + } + + $objectref = dol_sanitizeFileName($object->ref_number); + $dir = $conf->expensereport_->dir_output . "/" . $objectref; + $file = $dir . "/" . $objectref . ".pdf"; + + if (! file_exists($dir)) + { + if (dol_mkdir($dir) < 0) + { + $this->error=$langs->transnoentities("ErrorCanNotCreateDir",$dir); + return 0; + } + } + + if (isset($object->lignes) && ! isset($object->lines)) $object->lines=$object->lignes; + + if (file_exists($dir)) + { + $nblignes = count($object->lines); + + // Create pdf instance + $pdf=pdf_getInstance($this->format); + + if (class_exists('TCPDF')) + { + $pdf->setPrintHeader(false); + $pdf->setPrintFooter(false); + } + $pdf->SetFont(pdf_getPDFFont($outputlangs)); + // Set path to the background PDF File + if (empty($conf->global->MAIN_DISABLE_FPDI) && ! empty($conf->global->MAIN_ADD_PDF_BACKGROUND)) + { + $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output.'/'.$conf->global->MAIN_ADD_PDF_BACKGROUND); + $tplidx = $pdf->importPage(1); + } + + $pdf->Open(); + $pagenb=0; + $pdf->SetDrawColor(128,128,128); + + $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref_number)); + $pdf->SetSubject($outputlangs->transnoentities("Trips")); + $pdf->SetCreator(""); + $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs))); + $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref_number)." ".$outputlangs->transnoentities("Trips")); + if (! empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) $pdf->SetCompression(false); + + $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right + $pdf->SetAutoPageBreak(1,0); + + // Positionne $this->atleastonediscount si on a au moins une remise + for ($i = 0 ; $i < $nblignes ; $i++) + { + if ($object->lines[$i]->remise_percent) + { + $this->atleastonediscount++; + } + } + + // New page + $pdf->AddPage(); + if (! empty($tplidx)) $pdf->useTemplate($tplidx); + $pagenb++; + $this->_pagehead($pdf, $object, 1, $outputlangs); + $pdf->SetFont('','', $default_font_size - 1); + $pdf->MultiCell(0, 3, ''); // Set interline to 3 + $pdf->SetTextColor(0,0,0); + + $tab_top = 95; + $tab_top_newpage = 95; + $tab_height = 110; + $tab_height_newpage = 110; + + // Affiche notes + if (! empty($object->note)) + { + $tab_top = 93; + + $pdf->SetFont('','', $default_font_size - 1); + $pdf->writeHTMLCell(190, 3, $this->posxdesc-1, $tab_top, dol_htmlentitiesbr($object->note), 0, 1); + $nexY = $pdf->GetY(); + $height_note=$nexY-$tab_top; + + // Rect prend une longueur en 3eme param + $pdf->SetDrawColor(192,192,192); + $pdf->Rect($this->marge_gauche, $tab_top-1, $this->page_largeur-$this->marge_gauche-$this->marge_droite, $height_note+1); + + $tab_height = $tab_height - $height_note; + $tab_top = $nexY+6; + } + else + { + $height_note=0; + } + + $iniY = $tab_top + 7; + $curY = $tab_top + 7; + $nexY = $tab_top + 7; + + // Loop on each lines + for ($i = 0 ; $i < $nblignes ; $i++) + { + $curY = $nexY; + $pdf->SetFont('','', $default_font_size - 1); // Into loop to work with multipage + $pdf->SetTextColor(0,0,0); + + $piece_comptable = $i +1; + + // Piece comptable + $pdf->SetFont('','', $default_font_size - 1); + $pdf->writeHTMLCell($this->posxcomment-$this->posxpiece-1, 3, $this->posxpiece-1, $curY, $piece_comptable, 0, 1); + + // Comments + $pdf->SetFont('','', $default_font_size - 1); + $pdf->SetXY ($this->posxcomment, $curY); + $pdf->writeHTMLCell($this->posxdate-$this->posxdesc-1, 3, $this->posxdesc-1, $curY, $object->lignes[$i]->comments, 0, 1); + + //nexY + $nexY = $pdf->GetY(); + + // Date + $pdf->SetFont('','', $default_font_size - 1); + $pdf->SetXY ($this->posxdate, $curY); + $pdf->MultiCell($this->posxtype-$this->posxdate-1, 3,dol_print_date($object->lignes[$i]->date,"day",false,$outpulangs), 0, 'C'); + + // Type + $pdf->SetFont('','', $default_font_size - 1); + $pdf->SetXY ($this->posxtype, $curY); + $pdf->MultiCell($this->posxprojet-$this->posxtype-1, 3,$outputlangs->transnoentities($object->lignes[$i]->type_fees_code), 0, 'C'); + + // Projet + $pdf->SetFont('','', $default_font_size - 1); + $pdf->SetXY ($this->posxprojet, $curY); + $pdf->MultiCell($this->posxtva-$this->posxprojet-1, 3,$object->lignes[$i]->projet_ref, 0, 'C'); + + // TVA + $pdf->SetFont('','', $default_font_size - 1); + $pdf->SetXY ($this->posxtva, $curY); + $pdf->MultiCell($this->posxup-$this->posxtva-1, 3,vatrate($object->lignes[$i]->tva_taux,true), 0, 'R'); + + // UP + $pdf->SetFont('','', $default_font_size - 1); + $pdf->SetXY ($this->posxup, $curY); + $pdf->MultiCell($this->posxqty-$this->posxup-1, 3,price($object->lignes[$i]->value_unit), 0, 'R'); + + // QTY + $pdf->SetFont('','', $default_font_size - 1); + $pdf->SetXY ($this->posxqty, $curY); + $pdf->MultiCell($this->postotalttc-$this->posxqty, 3,$object->lignes[$i]->qty, 0, 'C'); + + // TotalTTC + $pdf->SetFont('','', $default_font_size - 1); + $pdf->SetXY ($this->postotalttc-2, $curY); + $pdf->MultiCell(26, 3,price($object->lignes[$i]->total_ttc), 0, 'R'); + + $nexY+=5; + + // Cherche nombre de lignes a venir pour savoir si place suffisante + if ($i < ($nblignes - 1)) // If it's not last line + { + //on recupere la description du produit suivant + $follow_descproduitservice = $object->lines[$i+1]->desc; + //on compte le nombre de ligne afin de verifier la place disponible (largeur de ligne 52 caracteres) + $nblineFollowDesc = dol_nboflines_bis($follow_descproduitservice,52,$outputlangs->charset_output)*4; + // Et si on affiche dates de validite, on ajoute encore une ligne + if ($object->lines[$i]->date_start && $object->lines[$i]->date_end) + { + $nblineFollowDesc += 4; + } + } + else // If it's last line + { + $nblineFollowDesc = 0; + } + + // Test if a new page is required + if ($pagenb == 1) + { + $tab_top_in_current_page=$tab_top; + $tab_height_in_current_page=$tab_height; + } + else + { + $tab_top_in_current_page=$tab_top_newpage; + $tab_height_in_current_page=$tab_height_newpage; + } + if (($nexY+$nblineFollowDesc) > ($tab_top_in_current_page+$tab_height_in_current_page) && $i < ($nblignes - 1)) + { + if ($pagenb == 1): + $this->_tableau($pdf, $tab_top, $tab_height, $nexY, $outputlangs); + $nexY=$tab_top + $tab_height + 1; + else: + $this->_tableau($pdf, $tab_top_newpage, $tab_height_newpage, $nexY, $outputlangs); + $nexY=$tab_top_newpage + $tab_height_newpage + 1; + endif; + + $this->_pagefoot($pdf,$object,$outputlangs); + + // New page + $pdf->AddPage(); + $pagenb++; + $this->_pagehead($pdf, $object, 0, $outputlangs); + $pdf->SetFont('','', $default_font_size - 1); + $pdf->MultiCell(0, 3, ''); // Set interline to 3 + $pdf->SetTextColor(0,0,0); + + $nexY = $tab_top_newpage + 7; + } + + } + + // Show square + if ($pagenb == 1) + { + $this->_tableau($pdf, $tab_top, $tab_height, $nexY, $outputlangs); + $bottomlasttab=$tab_top + $tab_height + 1; + } + else + { + $this->_tableau($pdf, $tab_top_newpage, $tab_height_newpage, $nexY, $outputlangs); + $bottomlasttab=$tab_top_newpage + $tab_height_newpage + 1; + } + + // Affiche zone totaux + $posy=$bottomlasttab+5;//$nexY+95; + $pdf->SetXY(120, $posy); + $pdf->MultiCell(50, 5, $outputlangs->transnoentities("TotalHT"), 1, 'L'); + $pdf->SetXY (170, $posy); + $pdf->MultiCell(30, 5, price($object->total_ht), 1, 'R'); + $pdf->SetFillColor(248,248,248); + + $posy+=5; + $pdf->SetXY (120, $posy); + $pdf->SetFont('','B', 10); + $pdf->SetTextColor(0,0,60); + $pdf->MultiCell(50, 5, $outputlangs->transnoentities("TotalTTC"), 1,'L'); + $pdf->SetXY (170, $posy); + $pdf->MultiCell(30, 5, price($object->total_ttc),1, 'R'); + + // Pied de page + $this->_pagefoot($pdf,$object,$outputlangs); + if (method_exists($pdf,'AliasNbPages')) $pdf->AliasNbPages(); + + $pdf->Close(); + + $pdf->Output($file,'F'); + + // Add pdfgeneration hook + if (! is_object($hookmanager)) + { + include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; + $hookmanager=new HookManager($this->db); + } + $hookmanager->initHooks(array('pdfgeneration')); + $parameters=array('file'=>$file,'object'=>$object,'outputlangs'=>$outputlangs); + global $action; + $reshook=$hookmanager->executeHooks('afterPDFCreation',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks + + if (! empty($conf->global->MAIN_UMASK)) + @chmod($file, octdec($conf->global->MAIN_UMASK)); + + return 1; // Pas d'erreur + } + else + { + $this->error=$langs->trans("ErrorCanNotCreateDir",$dir); + return 0; + } + } + else + { + $this->error=$langs->trans("ErrorConstantNotDefined","DEPLACEMENT_OUTPUTDIR"); + return 0; + } + $this->error=$langs->trans("ErrorUnknown"); + return 0; // Erreur par defaut + } + + /** + * Show top header of page. + * + * @param PDF &$pdf Object PDF + * @param Object $object Object to show + * @param int $showaddress 0=no, 1=yes + * @param Translate $outputlangs Object lang for output + * @return void + */ + function _pagehead(&$pdf, $object, $showaddress, $outputlangs) + { + global $conf,$langs,$hookmanager; + + $outputlangs->load("main"); + $outputlangs->load("trips"); + $outputlangs->load("companies"); + $default_font_size = pdf_getPDFFontSize($outputlangs); + + /* + // ajout du fondu vert en bas de page à droite + $image_fondue = $conf->mycompany->dir_output.'/fondu_vert_.jpg'; + $pdf->Image($image_fondue,20,107,200,190); + + pdf_pagehead($pdf,$outputlangs,$this->page_hauteur); + */ + + // Filligrane brouillon + if($object->fk_c_expensereport_statuts==1) + { + pdf_watermark($pdf,$outputlangs,$this->page_hauteur,$this->page_largeur,'mm',"' - PREVIEW ONLY"); + } + + $pdf->SetTextColor(0,0,60); + $pdf->SetFont('','B', $default_font_size + 3); + + $posy=$this->marge_haute; + $posx=$this->page_largeur-$this->marge_droite-100; + + $pdf->SetXY($this->marge_gauche,$posy); + + // Logo + $logo=$conf->mycompany->dir_output.'/logos/'.$this->emetteur->logo; + if ($this->emetteur->logo) + { + if (is_readable($logo)) + { + $height=pdf_getHeightForLogo($logo); + $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto) + } + else + { + $pdf->SetTextColor(200,0,0); + $pdf->SetFont('','B', $default_font_size -2); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound",$logo), 0, 'L'); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L'); + } + } + else + { + $text=$this->emetteur->name; + $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, 'L'); + } + + $pdf->SetFont('','B', $default_font_size + 6); + $pdf->SetXY($posx,$posy); + $pdf->SetTextColor(255,255,255); + $pdf->SetFillColor(193,219,62); + $ref_text = explode($conf->global->NDF_EXPLODE_CHAR,$object->ref_number); + $ref_text = substr($ref_text[1],3,$conf->global->NDF_NUM_CAR_REF); + $pdf->MultiCell(110,6,"Note de frais ".$ref_text, 0, 'L', 1); + + $pdf->SetFont('','', $default_font_size -1); + + // Réf complète + $posy+=8; + $pdf->SetXY(100,$posy); + $pdf->SetTextColor(0,0,60); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Ref")." : " . $object->ref_number, '', 'L'); + + // Date début période + $posy+=5; + $pdf->SetXY(100,$posy); + $pdf->SetTextColor(0,0,60); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("DateStart")." : " . ($object->date_debut>0?$object->date_debut:dol_print_date($object->date_debut,"day",false,$outpulangs)), '', 'L'); + + // Date fin période + $posy+=5; + $pdf->SetXY(100,$posy); + $pdf->SetTextColor(0,0,60); + $pdf->MultiCell(100, 3, $outputlangs->transnoentities("DateEnd")." : " . ($object->date_fin>0?dol_print_date($object->date_fin,"day",false,$outpulangs):''), '', 'L'); + + // Statut NDF + $posy+=7; + $pdf->SetXY(100,$posy); + $pdf->SetFont('','B',20); + $pdf->SetTextColor(111,81,124); + if(preg_match("#Pay#",$object->libelle_statut) && !preg_match("#A P#",$object->libelle_statut)): + $pdf->MultiCell(100, 3,$outputlangs->convToOutputCharset("Payée"), '', 'L'); + elseif(preg_match("#Annul#",$object->libelle_statut)): + $pdf->MultiCell(100, 3,$outputlangs->convToOutputCharset("Annulée"), '', 'L'); + elseif(preg_match("#Refus#",$object->libelle_statut)): + $pdf->MultiCell(100, 3,$outputlangs->convToOutputCharset("Refusée"), '', 'L'); + else: + $pdf->MultiCell(100, 3,$object->libelle_statut, '', 'L'); + endif; + + // Sender properties + $carac_emetteur = ''; + $carac_emetteur .= ($carac_emetteur ? "\n" : '' ).$outputlangs->convToOutputCharset($this->emetteur->address); + $carac_emetteur .= ($carac_emetteur ? "\n" : '' ).$outputlangs->convToOutputCharset($this->emetteur->zip).' '.$outputlangs->convToOutputCharset($this->emetteur->town); + $carac_emetteur .= "\n"; + // Tel + if ($this->emetteur->phone) $carac_emetteur .= ($carac_emetteur ? "\n" : '' ).$outputlangs->transnoentities("Phone")." : ".$outputlangs->convToOutputCharset($this->emetteur->phone); + // Fax + if ($this->emetteur->fax) $carac_emetteur .= ($carac_emetteur ? ($this->emetteur->tel ? " - " : "\n") : '' ).$outputlangs->transnoentities("Fax")." : ".$outputlangs->convToOutputCharset($this->emetteur->fax); + // EMail + if ($this->emetteur->email) $carac_emetteur .= ($carac_emetteur ? "\n" : '' ).$outputlangs->transnoentities("Email")." : ".$outputlangs->convToOutputCharset($this->emetteur->email); + // Web + if ($this->emetteur->url) $carac_emetteur .= ($carac_emetteur ? "\n" : '' ).$outputlangs->transnoentities("Web")." : ".$outputlangs->convToOutputCharset($this->emetteur->url); + + // Show sender + $posy=50; + $posx=$this->marge_gauche; + $hautcadre=40; + if (! empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) $posx=118; + + // Show sender frame + $pdf->SetTextColor(0,0,0); + $pdf->SetFont('','B', $default_font_size - 2); + $pdf->SetXY($posx,$posy-5); + $pdf->MultiCell(66,5, $outputlangs->transnoentities("TripSociete")." :",'','L'); + $pdf->SetXY($posx,$posy); + $pdf->SetFillColor(224,224,224); + $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1); + $pdf->SetTextColor(0,0,60); + + // Show sender name + $pdf->SetXY($posx+2,$posy+3); + $pdf->SetFont('','B', $default_font_size); + $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L'); + + // Show sender information + $pdf->SetXY($posx+2,$posy+8); + $pdf->SetFont('','', $default_font_size - 1); + $pdf->MultiCell(80, 4, $carac_emetteur, 0, 'L'); + + // Show recipient + $posy=50; + $posx=100; + + // Show recipient frame + $pdf->SetTextColor(0,0,0); + $pdf->SetFont('','B',8); + $pdf->SetXY($posx,$posy-5); + $pdf->MultiCell(80,5, $outputlangs->transnoentities("TripNDF")." :", 0, 'L'); + $pdf->rect($posx, $posy, 100, $hautcadre); + + // Informations for trip (dates and users workflow) + $userfee=new User($this->db); + $userfee->fetch($object->fk_user_author); $posy+=3; + $pdf->SetXY($posx+2,$posy); + $pdf->SetFont('','',10); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("AUTHOR")." : ".$outputlangs->convToOutputCharset($userfee->firstname)." ".$outputlangs->convToOutputCharset($userfee->lastname),0,'L'); + $posy+=5; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("DATE_SAVE")." : ".dol_print_date($object->date_create,"day",false,$outpulangs),0,'L'); + + if($object->fk_c_expensereport_statuts<3): + $userfee=new User($this->db); + $userfee->fetch($object->fk_user_validator); $posy+=6; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("VALIDATOR")." : ".$outputlangs->convToOutputCharset($userfee->firstname)." ".$outputlangs->convToOutputCharset($userfee->lastname),0,'L'); + elseif($object->fk_c_expensereport_statuts==99): + $userfee=new User($this->db); + $userfee->fetch($object->fk_user_refuse); $posy+=6; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("REFUSEUR")." : ".$outputlangs->convToOutputCharset($userfee->firstname)." ".$outputlangs->convToOutputCharset($userfee->lastname),0,'L'); + $posy+=5; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("MOTIF_REFUS")." : ".$outputlangs->convToOutputCharset($object->detail_refuse),0,'L'); + $posy+=5; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("DATE_REFUS")." : ".dol_print_date($object->date_refuse,"day",false,$outpulangs),0,'L'); + elseif($object->fk_c_expensereport_statuts==4): + $userfee=new User($this->db); + $userfee->fetch($object->fk_user_cancel); $posy+=6; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("CANCEL_USER")." : ".$outputlangs->convToOutputCharset($userfee->firstname)." ".$outputlangs->convToOutputCharset($userfee->lastname),0,'L'); + $posy+=5; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("MOTIF_CANCEL")." : ".$outputlangs->convToOutputCharset($object->detail_cancel),0,'L'); + $posy+=5; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("DATE_CANCEL")." : ".dol_print_date($object->date_cancel,"day",false,$outpulangs),0,'L'); + else: + $userfee=new User($this->db); + $userfee->fetch($object->fk_user_validator); $posy+=6; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("VALIDOR")." : ".$outputlangs->convToOutputCharset($userfee->firstname)." ".$outputlangs->convToOutputCharset($userfee->lastname),0,'L'); + $posy+=5; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("DATE_VALIDE")." : ".dol_print_date($object->date_valide,"day",false,$outpulangs),0,'L'); + endif; + + if($object->fk_c_expensereport_statuts==6): + $userfee=new User($this->db); + $userfee->fetch($object->fk_user_paid); $posy+=6; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("AUTHORPAIEMENT")." : ".$outputlangs->convToOutputCharset($userfee->firstname)." ".$outputlangs->convToOutputCharset($userfee->lastname),0,'L'); + $posy+=5; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("DATE_PAIEMENT")." : ".dol_print_date($object->date_paiement,"day",false,$outpulangs),0,'L'); + endif; + + } + + /** + * Affiche la grille des lignes de factures + * + * @param $pdf Objet PDF + * @param $tab_top Tab top + * @param $tab_height Tab height + * @param $nexY next y + * @param $outputlangs Output langs + * @return void + */ + function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs) + { + global $conf; + + $default_font_size = pdf_getPDFFontSize($outputlangs); + + // Amount in (at tab_top - 1) + $pdf->SetTextColor(0,0,0); + $pdf->SetFont('','', $default_font_size - 2); + $titre = $outputlangs->transnoentities("AmountInCurrency",$outputlangs->transnoentitiesnoconv("Currency".$conf->currency)); + $pdf->SetXY($this->page_largeur - $this->marge_droite - ($pdf->GetStringWidth($titre) + 4), $tab_top -4); + $pdf->MultiCell(($pdf->GetStringWidth($titre) + 3), 2, $titre); + + $pdf->SetDrawColor(128,128,128); + + // Rect prend une longueur en 3eme param + $pdf->Rect($this->marge_gauche, $tab_top, $this->page_largeur-$this->marge_gauche-$this->marge_droite, $tab_height); + // line prend une position y en 3eme param + $pdf->line($this->marge_gauche, $tab_top+5, $this->page_largeur-$this->marge_droite, $tab_top+5); + + $pdf->SetFont('','',8); + + //Piece comptable + $pdf->SetXY ($this->posxpiece-1, $tab_top+1); + $pdf->MultiCell($this->posxpiece-$this->posxpiece-1,1,$outputlangs->transnoentities("Piece"),'','L'); + + //Comments + $pdf->line($this->posxdesc-1, $tab_top, $this->posxdesc-1, $tab_top + $tab_height); + $pdf->SetXY ($this->posxdesc-1, $tab_top+1); + $pdf->MultiCell($this->posxdate-$this->posxdesc-1,1,$outputlangs->transnoentities("Description"),'','L'); + + //Date + $pdf->line($this->posxdate-1, $tab_top, $this->posxdate-1, $tab_top + $tab_height); + $pdf->SetXY ($this->posxdate-1, $tab_top+1); + $pdf->MultiCell($this->posxtype-$this->posxdate-1,2, $outputlangs->transnoentities("Date"),'','C'); + + //Type + $pdf->line($this->posxtype-1, $tab_top, $this->posxtype-1, $tab_top + $tab_height); + $pdf->SetXY ($this->posxtype-1, $tab_top+1); + $pdf->MultiCell($this->posxprojet-$this->posxtype-1,2, $outputlangs->transnoentities("Type"),'','C'); + + // Projet + $pdf->line($this->posxprojet-1, $tab_top, $this->posxprojet-1, $tab_top + $tab_height); + $pdf->SetXY ($this->posxprojet-1, $tab_top+1); + $pdf->MultiCell($this->posxtva-$this->posxprojet-1,2, $outputlangs->transnoentities("Project"),'','C'); + + //TVA + $pdf->line($this->posxtva-1, $tab_top, $this->posxtva-1, $tab_top + $tab_height); + $pdf->SetXY ($this->posxtva-1, $tab_top+1); + $pdf->MultiCell($this->posxup-$this->posxtva-1,2, $outputlangs->transnoentities("VAT"),'','C'); + + //PU + $pdf->line($this->posxup-1, $tab_top, $this->posxup-1, $tab_top + $tab_height); + $pdf->SetXY ($this->posxup-1, $tab_top+1); + $pdf->MultiCell($this->posxqty-$this->posxup-1,2, $outputlangs->transnoentities("PU"),'','C'); + + //QTY + $pdf->line($this->posxqty-1, $tab_top, $this->posxqty-1, $tab_top + $tab_height); + $pdf->SetXY ($this->posxqty-1, $tab_top+1); + $pdf->MultiCell($this->postotalttc-$this->posxqty,2, $outputlangs->transnoentities("Q"),'','R'); + + //TOTALTTC + $pdf->line($this->postotalttc, $tab_top, $this->postotalttc, $tab_top + $tab_height); + $pdf->SetXY ($this->postotalttc-4, $tab_top+1); + $pdf->MultiCell(28,2, $outputlangs->transnoentities("TotalTTC"),'','R'); + + $pdf->SetTextColor(0,0,0); + } + + /** + * Show footer of page. Need this->emetteur object + * + * @param PDF &$pdf PDF + * @param Object $object Object to show + * @param Translate $outputlangs Object lang for output + * @param int $hidefreetext 1=Hide free text + * @return int Return height of bottom margin including footer text + */ + function _pagefoot(&$pdf,$object,$outputlangs,$hidefreetext=0) + { + return pdf_pagefoot($pdf,$outputlangs,'DEPLACEMENT_FREE_TEXT',$this->emetteur,$this->marge_basse,$this->marge_gauche,$this->page_hauteur,$object,0,$hidefreetext); + } + +} + diff --git a/htdocs/core/modules/modDeplacement.class.php b/htdocs/core/modules/modDeplacement.class.php index c536553ac4b..f08a346577a 100644 --- a/htdocs/core/modules/modDeplacement.class.php +++ b/htdocs/core/modules/modDeplacement.class.php @@ -50,7 +50,7 @@ class modDeplacement extends DolibarrModules $this->description = "Gestion des notes de frais et deplacements"; // Si traduction Module75Desc non trouvee // Possible values for version are: 'development', 'experimental', 'dolibarr' or version - $this->version = 'dolibarr'; + $this->version = 'dolibarr_deprecated'; $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); $this->special = 0; diff --git a/htdocs/core/modules/modExpenseReport.class.php b/htdocs/core/modules/modExpenseReport.class.php new file mode 100755 index 00000000000..54d0496a4dd --- /dev/null +++ b/htdocs/core/modules/modExpenseReport.class.php @@ -0,0 +1,347 @@ + + * Copyright (C) 2004-2009 Laurent Destailleur + * Copyright (C) 2005-2010 Regis Houssin + * Copyright (C) 2011 Dimitri Mouillard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/** + * \defgroup Indicateurs + * \brief Module indicateurs + * Such a file must be copied into htdocs/includes/module directory. + */ + +/** + * \file htdocs/indicateurs/core/modules/modExpenseReport.class.php + * \ingroup indicateur + * \brief Description and activation file for module ExpenseReport + */ +include_once(DOL_DOCUMENT_ROOT ."/core/modules/DolibarrModules.class.php"); + + +/** + * Description and activation class for module ExpenseReport + */ +class modExpenseReport extends DolibarrModules +{ + /** + * Constructor. Define names, constants, directories, boxes, permissions + * + * @param Database $db Database handler + */ + function __construct($db) + { + global $conf; + + $this->db = $db; + + // Id for module (must be unique). + // Use here a free id (See in Home -> System information -> Dolibarr for list of used modules id). + $this->numero = 770; + // Key text used to identify module (for permissions, menus, etc...) + $this->rights_class = 'deplacement'; + + // Family can be 'crm','financial','hr','projects','products','ecm','technic','other' + // It is used to group modules in module setup page + $this->family = "hr"; + // Module label (no space allowed), used if translation string 'ModuleXXXName' not found (where XXX is value of numeric property 'numero' of module) + $this->name = preg_replace('/^mod/i','',get_class($this)); + // Module description, used if translation string 'ModuleXXXDesc' not found (where XXX is value of numeric property 'numero' of module) + $this->description = "Manage and claim expense reports (transportation, meal, ...)"; + // Possible values for version are: 'development', 'experimental', 'dolibarr' or version + $this->version = 'dolibarr'; + // Key used in llx_const table to save module status enabled/disabled (where MYMODULE is value of property name of module in uppercase) + $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); + // Where to store the module in setup page (0=common,1=interface,2=others,3=very specific) + $this->special = 0; + // Name of image file used for this module. + // If file is in theme/yourtheme/img directory under name object_pictovalue.png, use this->picto='pictovalue' + // If file is in module/img directory under name object_pictovalue.png, use this->picto='pictovalue@module' + $this->picto='trip'; + + // Defined if the directory /mymodule/inc/triggers/ contains triggers or not + $this->triggers = 0; + + // Data directories to create when module is enabled. + // Example: this->dirs = array("/mymodule/temp"); + $this->dirs = array(); + $r=0; + + // Relative path to module style sheet if exists. Example: '/mymodule/css/mycss.css'. + //$this->style_sheet = '/mymodule/mymodule.css.php'; + + // Config pages. Put here list of php page names stored in admmin directory used to setup module. + $this->config_page_url = array(); + + // Dependencies + $this->depends = array(); // List of modules id that must be enabled if this module is enabled +// $this->conflictwith = array("modDeplacement"); + $this->requiredby = array(); // List of modules id to disable if this one is disabled + $this->phpmin = array(4,3); // Minimum version of PHP required by module + $this->need_dolibarr_version = array(3,0); // Minimum version of Dolibarr required by module + $this->langfiles = array("companies","trips","deplacement@deplacement"); + + // Constants + // Example: $this->const=array(0=>array('MYMODULE_MYNEWCONST1','chaine','myvalue','This is a constant to add',0), + // 1=>array('MYMODULE_MYNEWCONST2','chaine','myvalue','This is another constant to add',0) ); + // 2=>array('MAIN_MODULE_MYMODULE_NEEDSMARTY','chaine',1,'Constant to say module need smarty',0) + $this->const = array(); // List of particular constants to add when module is enabled (key, 'chaine', value, desc, visible, 0 or 'allentities') + + // Array to add new pages in new tabs + $this->tabs = array(); + // where entity can be + // 'thirdparty' to add a tab in third party view + // 'intervention' to add a tab in intervention view + // 'order_supplier' to add a tab in supplier order view + // 'invoice_supplier' to add a tab in supplier invoice view + // 'invoice' to add a tab in customer invoice view + // 'order' to add a tab in customer order view + // 'product' to add a tab in product view + // 'stock' to add a tab in stock view + // 'propal' to add a tab in propal view + // 'member' to add a tab in fundation member view + // 'contract' to add a tab in contract view + // 'user' to add a tab in user view + // 'group' to add a tab in group view + // 'contact' to add a tab in contact view + + + // Boxes + $this->boxes = array(); // List of boxes + $r=0; + + // Add here list of php file(s) stored in includes/boxes that contains class to show a box. + // Example: + //$this->boxes[$r][1] = "myboxa.php"; + //$r++; + //$this->boxes[$r][1] = "myboxb.php"; + //$r++; + + + // Permissions + $this->rights = array(); // Permission array used by this module + $this->rights_class = 'expensereport'; + + $this->rights[1][0] = 771; + $this->rights[1][1] = 'Read expense reports (own and his subordinates)'; + $this->rights[1][2] = 'r'; + $this->rights[1][3] = 1; + $this->rights[1][4] = 'lire'; + + $this->rights[3][0] = 772; + $this->rights[3][1] = 'Create/modify expense reports'; + $this->rights[3][2] = 'w'; + $this->rights[3][3] = 0; + $this->rights[3][4] = 'creer'; + + $this->rights[4][0] = 773; + $this->rights[4][1] = 'Delete expense reports'; + $this->rights[4][2] = 'd'; + $this->rights[4][3] = 0; + $this->rights[4][4] = 'supprimer'; + + $this->rights[2][0] = 774; + $this->rights[2][1] = 'Read all expense reports'; + $this->rights[2][2] = 'r'; + $this->rights[2][3] = 1; + $this->rights[2][4] = 'readall'; + + $this->rights[6][0] = 775; + $this->rights[6][1] = 'Approve expense reports'; + $this->rights[6][2] = 'w'; + $this->rights[6][3] = 0; + $this->rights[6][4] = 'to_validate'; + + $this->rights[7][0] = 776; + $this->rights[7][1] = 'Pay expense reports'; + $this->rights[7][2] = 'w'; + $this->rights[7][3] = 0; + $this->rights[7][4] = 'to_paid'; + + if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) + { + $this->rights[8][0] = 777; + $this->rights[8][1] = 'Synchroniser les NDF avec un compte courant'; + $this->rights[8][2] = 'w'; + $this->rights[8][3] = 0; + $this->rights[8][4] = 'synchro'; + + $this->rights[9][0] = 778; + $this->rights[9][1] = 'Exporter les NDF au format CSV'; + $this->rights[9][2] = 'r'; + $this->rights[9][3] = 0; + $this->rights[9][4] = 'export_csv'; + } + + $this->rights[5][0] = 779; + $this->rights[5][1] = 'Export expense reports'; + $this->rights[5][2] = 'r'; + $this->rights[5][3] = 0; + $this->rights[5][4] = 'export'; + + // Exports + $r=0; + + $r++; + $this->export_code[$r]='trips_'.$r; + $this->export_label[$r]='ListTripsAndExpenses'; + $this->export_permission[$r]=array(array("expensereport","export")); + $this->export_fields_array[$r]=array('d.rowid'=>"TripId",'d.type'=>"Type",'d.km'=>"FeesKilometersOrAmout",'d.note'=>'NotePrivate','d.note_public'=>'NotePublic','s.nom'=>'ThirdParty','u.lastname'=>'Lastname','u.firstname'=>'Firstname','d.dated'=>"Date"); + $this->export_entities_array[$r]=array('d.rowid'=>"Trip",'d.type'=>"Trip",'d.km'=>"Trip",'d.note'=>'Trip','d.note_public'=>'Trip','s.nom'=>'company','u.lastname'=>'user','u.firstname'=>'user','d.dated'=>"Date"); + $this->export_alias_array[$r]=array('d.rowid'=>"idtrip",'d.type'=>"type",'d.km'=>"km",'d.note'=>'note','d.note_public'=>'note_public','s.nom'=>'companyname','u.lastname'=>'name','u.firstname'=>'firstname','d.dated'=>'date'); + + $this->export_sql_start[$r]='SELECT DISTINCT '; + $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'user as u'; + $this->export_sql_end[$r] .=', '.MAIN_DB_PREFIX.'expensereport as d'; + $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe as s ON d.fk_soc = s.rowid'; + $this->export_sql_end[$r] .=' WHERE d.fk_user = u.rowid'; + $this->export_sql_end[$r] .=' AND d.entity = '.$conf->entity; + + + + // Main menu entries + $this->menu = array(); // List of menus to add + $r=0; + + // Example to declare a Left Menu entry: fk_mainmenu=home,fk_leftmenu=modulesadmintools + $this->menu[$r]=array( 'fk_menu'=>'fk_mainmenu=accountancy', // Use r=value where r is index key used for the parent menu entry (higher parent must be a top menu entry) + 'type'=>'left', // This is a Left menu entry + 'titre'=>'TripsAndExpenses', + 'mainmenu'=>'accountancy', + 'leftmenu'=>'expensereport', + 'url'=>'/expensereport/index.php', + 'langs'=>'trips', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>100, + 'enabled'=>'1', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. + 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both + $r++; + + $this->menu[$r]=array( 'fk_menu'=>'fk_mainmenu=accountancy,fk_leftmenu=expensereport', // Use r=value where r is index key used for the parent menu entry (higher parent must be a top menu entry) + 'type'=>'left', // This is a Left menu entry + 'titre'=>'New', + 'mainmenu'=>'accountancy', + 'leftmenu'=>'expensereport_detail', + 'url'=>'/expensereport/card.php?action=create', + 'langs'=>'trips', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>100, + 'enabled'=>'1', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. + 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both + $r++; + + $this->menu[$r]=array( 'fk_menu'=>'fk_mainmenu=accountancy,fk_leftmenu=expensereport', // Use r=value where r is index key used for the parent menu entry (higher parent must be a top menu entry) + 'type'=>'left', // This is a Left menu entry + 'titre'=>'List', + 'mainmenu'=>'accountancy', + 'leftmenu'=>'expensereport_detail', + 'url'=>'/expensereport/list.php', + 'langs'=>'trips', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>100, + 'enabled'=>'1', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. + 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both + $r++; + + $this->menu[$r]=array( 'fk_menu'=>'fk_mainmenu=accountancy,fk_leftmenu=expensereport', // Use r=value where r is index key used for the parent menu entry (higher parent must be a top menu entry) + 'type'=>'left', // This is a Left menu entry + 'titre'=>'Statistics', + 'mainmenu'=>'accountancy', + 'leftmenu'=>'expensereport_detail', + 'url'=>'/expensereport/stats/index.php', + 'langs'=>'trips', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>100, + 'enabled'=>'1', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. + 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both + $r++; + + + $this->menu[$r]=array( 'fk_menu'=>'fk_mainmenu=accountancy,fk_leftmenu=expensereport', // Use r=value where r is index key used for the parent menu entry (higher parent must be a top menu entry) + 'type'=>'left', // This is a Left menu entry + 'titre'=>'ExportTripCSV', + 'mainmenu'=>'accountancy', + 'leftmenu'=>'expensereport_detail', + 'url'=>'/expensereport/export_csv.php', + 'langs'=>'expensereport', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>100, + 'enabled'=>'$conf->global->DEPLACEMENT_TO_CLEAN', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. + 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both + $r++; + + $this->menu[$r]=array( 'fk_menu'=>'fk_mainmenu=accountancy,fk_leftmenu=expensereport', // Use r=value where r is index key used for the parent menu entry (higher parent must be a top menu entry) + 'type'=>'left', // This is a Left menu entry + 'titre'=>'Synchro_Compta', + 'mainmenu'=>'accountancy', + 'leftmenu'=>'expensereport_detail', + 'url'=>'/expensereport/synchro_compta.php', + 'langs'=>'expensereport', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>100, + 'enabled'=>'$conf->global->DEPLACEMENT_TO_CLEAN', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. + 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both + $r++; + } + + /** + * Function called when module is enabled. + * The init function add constants, boxes, permissions and menus (defined in constructor) into Dolibarr database. + * It also creates data directories. + * + * @param string $options Options + * @return int 1 if OK, 0 if KO + */ + function init($options='') + { + global $conf; + + $this->remove($options); + + $result=$this->_load_tables('/deplacement/sql/'); + + $sql = array( + "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = 'teclib' AND entity = ".$conf->entity, + "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('teclib','deplacement',".$conf->entity.")" + ); + + return $this->_init($sql,$options); + } + + /** + * Function called when module is disabled. + * Remove from database constants, boxes and permissions from Dolibarr database. + * Data directories are not deleted. + * + * @param string Options + * @return int 1 if OK, 0 if KO + */ + function remove($options='') + { + $sql = array(); + + return $this->_remove($sql,$options); + } + +} + diff --git a/htdocs/expensereport/ajax/ajaxprojet.php b/htdocs/expensereport/ajax/ajaxprojet.php new file mode 100755 index 00000000000..0ab75543309 --- /dev/null +++ b/htdocs/expensereport/ajax/ajaxprojet.php @@ -0,0 +1,88 @@ + + * Copyright (C) 2005-2009 Regis Houssin + * Copyright (C) 2007-2010 Laurent Destailleur + * Copyright (C) 2010 Cyrille de Lambert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/** + * \file htdocs/expensereport/ajax/ajaxprojet.php + * \brief File to return Ajax response on third parties request + */ + +if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL',1); // Disables token renewal +if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1'); +if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1'); +if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1'); +if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1'); +if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK','1'); + +$res=0; +require '../../main.inc.php'; + + +/* + * View + */ + +// Ajout directives pour resoudre bug IE +//header('Cache-Control: Public, must-revalidate'); +//header('Pragma: public'); + +//top_htmlhead("", "", 1); // Replaced with top_httphead. An ajax page does not need html header. +top_httphead(); + +//print ''."\n"; + +dol_syslog(join(',',$_GET)); + + +// Generation liste des projets +if (GETPOST('fk_projet') != '') +{ + $return_arr = array(); + + $sql = "SELECT p.rowid, p.ref, p.title, s.nom"; + $sql.= " FROM ".MAIN_DB_PREFIX."projet as p"; + $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON p.fk_soc = s.rowid"; + if (! empty($_GET["fk_projet"])) $sql.= " WHERE p.ref LIKE '%".$db->escape($_GET["fk_projet"])."%' OR p.title LIKE '%".$db->escape($_GET["fk_projet"])."%' OR s.nom LIKE '%".$db->escape($_GET["fk_projet"])."%'"; // Add other filters + $sql.= " ORDER BY p.ref ASC"; + + $resql=$db->query($sql); + if ($resql) + { + while ($row = $db->fetch_array($resql)) + { + $label=$row['ref'].' - '.$row['title']; + $row_array['label'] = $label; + $row_array['value'] = $label; + $row_array['key'] = $row['rowid']; + + array_push($return_arr,$row_array); + } + + echo json_encode($return_arr); + } + else + { + echo json_encode(array('nom'=>'Error','label'=>'Error','key'=>'Error','value'=>'Error')); + } +} +else +{ + echo json_encode(array('nom'=>'ErrorBadParameter','label'=>'ErrorBadParameter','key'=>'ErrorBadParameter','value'=>'ErrorBadParameter')); +} diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php new file mode 100755 index 00000000000..7d52ac5b538 --- /dev/null +++ b/htdocs/expensereport/card.php @@ -0,0 +1,1776 @@ + + * Copyright (C) 2004-2008 Laurent Destailleur + * Copyright (C) 2005-2009 Regis Houssin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/** + * \file htdocs/expensereport/card.php + * \brief Page for trip and expense card + */ + +$res=0; +require '../main.inc.php'; +require_once(DOL_DOCUMENT_ROOT."/core/class/html.formfile.class.php"); +require_once(DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'); +require_once(DOL_DOCUMENT_ROOT."/core/class/html.formmail.class.php"); +require_once(DOL_DOCUMENT_ROOT."/core/class/html.formprojet.class.php"); +require_once(DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'); +require_once(DOL_DOCUMENT_ROOT."/core/lib/trip.lib.php"); +dol_include_once('/expensereport/core/modules/expensereport/modules_expensereport.php'); +dol_include_once("/expensereport/class/expensereport.class.php"); + +$langs->load("trips"); + +$action=GETPOST('action'); +$date_start = dol_mktime(0, 0, 0, GETPOST('date_debutmonth'), GETPOST('date_debutday'), GETPOST('date_debutyear')); +$date_end = dol_mktime(0, 0, 0, GETPOST('date_finmonth'), GETPOST('date_finday'), GETPOST('date_finyear')); + + +// If socid provided by ajax company selector +if (! empty($_REQUEST['socid_id'])) +{ + $_GET['socid'] = $_GET['socid_id']; + $_POST['socid'] = $_POST['socid_id']; + $_REQUEST['socid'] = $_REQUEST['socid_id']; +} + +// Security check +$id=GETPOST("id",'int'); +if ($user->societe_id) $socid=$user->societe_id; +$result = restrictedArea($user, 'expensereport', 0, 'expensereport'); + +$mesg=""; + + +// Hack to use expensereport dir +$rootfordata = DOL_DATA_ROOT; +$rootforuser = DOL_DATA_ROOT; +// If multicompany module is enabled, we redefine the root of data +if (! empty($conf->multicompany->enabled) && ! empty($conf->entity) && $conf->entity > 1) +{ + $rootfordata.='/'.$conf->entity; +} +$conf->expensereport->dir_output = $rootfordata.'/expensereport'; +$conf->expensereport->dir_output = $rootfordata.'/expensereport'; + + + +/* + * Actions + */ + +if ($action == 'confirm_delete' && $_GET["confirm"] == "yes" && $id > 0 && $user->rights->expensereport->supprimer) +{ + $object = new ExpenseReport($db); + $result=$object->delete($id); + if ($result >= 0) + { + header("Location: index.php"); + exit; + } + else + { + setEventMessages($object->error, $object->errors, 'errors'); + } +} + +if ($action == 'add' && $user->rights->expensereport->creer) +{ + $object = new ExpenseReport($db); + + $object->date_debut = $date_start; + $object->date_fin = $date_end; + + $object->fk_user_validator = GETPOST('fk_user_validator','int'); + $object->fk_c_expensereport_statuts = 1; + $object->fk_c_paiement = GETPOST('fk_c_paiement','int'); + $object->note = GETPOST('note'); + + if ($object->periode_existe($user,dol_print_date($object->date_debut, 'dayrfc'),dol_print_date($object->date_fin, 'dayrfc'))) + { + setEventMessage($langs->trans("ErrorDoubleDeclaration"),'errors'); + $action='create'; + } + else + { + $db->begin(); + + $id = $object->create($user); + + if ($id > 0) + { + $db->commit(); + Header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id); + exit; + } + else + { + setEventMessages($object->error, $object->errors, 'errors'); + $db->rollback(); + $action='create'; + } + } +} + +if ($action == 'update' && $user->rights->expensereport->creer) +{ + $object = new ExpenseReport($db); + $object->fetch($_POST['id'],$user); + + $object->date_debut = $date_start; + $object->date_fin = $date_end; + + if($object->fk_c_expensereport_statuts < 3) + { + $object->fk_user_validator = GETPOST('fk_user_validator','int'); + } + + $object->fk_c_paiement = GETPOST('fk_c_paiement','int'); + $object->note = GETPOST('note'); + + $result = $object->update($user); + if ($result > 0) + { + header("Location: ".$_SEVER["PHP_SELF"]."?id=".$_POST['id']); + exit; + } + else + { + setEventMessages($object->error, $object->errors, 'errors'); + } +} + +if ($action == "confirm_save" && GETPOST("confirm") == "yes" && $id > 0 && $user->rights->expensereport->creer) +{ + $object = new ExpenseReport($db); + $object->fetch($id,$user); + $result = $object->set_save($user); + if ($result > 0) + { + // Send mail + if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) + { + // Send mail + + // TO + $destinataire = new User($db); + $destinataire->fetch($object->fk_user_validator); + $emailTo = $destinataire->email; + + // FROM + $expediteur = new User($db); + $expediteur->fetch($object->fk_user_author); + $emailFrom = $expediteur->email; + + // SUBJECT + $subject = "' ERP - Note de frais à valider"; + + // CONTENT + $message = "Bonjour {$destinataire->firstname},\n\n"; + $message.= "Veuillez trouver en pièce jointe une nouvelle note de frais à valider.\n"; + $message.= "- Déclarant : {$expediteur->firstname} {$expediteur->lastname}\n"; + $message.= "- Période : du {$object->date_debut} au {$object->date_fin}\n"; + $message.= "- Lien : {$dolibarr_main_url_root}/expensereport/card.php?id={$object->id}\n\n"; + $message.= "Bien cordialement,\n' SI"; + + // Génération du pdf avant attachement + $object->setDocModel($user,""); + $resultPDF = expensereport_pdf_create($db,$id,'',"",$langs); + + if($resultPDF): + // ATTACHMENT + $filename=array(); $filedir=array(); $mimetype=array(); + array_push($filename,dol_sanitizeFileName($object->ref_number).".pdf"); + array_push($filedir,$conf->expensereport->dir_output . "/" . dol_sanitizeFileName($object->ref_number) . "/" . dol_sanitizeFileName($object->ref_number).".pdf"); + array_push($mimetype,"application/pdf"); + + // PREPARE SEND + $mailfile = new CMailFile($subject,$emailTo,$emailFrom,$message,$filedir,$mimetype,$filename); + + if(!$mailfile->error): + + // SEND + $result=$mailfile->sendfile(); + if ($result): + Header("Location: ".$_SEVER["PHP_SELF"]."?id=".$id); + exit; + endif; + + else: + + $mesg="Impossible d'envoyer l'email."; + + endif; + // END - Send mail + else: + dol_print_error($db,$resultPDF); + exit; + endif; + } + } + else + { + setEventMessages($object->error, $object->errors, 'errors'); + } +} + +if ($action == "confirm_save_from_refuse" && $_GET["confirm"] == "yes" && $id > 0 && $user->rights->expensereport->creer) +{ + $object = new ExpenseReport($db); + $object->fetch($id,$user); + $result = $object->set_save_from_refuse($user); + if ($result > 0) + { + // Send mail + if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) + { + // TO + $destinataire = new User($db); + $destinataire->fetch($object->fk_user_validator); + $emailTo = $destinataire->email; + + // FROM + $expediteur = new User($db); + $expediteur->fetch($object->fk_user_author); + $emailFrom = $expediteur->email; + + // SUBJECT + $subject = "' ERP - Note de frais à re-approuver"; + + // CONTENT + $dateRefusEx = explode(" ",$object->date_refuse); + + $message = "Bonjour {$destinataire->firstname},\n\n"; + $message.= "Le {$dateRefusEx[0]} à {$dateRefusEx[1]} vous avez refusé d'approuver la note de frais \"{$object->ref_number}\". Vous aviez émis le motif suivant : {$object->detail_refuse}\n\n"; + $message.= "L'auteur vient de modifier la note de frais, veuillez trouver la nouvelle version en pièce jointe.\n"; + $message.= "- Déclarant : {$expediteur->firstname} {$expediteur->lastname}\n"; + $message.= "- Période : du {$object->date_debut} au {$object->date_fin}\n"; + $message.= "- Lien : {$dolibarr_main_url_root}/expensereport/card.php?id={$object->id}\n\n"; + $message.= "Bien cordialement,\n' SI"; + + // Génération du pdf avant attachement + $object->setDocModel($user,""); + $resultPDF = expensereport_pdf_create($db,$id,'',"",$langs); + + if($resultPDF): + // ATTACHMENT + $filename=array(); $filedir=array(); $mimetype=array(); + array_push($filename,dol_sanitizeFileName($object->ref_number).".pdf"); + array_push($filedir,$conf->expensereport->dir_output . "/" . dol_sanitizeFileName($object->ref_number) . "/" . dol_sanitizeFileName($object->ref_number).".pdf"); + array_push($mimetype,"application/pdf"); + + // PREPARE SEND + $mailfile = new CMailFile($subject,$emailTo,$emailFrom,$message,$filedir,$mimetype,$filename); + + if(!$mailfile->error): + + // SEND + $result=$mailfile->sendfile(); + if ($result): + Header("Location: ".$_SEVER["PHP_SELF"]."?id=".$id); + exit; + endif; + + else: + + $mesg="Impossible d'envoyer l'email."; + + endif; + // END - Send mail + else: + dol_print_error($db,$resultPDF); + exit; + endif; + } + } + else + { + setEventMessages($object->error, $object->errors, 'errors'); + } +} + +// Approve +if ($action == "confirm_validate" && GETPOST("confirm") == "yes" && $id > 0 && $user->rights->expensereport->to_validate) +{ + $object = new ExpenseReport($db); + $object->fetch($id,$user); + + $result = $object->set_valide($user); + if ($result > 0) + { + if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) + { + $object = new ExpenseReport($db); + $object->fetch($id,$user); + + // Send mail + + // TO + $destinataire = new User($db); + $destinataire->fetch($object->fk_user_author); + $emailTo = $destinataire->email; + + // CC + $emailCC = $conf->global->NDF_CC_EMAILS; + + // FROM + $expediteur = new User($db); + $expediteur->fetch($object->fk_user_valid); + $emailFrom = $expediteur->email; + + // SUBJECT + $subject = "' ERP - Note de frais validée"; + + // CONTENT + $message = "Bonjour {$destinataire->firstname},\n\n"; + $message.= "Votre note de frais \"{$object->ref_number}\" vient d'être approuvé!\n"; + $message.= "- Approbateur : {$expediteur->firstname} {$expediteur->lastname}\n"; + $message.= "- Lien : {$dolibarr_main_url_root}/expensereport/card.php?id={$object->id}\n\n"; + $message.= "Bien cordialement,\n' SI"; + + // Génération du pdf avant attachement + $object->setDocModel($user,""); + $resultPDF = expensereport_pdf_create($db,$id,'',"",$langs); + + if($resultPDF): + // ATTACHMENT + $filename=array(); $filedir=array(); $mimetype=array(); + array_push($filename,dol_sanitizeFileName($object->ref_number).".pdf"); + array_push($filedir, $conf->expensereport->dir_output. + "/". + dol_sanitizeFileName($object->ref_number) . + "/". + dol_sanitizeFileName($object->ref_number). + ".pdf" + ); + array_push($mimetype,"application/pdf"); + + // PREPARE SEND + $mailfile = new CMailFile($subject,$emailTo,$emailFrom,$message,$filedir,$mimetype,$filename,$emailCC); + + if(!$mailfile->error): + + // SEND + $result=$mailfile->sendfile(); + if ($result): + setEventMessage($langs->trans("MailSuccessfulySent",$emailFrom,$emailTo)); + Header("Location: ".$_SEVER["PHP_SELF"]."?id=".$id); + exit; + else: + setEventMessage($langs->trans("ErrorFailedToSendMail",$emailFrom,$emailTo),'errors'); + endif; + + else: + setEventMessage($langs->trans("ErrorFailedToSendMail",$emailFrom,$emailTo),'errors'); + endif; + // END - Send mail + else : // if ($resultPDF) + dol_print_error($db,$resultPDF); + exit; + endif; + } + } + else + { + setEventMessages($object->error, $object->errors, 'errors'); + } +} + +if ($action == "confirm_refuse" && $_POST['confirm']=="yes" && !empty($_POST['detail_refuse']) && $id > 0 && $user->rights->expensereport->to_validate) +{ + $object = new ExpenseReport($db); + $object->fetch($id,$user); + + $result = $object->set_refuse($user,$_POST['detail_refuse']); + if ($result > 0) + { + if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) + { + $object = new ExpenseReport($db); + $object->fetch($id,$user); + + // Send mail + + // TO + $destinataire = new User($db); + $destinataire->fetch($object->fk_user_author); + $emailTo = $destinataire->email; + + // FROM + $expediteur = new User($db); + $expediteur->fetch($object->fk_user_refuse); + $emailFrom = $expediteur->email; + + // SUBJECT + $subject = "' ERP - Note de frais refusée"; + + // CONTENT + $message = "Bonjour {$destinataire->firstname},\n\n"; + $message.= "Votre note de frais \"{$object->ref_number}\" vient d'être refusée.\n"; + $message.= "- Refuseur : {$expediteur->firstname} {$expediteur->lastname}\n"; + $message.= "- Motif de refus : {$_POST['detail_refuse']}\n"; + $message.= "- Lien : {$dolibarr_main_url_root}/expensereport/card.php?id={$object->id}\n\n"; + $message.= "Bien cordialement,\n' SI"; + + // PREPARE SEND + $mailfile = new CMailFile($subject,$emailTo,$emailFrom,$message); + + if(!$mailfile->error) + { + // SEND + $result=$mailfile->sendfile(); + if ($result) + { + setEventMessage($langs->trans("MailSuccessfulySent",$emailFrom,$emailTo)); + Header("Location: ".$_SEVER["PHP_SELF"]."?id=".$id); + exit; + } + else + { + setEventMessage($langs->trans("ErrorFailedToSendMail",$emailFrom,$emailTo),'errors'); + $mesg="Impossible d'envoyer l'email."; + } + // END - Send mail + } + } + } + else + { + setEventMessage($object->error, $object->errors); + } +} + +if ($action == "confirm_cancel" && GETPOST('confirm')=="yes" && !empty($_POST['detail_cancel']) && $id > 0 && $user->rights->expensereport->to_validate) +{ + $object = new ExpenseReport($db); + $object->fetch($id,$user); + if($user->id == $object->fk_user_validator) + { + $result = $object->set_cancel($user,$_POST['detail_cancel']); + + if ($result > 0) + { + if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) + { + $object = new ExpenseReport($db); + $object->fetch($id,$user); + + // Send mail + + // TO + $destinataire = new User($db); + $destinataire->fetch($object->fk_user_author); + $emailTo = $destinataire->email; + + // FROM + $expediteur = new User($db); + $expediteur->fetch($object->fk_user_cancel); + $emailFrom = $expediteur->email; + + // SUBJECT + $subject = "' ERP - Note de frais annulée"; + + // CONTENT + $message = "Bonjour {$destinataire->firstname},\n\n"; + $message.= "Votre note de frais \"{$object->ref_number}\" vient d'être annulée.\n"; + $message.= "- Annuleur : {$expediteur->firstname} {$expediteur->lastname}\n"; + $message.= "- Motif d'annulation : {$_POST['detail_cancel']}\n"; + $message.= "- Lien : {$dolibarr_main_url_root}/expensereport/card.php?id={$object->id}\n\n"; + $message.= "Bien cordialement,\n' SI"; + + // PREPARE SEND + $mailfile = new CMailFile($subject,$emailTo,$emailFrom,$message); + + if(!$mailfile->error) + { + // SEND + $result=$mailfile->sendfile(); + if ($result) + { + header("Location: ".$_SEVER["PHP_SELF"]."?id=".$id); + exit; + } + else + { + $mesg="Impossible d'envoyer l'email."; + } + // END - Send mail + } + else + { + setEventMessages($mail->error, $mail->errors, 'errors'); + } + } + } + else + { + setEventMessages($object->error, $object->errors, 'errors'); + } + } + else + { + setEventMessages($langs->transnoentitiesnoconv("NOT_VALIDATOR"), '', 'errors'); + } +} + +if ($action == "confirm_paid" && $_GET['confirm']=="yes" && $id > 0 && $user->rights->expensereport->to_paid) +{ + $object = new ExpenseReport($db); + $object->fetch($id,$user); + $result = $object->set_paid($user); + if ($result > 0) + { + if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) + { + $object = new ExpenseReport($db); + $object->fetch($id,$user); + + // Send mail + + // TO + $destinataire = new User($db); + $destinataire->fetch($object->fk_user_author); + $emailTo = $destinataire->email; + + // FROM + $expediteur = new User($db); + $expediteur->fetch($object->fk_user_paid); + $emailFrom = $expediteur->email; + + // SUBJECT + $subject = "' ERP - Note de frais payée"; + + // CONTENT + $message = "Bonjour {$destinataire->firstname},\n\n"; + $message.= "Votre note de frais \"{$object->ref_number}\" vient d'être payée.\n"; + $message.= "- Payeur : {$expediteur->firstname} {$expediteur->lastname}\n"; + $message.= "- Lien : {$dolibarr_main_url_root}/expensereport/card.php?id={$object->id}\n\n"; + $message.= "Bien cordialement,\n' SI"; + + // Génération du pdf avant attachement + $object->setDocModel($user,""); + $resultPDF = expensereport_pdf_create($db,$id,'',"",$langs); + + // PREPARE SEND + $mailfile = new CMailFile($subject,$emailTo,$emailFrom,$message); + + if(!$mailfile->error): + + // SEND + $result=$mailfile->sendfile(); + if ($result): + // Insert écriture dans le compte courant + $idTrip = $id; + $idAccount = 1; + + $object = new ExpenseReport($db); + $object->fetch($idTrip,$user); + + $datePaiement = explode("-",$object->date_paiement); + + $dateop = dol_mktime(12,0,0,$datePaiement[1],$datePaiement[2],$datePaiement[0]); + $operation = $object->code_paiement; + $label = "Règlement ".$object->ref_number; + $amount = - price2num($object->total_ttc); + $num_chq = ''; + $cat1 = ''; + + $user = new User($db); + $user->fetch($object->fk_user_paid); + + $acct=new Account($db,$idAccount); + $insertid = $acct->addline($dateop, $operation, $label, $amount, $num_chq, $cat1, $user); + + if ($insertid > 0): + $sql = " UPDATE ".MAIN_DB_PREFIX."expensereport d"; + $sql.= " SET integration_compta = 1, fk_bank_account = $idAccount"; + $sql.= " WHERE rowid = $idTrip"; + $resql=$db->query($sql); + if($result): + Header("Location: ".$_SEVER["PHP_SELF"]."?id=".$id); + exit; + else: + dol_print_error($db); + endif; + else: + dol_print_error($db,$acct->error); + endif; + endif; + + else: + + $mesg="Impossible d'envoyer l'email."; + + endif; + // END - Send mail + } + } + else + { + setEventMessages($object->error, $object->errors, 'errors'); + } +} + +if ($action == "confirm_brouillonner" && $_GET['confirm']=="yes" && $id > 0 && $user->rights->expensereport->creer) +{ + $object = new ExpenseReport($db); + $object->fetch($id,$user); + if($user->id == $object->fk_user_author OR $user->id == $object->fk_user_validator) + { + $result = $object->set_draft($user); + if ($result > 0) + { + header("Location: ".$_SEVER["PHP_SELF"]."?id=".$id); + exit; + } + else + { + setEventMessages($object->error, $object->errors, 'errors'); + } + } + else + { + setEventMessages($langs->transnoentitiesnoconv("NOT_AUTHOR"), '', 'errors'); + } +} + +if ($action == "addline") +{ + $db->begin(); + + $object_ligne = new ExpenseReportLigne($db); + + $object_ligne->comments = empty($_POST['comments'])?"Aucun commentaire.":$_POST['comments']; + $object_ligne->qty = empty($_POST['qty'])?1:$_POST['qty']; + + // Convertion de "," en "." dans le nombre entré dans le champ + if(preg_match("#,#",$_POST['value_unit'])) + { + $object_ligne->value_unit = preg_replace("#,#",".",$_POST['value_unit']); + } + else + { + $object_ligne->value_unit = $_POST['value_unit']; + } + + $object_ligne->value_unit = number_format($object_ligne->value_unit,3,'.',''); + + $date = explode("/",$_POST['date']); + $object_ligne->date = $date[2]."-".$date[1]."-".$date[0]; + + $object_ligne->fk_c_type_fees = empty($_POST['fk_c_type_fees'])?1:$_POST['fk_c_type_fees']; + + // Get tax id from rate + $tva_tx=GETPOST('fk_c_tva'); + $sql = "SELECT t.rowid, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type"; + $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as p"; + $sql .= " WHERE t.fk_pays = p.rowid AND p.code = '".$mysoc->country_code."'"; + $sql .= " AND t.taux = ".$db->escape($tva_tx)." AND t.active = 1"; + + dol_syslog("get_localtax sql=".$sql); + $resql=$db->query($sql); + if ($resql) + { + $obj = $db->fetch_object($resql); + $tva=$obj->rowid; + } + else dol_print_error($db); + + // Force la TVA à 0% lorsque c'est du transport + if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) + { + if ($object_ligne->fk_c_type_fees==10) + { + $tva = 15; // TODO A virer le hardcoding + } + } + + $object_ligne->fk_c_tva = $tva; + + $object_ligne->fk_projet = $_POST['fk_projet']; + + // Tests des données rentrées + $error = false; + + // Si aucun projet n'est défini + if (empty($object_ligne->fk_projet) || $object_ligne->fk_projet==-1) + { + $error = true; + $text_error[] = "NO_PROJECT"; + } + + // Si aucune date n'est rentrée + if($object_ligne->date=="--"): + $error = true; + $text_error[] = "NO_DATE"; + endif; + + // Si aucun prix n'est rentré + if($object_ligne->value_unit==0): + $error = true; + $text_error[] = "NO_PRICE"; + endif; + + // S'il y'a eu au moins une erreur + if($error) + { + $mesg = implode(",",$text_error); + Header("Location: ".$_SERVER["PHP_SELF"]."?id=".$_POST['fk_expensereport']."&mesg=$mesg"); + exit; + } + else + { + $object_ligne->fk_expensereport = $_POST['fk_expensereport']; + + $object_ligne->fetch_taux($object_ligne->fk_c_tva); + + // Calculs des totos + $object_ligne->total_ttc = $object_ligne->value_unit * $object_ligne->qty; + $object_ligne->total_ttc = number_format($object_ligne->total_ttc,2,'.',''); + + $tx_tva = $object_ligne->tva_taux/100; + $tx_tva = $tx_tva + 1; + + $object_ligne->total_ht = $object_ligne->total_ttc / $tx_tva; + $object_ligne->total_ht = number_format($object_ligne->total_ht,2,'.',''); + + $object_ligne->total_tva = $object_ligne->total_ttc - $object_ligne->total_ht; + // Fin calculs des totos + + $result = $object_ligne->insert(); + if ($result > 0) + { + $object = new ExpenseReport($db); + $object->fetch($_POST['fk_expensereport'],$user); + $object->update_totaux_add($object_ligne->total_ht,$object_ligne->total_tva); + + $db->commit(); + Header("Location: ".$_SERVER["PHP_SELF"]."?id=".$_POST['fk_expensereport']); + exit; + } + else + { + dol_print_error($db,$object->error); + $db->rollback(); + exit; + } + } +} + +if ($action == 'confirm_delete_line' && $_POST["confirm"] == "yes") +{ + $object = new ExpenseReport($db); + $object->fetch($_GET["id"],$user); + + $object_ligne = new ExpenseReportLigne($db); + $object_ligne->fetch($_GET["rowid"]); + $total_ht = $object_ligne->total_ht; + $total_tva = $object_ligne->total_tva; + + $result=$object->deleteline($_GET["rowid"]); + if ($result >= 0) + { + $object->update_totaux_del($object_ligne->total_ht,$object_ligne->total_tva); + header("Location: ".$_SERVER["PHP_SELF"]."?id=".$_GET['id']); + exit; + } + else + { + setEventMessages($object->error, $object->errors, 'errors'); + } +} + +if ($action == "updateligne" ) +{ + $object = new ExpenseReport($db); + + $object_id = GETPOST('id','int'); + $object->fetch($object_id,$user); + + $rowid = $_POST['rowid']; + $type_fees_id = empty($_POST['fk_c_type_fees'])?1:$_POST['fk_c_type_fees']; + + // Get tax id from rate + $tva_tx=GETPOST('fk_c_tva'); + $sql = "SELECT t.rowid, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type"; + $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as p"; + $sql .= " WHERE t.fk_pays = p.rowid AND p.code = '".$mysoc->country_code."'"; + $sql .= " AND t.taux = ".$db->escape($tva_tx)." AND t.active = 1"; + + dol_syslog("get_localtax sql=".$sql); + $resql=$db->query($sql); + if ($resql) + { + $obj = $db->fetch_object($resql); + $c_tva=$obj->rowid; + } + else dol_print_error($db); + + // Force la TVA à 0% lorsque c'est du transport + if ($type_fees_id==10) + { + $c_tva = 15; + } + + $object_ligne->fk_c_tva = $c_tva; + $projet_id = $_POST['fk_projet']; + $comments = $_POST['comments']; + $qty = $_POST['qty']; + + // Convertion de "," en "." dans le nombre entré dans le champ + if(preg_match("#,#",$_POST['value_unit'])): + $value_unit = preg_replace("#,#",".",$_POST['value_unit']); + else: + $value_unit = $_POST['value_unit']; + endif; + + $date = explode("/",$_POST['date']); + $date = $date[2]."-".$date[1]."-".$date[0]; + + $result = $object->updateline($rowid, $type_fees_id, $projet_id, $c_tva, $comments, $qty, $value_unit, $date, $object_id); + if ($result >= 0) + { + $object->recalculer($object_id); + header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object_id); + exit; + } + else + { + setEventMessages($object->error, $object->errors, 'errors'); + } +} + +if ($action == "recalc" && $id > 0) +{ + $object = new ExpenseReport($db); + $object->fetch($id); + if($object->recalculer($id) > 0) + { + header("Location: ".$_SERVER["PHP_SELF"]."?id=".$_GET['id']); + exit; + } + else + { + setEventMessages($object->error, $object->errors, 'errors'); + } +} + +/* + * Generer ou regenerer le document PDF + */ +if ($action == 'builddoc') // En get ou en post +{ + $depl = new ExpenseReport($db, 0, $_GET['id']); + $depl->fetch($_GET['id'],$user); + + if ($_REQUEST['model']) + { + $depl->setDocModel($user, $_REQUEST['model']); + } + + $outputlangs = $langs; + if (! empty($_REQUEST['lang_id'])) + { + $outputlangs = new Translate("",$conf); + $outputlangs->setDefaultLang($_REQUEST['lang_id']); + } + $result=expensereport_pdf_create($db, $depl->id, '', $depl->modelpdf, $outputlangs); + if ($result <= 0) + { + dol_print_error($db,$result); + exit; + } + else + { + Header('Location: '.$_SERVER["PHP_SELF"].'?id='.$depl->id.(empty($conf->global->MAIN_JUMP_TAG)?'':'#builddoc')); + exit; + } +} + +// Remove file in doc form +else if ($action == 'remove_file') +{ + $object = new ExpenseReport($db, 0, $_GET['id']); + if ($object->fetch($id)) + { + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + + $object->fetch_thirdparty(); + + $langs->load("other"); + $upload_dir = $conf->expensereport->dir_output; + $file = $upload_dir . '/' . GETPOST('file'); + $ret=dol_delete_file($file,0,0,0,$object); + if ($ret) setEventMessage($langs->trans("FileWasRemoved", GETPOST('urlfile'))); + else setEventMessage($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), 'errors'); + $action=''; + } +} + + +/* + * View + */ + +llxHeader(); + +$html = new Form($db); +$formfile = new FormFile($db); +$form = new Form($db); +$formproject = new FormProjets($db); + +if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) +{ + if(!empty($_GET['mesg'])) + { + $text_mesg = explode(",",$_GET['mesg']); + + foreach($text_mesg as $text) + { + $mesg.= "- ".$langs->trans($text)."
"; + } + + print "
"; + print $langs->trans("LINE_NOT_ADDED")."
"; + print $mesg; + print "
"; + } + else + { + if ($mesg) print "
".$mesg."
"; + } +} + + +/* + * Create + */ + +if ($action == 'create') +{ + print print_fiche_titre($langs->trans("NewTrip")); + + print '
'; + print ''; + print ''; + + dol_fiche_head(''); + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + if (! empty($conf->global->EXPENSEREPORT_ASK_PAYMENTMODE_ON_CREATION)) + { + print ''; + print ''; + print ''; + print ''; + } + print ''; + print ''; + print ''; + print ''; + print ''; + print '
'.$langs->trans("DateStart").''; + $html->select_date($date_start?$date_start:-1,'date_debut',0,0,0,'',1,1); + print '
'.$langs->trans("DateEnd").''; + $html->select_date($date_end?$date_end:-1,'date_fin',0,0,0,'',1,1); + print '
'.$langs->trans("VALIDATOR").''; + $object = new ExpenseReport($db); + $include_users = $object->fetch_users_approver_expensereport(); + $s=$html->select_dolusers((GETPOST('fk_user_validator')?GETPOST('fk_user_validator'):$conf->global->EXPENSEREPORT_DEFAULT_VALIDATOR), "fk_user_validator", 1, "", 0, $include_users); + print $html->textwithpicto($s, $langs->trans("AnyOtherInThisListCanValidate")); + print '
'.$langs->trans("ModePaiement").''; + $html->select_types_paiements(2,'fk_c_paiement'); + print '
'.$langs->trans("Note").''; + print ''; + print '
'; + + dol_fiche_end(); + + print '
'; + print ''; + print '     '; + print '
'; + + print '
'; +} +else +{ + if($id > 0) + { + $object = new ExpenseReport($db); + $result = $object->fetch($id,$user); + + if($result) + { + if ($object->fk_user_author != $user->id) + { + if (empty($user->rights->expensereport->readall) && empty($user->rights->expensereport->lire_tous)) + { + print_fiche_titre($langs->trans('TripCard')); + + print '
'; + print $langs->trans('NotUserRightToView'); + print '
'; + + $db->close(); + + llxFooter(); + + exit; + } + } + + //$head = trip_prepare_head($object); + + $head[0][0] = $_SERVER['PHP_SELF'].'?id='.$object->id; + $head[0][1] = $langs->trans('Card'); + $head[0][2] = 'card'; + $h++; + + dol_fiche_head($head, 'card', $langs->trans("TripCard"), 0, 'trip'); + + if ($action == 'edit' && ($object->fk_c_expensereport_statuts < 3 || $object->fk_c_expensereport_statuts==99)) + { + print "
\n"; + print ''; + + if($object->fk_c_expensereport_statuts==99) + { + print ''; + } + else + { + print ''; + } + + print ''; + + + print ''; + + $linkback = ''.$langs->trans("BackToList").''; + + // Ref + print ''; + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + if (! empty($conf->global->EXPENSEREPORT_ASK_PAYMENTMODE_ON_CREATION)) + { + print ''; + print ''; + print ''; + print ''; + } + + if($object->fk_c_expensereport_statuts<3) + { + print ''; + print ''; + print ''; + print ''; + } + else + { + print ''; + print ''; + print ''; + } + + print ''; + print ''; + print ''; + if ($object->fk_c_expensereport_statuts==6) + { + print ''; + print ''; + print ''; + + } + print ''; + print ''; + print ''; + print ''; + print '
'.$langs->trans("Ref").''; + print $form->showrefnav($object, 'id', $linkback, 1, 'rowid', 'ref', ''); + print '
'.$langs->trans("DateStart").''; + $html->select_date($object->date_debut,'date_debut'); + print '
'.$langs->trans("DateEnd").''; + $html->select_date($object->date_fin,'date_fin'); + print '
'.$langs->trans("ModePaiement").''; + $html->select_types_paiements($object->fk_c_paiement,'fk_c_paiement'); + print '
'.$langs->trans("VALIDATOR").''; + $include_users = $object->fetch_users_approver_expensereport(); + $s=$html->select_dolusers($object->fk_user_validator,"fk_user_validator",0,"",0,$include_users); + print $html->textwithpicto($s, $langs->trans("AnyOtherInThisListCanValidate")); + print '
'.$langs->trans("VALIDOR").''; + $userfee=new User($db); + $userfee->fetch($object->fk_user_valid); + print $userfee->getNomUrl(1); + print '
'.$langs->trans("AUTHOR").''; + $userfee=new User($db); + $userfee->fetch($object->fk_user_author); + print $userfee->getNomUrl(1); + print '
'.$langs->trans("AUTHORPAIEMENT").''; + $userfee=new User($db); + $userfee->fetch($object->fk_user_paid); + print $userfee->getNomUrl(1); + print '
'.$langs->trans("Note").''; + print ''; + print '
'; + + print '
'; + print '     '; + print ''; + print '
'; + + print '
'; + + } + else + { + + if ($action == 'save'): + $ret=$html->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("SaveTrip"),$langs->trans("ConfirmSaveTrip"),"confirm_save","","",1); + if ($ret == 'html') print '
'; + endif; + + if ($action == 'save_from_refuse'): + $ret=$html->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("SaveTrip"),$langs->trans("ConfirmSaveTrip"),"confirm_save_from_refuse","","",1); + if ($ret == 'html') print '
'; + endif; + + if ($action == 'delete'): + $ret=$html->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("DeleteTrip"),$langs->trans("ConfirmDeleteTrip"),"confirm_delete","","",1); + if ($ret == 'html') print '
'; + endif; + + if ($action == 'validate'): + $ret=$html->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("ValideTrip"),$langs->trans("ConfirmValideTrip"),"confirm_validate","","",1); + if ($ret == 'html') print '
'; + endif; + + if ($action == 'paid'): + $ret=$html->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("PaidTrip"),$langs->trans("ConfirmPaidTrip"),"confirm_paid","","",1); + if ($ret == 'html') print '
'; + endif; + + if ($action == 'cancel'): + $array_input = array(array('type'=>"text",'label'=>"Entrez ci-dessous un motif d'annulation :",'name'=>"detail_cancel",'size'=>"50",'value'=>"")); + $ret=$html->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("ConfirmCancelTrip"),"","confirm_cancel",$array_input,"",0); + if ($ret == 'html') print '
'; + endif; + + if ($action == 'brouillonner'): + $ret=$html->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("BrouillonnerTrip"),$langs->trans("ConfirmBrouillonnerTrip"),"confirm_brouillonner","","",1); + if ($ret == 'html') print '
'; + endif; + + if ($action == 'refuse'): + $array_input = array(array('type'=>"text",'label'=>"Entrez ci-dessous un motif de refus :",'name'=>"detail_refuse",'size'=>"50",'value'=>"")); + $ret=$html->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("ConfirmRefuseTrip"),"","confirm_refuse",$array_input,"yes",0); + if ($ret == 'html') print '
'; + endif; + + if ($action == 'delete_line') + { + $ret=$html->form_confirm($_SEVER["PHP_SELF"]."?id=".$_GET['id']."&rowid=".$_GET['rowid'],$langs->trans("DeleteLine"),$langs->trans("ConfirmDeleteLine"),"confirm_delete_line"); + if ($ret == 'html') print '
'; + } + + print ''; + + $linkback = ''.$langs->trans("BackToList").''; + + // Ref + print ''; + + print ''; + print ''; + print ''; + print ''; + if (! empty($conf->global->EXPENSEREPORT_ASK_PAYMENTMODE_ON_CREATION)) + { + print ''; + print ''; + print ''; + print ''; + } + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + if($object->fk_c_expensereport_statuts<3) + { + print ''; + print ''; + print ''; + } + elseif($object->fk_c_expensereport_statuts==4) + { + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + } + else + { + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + } + + print ''; + print ''; + print ''; + + print ''; + print ''; + print ''; + print ''; + if($object->fk_c_expensereport_statuts==6) + { + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + } + if($object->fk_c_expensereport_statuts==99 || !empty($object->detail_refuse)) + { + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + } + print '
'.$langs->trans("Ref").''; + print $form->showrefnav($object, 'id', $linkback, 1, 'rowid', 'ref', ''); + print '
'.$langs->trans("Periode").''; + print get_date_range($object->date_debut,$object->date_fin,'',$langs,0); + print '
'.$langs->trans("ModePaiement").''.$object->libelle_paiement.'
'.$langs->trans("Statut").''.$object->libelle_statut.'
'.$langs->trans("Note").''.$object->note.'
'.$langs->trans("AmountHT").''.price($object->total_ht).'
'.$langs->trans("AmountVAT").''.price($object->total_tva).'
'.$langs->trans("AmountTTC").''.price($object->total_ttc).'
'.$langs->trans("VALIDATOR").''; + $userfee=new User($db); + $userfee->fetch($object->fk_user_validator); + print $userfee->getNomUrl(1); + print '
'.$langs->trans("CANCEL_USER").''; + $userfee=new User($db); + $userfee->fetch($object->fk_user_cancel); + print $userfee->getNomUrl(1); + print '
'.$langs->trans("MOTIF_CANCEL").''.$object->detail_cancel.'
'.$langs->trans("DATE_CANCEL").''.$object->date_cancel.'
'.$langs->trans("VALIDOR").''; + $userfee=new User($db); + $userfee->fetch($object->fk_user_valid); + print $userfee->getNomUrl(1); + print '
'.$langs->trans("DATE_VALIDE").''.$object->date_valide.'
'.$langs->trans("AUTHOR").''; + $userfee=new User($db); + $userfee->fetch($object->fk_user_author); + print $userfee->getNomUrl(1); + print '
'.$langs->trans("DATE_SAVE").''.$object->date_create.'
'.$langs->trans("AUTHORPAIEMENT").''; + $userfee=new User($db); + $userfee->fetch($object->fk_user_paid); + print $userfee->getNomUrl(1); + print '
'.$langs->trans("DATE_PAIEMENT").''.$object->date_paiement.'
'.$langs->trans("REFUSEUR").''; + $userfee=new User($db); + $userfee->fetch($object->fk_user_refuse); + print $userfee->getNomUrl(1); + print '
'.$langs->trans("MOTIF_REFUS").''.$object->detail_refuse.'
'.$langs->trans("DATE_REFUS").''.$object->date_refuse.'
'; + + print '
'; + + // Fetch Lines of current ndf + $sql = 'SELECT fde.rowid, fde.fk_expensereport, fde.fk_c_type_fees, fde.fk_projet, fde.date,'; + $sql.= ' fde.fk_c_tva, fde.comments, fde.qty, fde.value_unit, fde.total_ht, fde.total_tva, fde.total_ttc,'; + $sql.= ' ctf.code as type_fees_code, ctf.label as type_fees_libelle,'; + $sql.= ' pjt.rowid as projet_id, pjt.title as projet_title, pjt.ref as projet_ref,'; + $sql.= ' tva.rowid as tva_id, tva.taux as tva_taux'; + $sql.= ' FROM '.MAIN_DB_PREFIX.'expensereport_det fde'; + $sql.= ' INNER JOIN '.MAIN_DB_PREFIX.'c_type_fees ctf ON fde.fk_c_type_fees=ctf.id'; + $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'projet pjt ON fde.fk_projet=pjt.rowid'; + $sql.= ' INNER JOIN '.MAIN_DB_PREFIX.'c_tva tva ON fde.fk_c_tva=tva.rowid'; + $sql.= ' WHERE fde.fk_expensereport = '.$id; + + $resql = $db->query($sql); + if ($resql) + { + $num_lignes = $db->num_rows($resql); + $i = 0;$total = 0; + + if ($num_lignes) + { + print '
'; + + print '
'; + print ''; + print ''; + print ''; + + print ''; + + print ''; + if ($action != 'editline') print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + if ($action != 'editline') + { + print ''; + print ''; + } + // Ajout des boutons de modification/suppression + if ($object->fk_c_expensereport_statuts<2 OR $object->fk_c_expensereport_statuts==99) + { + print ''; + } + + print ''; + + $var=true; + while ($i < $num_lignes) + { + $piece_comptable = $i + 1; + $objp = $db->fetch_object($resql); + $var=!$var; + if ($action != 'editline') + { + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + // Ajout des boutons de modification/suppression + if($object->fk_c_expensereport_statuts<2 OR $object->fk_c_expensereport_statuts==99) + { + print ''; + } + print ''; + } + else + { + if($objp->rowid==$_GET['rowid']) + { + //modif ligne!!!!! + print ''; + // Sélection date + print ''; + + // Sélection projet + print ''; + + // Sélection type + print ''; + + // Add comments + print ''; + + // Sélection TVA + print ''; + + // Prix unitaire + print ''; + + // Quantité + print ''; + + print ''; + } + } + + $i++; + } + + $db->free($resql); + + print '
'.$langs->trans('Piece').''.$langs->trans('Date').''.$langs->trans('Project').''.$langs->trans('Type').''.$langs->trans('Description').''.$langs->trans('VAT').''.$langs->trans('UnitPriceTTC').''.$langs->trans('Qty').''.$langs->trans('AmountHT').''.$langs->trans('AmountTTC').'
'; + print img_picto("Document", "generic"); + print ' '.$piece_comptable.''.$objp->date.''.$objp->projet_ref.''.$langs->trans("TF_".strtoupper($objp->type_fees_libelle)).''.$objp->comments.''.vatrate($objp->tva_taux,true).''.price($objp->value_unit).''.$objp->qty.''.$objp->total_ht.''.$objp->total_ttc.''; + print 'rowid.'#'.$objp->rowid.'">'; + print img_edit(); + print '   '; + print 'rowid.'">'; + print img_delete(); + print ''; + print '
'; + $html->select_date($objp->date,'date'); + print ''; + print select_projet($objp->fk_projet,'','fk_projet'); + print ''; + select_type_fees_id($objp->type_fees_code,'fk_c_type_fees'); + print ''; + print ''; + print ''; + print $form->load_tva('fk_c_tva', (isset($_POST["fk_c_tva"])?$_POST["fk_c_tva"]:$objp->tva_taux), $mysoc, ''); + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print '
'; + print '
'; + + print '
'; + + print '
'; + } + else + { + /* print ''; + print ''; + print '
'.$langs->trans("AucuneLigne").'
';*/ + } + //print '
'; + + // Ajouter une ligne + if (($object->fk_c_expensereport_statuts==1 || $object->fk_c_expensereport_statuts==99) && $action != 'editline') + { + print_fiche_titre($langs->trans("AddLine"),'',''); + + print '
'; + print ''; + print ''; + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + print ''; + + // Sélection date + print ''; + + // Sélection projet + print ''; + + // Sélection type + print ''; + + // Add comments + print ''; + + // Sélection TVA + print ''; + + // Prix unitaire + print ''; + + // Quantité + print ''; + + print ''; + print ''; + + print '
'.$langs->trans('Date').''.$langs->trans('Project').''.$langs->trans('Type').''.$langs->trans('Description').''.$langs->trans('VAT').''.$langs->trans('UnitPriceTTC').''.$langs->trans('Qty').'
'; + $html->select_date(-1,'date'); + print ''; + print select_projet('','','fk_projet'); + //$formproject->select_projects('','','fk_projet'); + print ''; + select_type_fees_id('TF_TRAIN','fk_c_type_fees'); + print ''; + print ''; + print ''; + print $form->load_tva('fk_c_tva', (isset($_POST["fk_c_tva"])?$_POST["fk_c_tva"]:-1), $mysoc, ''); + print ''; + print ''; + print ''; + print ''; + print '
'; + + print '
'; + } // Fin si c'est payé/validé + + } + } // end edit or not edit + + dol_fiche_end(); + + } // end of if result + else + { + dol_print_error($db); + } + + } //fin si id > 0 + +} + + + +/* + * Barre d'actions + */ + +print '
'; + +if ($action != 'create' && $action != 'edit') +{ + $object = new ExpenseReport($db); + $object->fetch($id,$user); + + /* Si l'état est "Brouillon" + * ET user à droit "creer/supprimer" + * ET fk_user_author == user courant + * Afficher : "Enregistrer" / "Modifier" / "Supprimer" + */ + if($user->rights->expensereport->creer AND $object->fk_c_expensereport_statuts==1) + { + if($object->fk_user_author==$user->id) + { + // Modifier + print ''.$langs->trans('ModifyInfoGen').''; + + // Enregistrer + print ''.$langs->trans('Validate').''; + + if ($user->rights->expensereport->supprimer) + { + // Supprimer + print ''.$langs->trans('Delete').''; + } + } + } + + /* Si l'état est "Refusée" + * ET user à droit "creer/supprimer" + * ET fk_user_author == user courant + * Afficher : "Enregistrer" / "Modifier" / "Supprimer" + */ + if($user->rights->expensereport->creer && $object->fk_c_expensereport_statuts==99) + { + if ($object->fk_user_author == $user->id) + { + // Modifier + print ''.$langs->trans('ModifyInfoGen').''; + + // Brouillonner (le statut refusée est identique à brouillon) + //print ''.$langs->trans('BROUILLONNER').''; + // Enregistrer depuis le statut "Refusée" + print ''.$langs->trans('Validate').''; + + if ($user->rights->expensereport->supprimer) + { + // Supprimer + print ''.$langs->trans('Delete').''; + } + } + } + + if ($user->rights->expensereport->to_paid && $object->fk_c_expensereport_statuts==5) + { + if ($object->fk_user_author == $user->id || $object->fk_user_valid == $user->id) + { + // Brouillonner + print ''.$langs->trans('BROUILLONNER').''; + } + } + + /* Si l'état est "En attente d'approbation" + * ET user à droit de "to_validate" + * ET fk_user_validator == user courant + * Afficher : "Valider" / "Refuser" / "Supprimer" + */ + if ($object->fk_c_expensereport_statuts == 2) + { + if ($object->fk_user_author == $user->id) + { + // Brouillonner + print ''.$langs->trans('BROUILLONNER').''; + } + } + + if ($user->rights->expensereport->to_validate && $object->fk_c_expensereport_statuts == 2) + { + //if($object->fk_user_validator==$user->id) + //{ + // Valider + print ''.$langs->trans('Approve').''; + // Refuser + print ''.$langs->trans('REFUSE').''; + //} + + if ($object->fk_user_author==$user->id) + { + // Annuler + print ''.$langs->trans('CANCEL').''; + } + + if($user->rights->expensereport->supprimer) + { + // Supprimer + print ''.$langs->trans('Delete').''; + } + } + + /* Si l'état est "A payer" + * ET user à droit de "to_paid" + * Afficher : "Annuler" / "Payer" / "Supprimer" + */ + if ($user->rights->expensereport->to_paid && $object->fk_c_expensereport_statuts==5) + { + // Payer + print ''.$langs->trans('TO_PAID').''; + + // Annuler + print ''.$langs->trans('CANCEL').''; + + if($user->rights->expensereport->supprimer) + { + // Supprimer + print ''.$langs->trans('Delete').''; + } + } + + /* Si l'état est "Payée" + * ET user à droit "to_validate" + * ET user à droit "to_paid" + * Afficher : "Annuler" + */ + if ($user->rights->expensereport->to_validate && $user->rights->expensereport->to_paid && $object->fk_c_expensereport_statuts==6) + { + // Annuler + print ''.$langs->trans('Cancel').''; + if($user->rights->expensereport->supprimer) + { + // Supprimer + print ''.$langs->trans('Delete').''; + } + } + + /* Si l'état est "Annulée" + * ET user à droit "supprimer" + * Afficher : "Supprimer" + */ + if ($user->rights->expensereport->supprimer && $object->fk_c_expensereport_statuts==4) + { + + if ($object->fk_user_validator==$user->id) + { + // Brouillonner + print ''.$langs->trans('BROUILLONNER').''; + } + + // Supprimer + print ''.$langs->trans('Delete').''; + + } +} + +print '
'; + + +$conf->global->DOL_URL_ROOT_DOCUMENT_PHP=dol_buildpath('/expensereport/documentwrapper.php',1); + + +print '
'; + +/* + * Documents generes + */ +if($user->rights->expensereport->export && $object->fk_c_expensereport_statuts>0 && $action != 'edit') +{ + $filename = dol_sanitizeFileName($object->ref_number); + $filedir = $conf->expensereport->dir_output . "/" . dol_sanitizeFileName($object->ref_number); + $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id; + $genallowed = 1; + $delallowed = 1; + $var = true; + print $formfile->showdocuments('expensereport',$filename,$filedir,$urlsource,$genallowed,$delallowed); + $somethingshown = $formfile->numoffiles; +} + +print '
'; + + +llxFooter(); + +$db->close(); diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php new file mode 100755 index 00000000000..c54090dfe2f --- /dev/null +++ b/htdocs/expensereport/class/expensereport.class.php @@ -0,0 +1,1496 @@ +db = $db; + $this->total_ht = 0; + $this->total_ttc = 0; + $this->total_tva = 0; + + // List of language codes for status + $this->statuts[0]='Draft'; + $this->statuts[2]='Validated'; + $this->statuts[4]='Canceled'; + $this->statuts[5]='Approved'; + $this->statuts[6]='Paid'; + $this->statuts[99]='Refused'; + $this->statuts_short[0]='Draft'; + $this->statuts_short[2]='Validated'; + $this->statuts_short[4]='Canceled'; + $this->statuts_short[5]='Approved'; + $this->statuts_short[6]='Paid'; + $this->statuts_short[99]='Refused'; + $this->statuts_logo[0]='statut0'; + $this->statuts_logo[2]='statut4'; + $this->statuts_logo[4]='statut3'; + $this->statuts_logo[5]='statut5'; + $this->statuts_logo[6]='statut6'; + $this->statuts_logo[99]='statutx'; + + return 1; + } + + /** + * Create object in database + * + * @param User $user User that create + * @return int <0 if KO, >0 if OK + */ + function create($user) + { + global $conf; + + $now = dol_now(); + + $this->db->begin(); + + $sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." ("; + $sql.= "ref_number"; + $sql.= ",total_ht"; + $sql.= ",total_ttc"; + $sql.= ",total_tva"; + $sql.= ",date_debut"; + $sql.= ",date_fin"; + $sql.= ",date_create"; + $sql.= ",fk_user_author"; + $sql.= ",fk_user_validator"; + $sql.= ",fk_c_expensereport_statuts"; + $sql.= ",fk_c_paiement"; + $sql.= ",note"; + $sql.= ") VALUES("; + $sql.= "'(PROV)'"; + $sql.= ", ".$this->total_ht; + $sql.= ", ".$this->total_ttc; + $sql.= ", ".$this->total_tva; + $sql.= ", '".$this->db->idate($this->date_debut)."'"; + $sql.= ", '".$this->db->idate($this->date_fin)."'"; + $sql.= ", '".$this->db->idate($now)."'"; + $sql.= ", ".($user->id > 0 ? $user->id:"null"); + $sql.= ", ".($this->fk_user_validator > 0 ? $this->fk_user_validator:2); + $sql.= ", ".($this->fk_c_expensereport_statuts > 1 ? $this->fk_c_expensereport_statuts:1); + $sql.= ", ".($this->fk_c_paiement > 0 ? $this->fk_c_paiement:2); + $sql.= ", ".($this->note?"'".$this->note."'":"null"); + $sql.= ")"; + + dol_syslog(get_class($this)."::create sql=".$sql, LOG_DEBUG); + $result = $this->db->query($sql); + if ($result) + { + $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element); + $this->ref_number='(PROV'.$this->id.')'; + + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element." SET ref_number='".$this->ref_number."' WHERE rowid=".$this->id; + dol_syslog(get_class($this)."::create sql=".$sql); + $resql=$this->db->query($sql); + if (!$resql) $error++; + + foreach ($this->lignes as $i => $val) + { + $newndfline=new ExpenseReportLigne($this->db); + $newndfline=$this->lignes[$i]; + $newndfline->fk_expensereport=$this->id; + if ($result >= 0) + { + $result=$newndfline->insert(); + } + if ($result < 0) + { + $error++; + break; + } + } + + if (! $error) + { + $result=$this->update_price(); + if ($result > 0) + { + $this->db->commit(); + return $this->id; + } + else + { + $this->db->rollback(); + return -3; + } + } + else + { + dol_syslog(get_class($this)."::create error ".$this->error, LOG_ERR); + $this->db->rollback(); + return -2; + } + } + else + { + $this->error=$this->db->error()." sql=".$sql; + $this->db->rollback(); + return -1; + } + + } + + /** + * update + * + * @param User $user User making change + * @return int <0 if KO, >0 if OK + */ + function update($user) + { + global $langs; + + $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET"; + $sql.= " total_ht = ".$this->total_ht; + $sql.= " , total_ttc = ".$this->total_ttc; + $sql.= " , total_tva = ".$this->total_tva; + $sql.= " , date_debut = '".$this->date_debut."'"; + $sql.= " , date_fin = '".$this->date_fin."'"; + $sql.= " , fk_user_author = ".($user->id > 0 ? "'".$user->id."'":"null"); + $sql.= " , fk_user_validator = ".($this->fk_user_validator > 0 ? $this->fk_user_validator:"null"); + $sql.= " , fk_user_valid = ".($this->fk_user_valid > 0 ? $this->fk_user_valid:"null"); + $sql.= " , fk_user_paid = ".($this->fk_user_paid > 0 ? $this->fk_user_paid:"null"); + $sql.= " , fk_c_expensereport_statuts = ".($this->fk_c_expensereport_statuts > 0 ? $this->fk_c_expensereport_statuts:"null"); + $sql.= " , fk_c_paiement = ".($this->fk_c_paiement > 0 ? $this->fk_c_paiement:"null"); + $sql.= " , note = ".(!empty($this->note)?"'".$this->db->escape($this->note)."'":"''"); + $sql.= " , detail_refuse = ".(!empty($this->detail_refuse)?"'".$this->db->escape($this->detail_refuse)."'":"''"); + $sql.= " WHERE rowid = ".$this->id; + + dol_syslog(get_class($this)."::update sql=".$sql, LOG_DEBUG); + $result = $this->db->query($sql); + if ($result) + { + return 1; + } + else + { + $this->error=$this->db->error(); + return -1; + } + } + + /** + * Load an object from database + */ + function fetch($id,$user='') + { + global $conf,$db; + + if(!$user->rights->expensereport->lire): + $restrict = " AND fk_user_author = ".$user->id; + else: + $restrict = ""; + endif; + + $sql = "SELECT d.rowid, d.ref_number, d.note,"; // DEFAULT + $sql.= " d.detail_refuse, d.detail_cancel, d.fk_user_refuse, d.fk_user_cancel,"; // ACTIONS + $sql.= " d.date_refuse, d.date_cancel,"; // ACTIONS + $sql.= " d.total_ht, d.total_ttc, d.total_tva,"; // TOTAUX (int) + $sql.= " d.date_debut, d.date_fin, d.date_create, d.date_valide, d.date_paiement,"; // DATES (datetime) + $sql.= " d.fk_user_author, d.fk_user_validator, d.fk_c_expensereport_statuts, d.fk_c_paiement,"; // FOREING KEY (int) + $sql.= " d.fk_user_valid, d.fk_user_paid,"; // FOREING KEY 2 (int) + $sql.= " dp.libelle as libelle_paiement, dp.code as code_paiement"; // INNER JOIN paiement + $sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element." d"; + $sql.= " INNER JOIN ".MAIN_DB_PREFIX."c_paiement dp ON d.fk_c_paiement = dp.id"; + $sql.= " WHERE d.rowid = ".$id; + $sql.= $restrict; + + dol_syslog(get_class($this)."::fetch sql=".$sql, LOG_DEBUG); + $result = $db->query($sql) ; + if ($result) + { + $obj = $db->fetch_object($result); + + $this->id = $obj->rowid; + $this->ref = $obj->ref_number; + $this->ref_number = $obj->ref_number; + $this->total_ht = $obj->total_ht; + $this->total_tva = $obj->total_tva; + $this->total_ttc = $obj->total_ttc; + $this->note = $obj->note; + $this->detail_refuse = $obj->detail_refuse; + $this->detail_cancel = $obj->detail_cancel; + + $this->date_debut = $obj->date_debut; + $this->date_fin = $obj->date_fin; + $this->date_paiement = $obj->date_paiement; + $this->date_valide = $obj->date_valide; + $this->date_create = $obj->date_create; + $this->date_refuse = $obj->date_refuse; + $this->date_cancel = $obj->date_cancel; + + $this->fk_user_author = $obj->fk_user_author; + $this->fk_user_validator = $obj->fk_user_validator; + $this->fk_user_valid = $obj->fk_user_valid; + $this->fk_user_paid = $obj->fk_user_paid; + $this->fk_user_refuse = $obj->fk_user_refuse; + $this->fk_user_cancel = $obj->fk_user_cancel; + + $this->user_author_infos = $this->fetch_names($this->fk_user_author); + $this->user_validator_infos = $this->fetch_names($this->fk_user_validator); + + $this->fk_c_expensereport_statuts = $obj->fk_c_expensereport_statuts; + $this->fk_c_paiement = $obj->fk_c_paiement; + + if($this->fk_c_expensereport_statuts==5 || $this->fk_c_expensereport_statuts==6){ + $this->user_valid_infos = $this->fetch_names($this->fk_user_valid); + } + + if($this->fk_c_expensereport_statuts==6){ + $this->user_paid_infos = $this->fetch_names($this->fk_user_paid); + } + + $this->libelle_statut = $obj->libelle_statut; + $this->libelle_paiement = $obj->libelle_paiement; + $this->code_statut = $obj->code_statut; + $this->code_paiement = $obj->code_paiement; + + $this->lignes = array(); + + $result=$this->fetch_lines(); + + return 1; + } + else + { + $this->error=$db->error(); + return -1; + } + } + + + /** + * Returns the label status + * + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto + * @return string Label + */ + function getLibStatut($mode=0) + { + return $this->LibStatut($this->status,$mode); + } + + /** + * Returns the label of a statut + * + * @param int $status id statut + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto + * @return string Label + */ + function LibStatut($status,$mode=0) + { + global $langs; + + if ($mode == 0) + return $langs->trans($this->statuts[$status]); + + if ($mode == 1) + return $langs->trans($this->statuts_short[$status]); + + if ($mode == 2) + return img_picto($langs->trans($this->statuts_short[$status]), $this->statuts_logo[$status]).' '.$langs->trans($this->statuts_short[$status]); + + if ($mode == 3) + return img_picto($langs->trans($this->statuts_short[$status]), $this->statuts_logo[$status]); + + if ($mode == 4) + return img_picto($langs->trans($this->statuts_short[$status]),$this->statuts_logo[$status]).' '.$langs->trans($this->statuts[$status]); + + if ($mode == 5) + return ''.$langs->trans($this->statuts_short[$status]).' '.img_picto($langs->trans($this->statuts_short[$status]),$this->statuts_logo[$status]); + + } + + + /** + * + * @param unknown_type $id + * @return unknown + */ + function fetch_names($id) + { + global $db; + + $sql = "SELECT lastname, firstname, email, user_mobile, office_phone "; + $sql.= "FROM ".MAIN_DB_PREFIX."user "; + $sql.= "WHERE rowid = ".$id; + $result = $db->query($sql); + $obj = $db->fetch_object($result); + return $obj; + } + + /** + * + * @param unknown_type $projectid + * @param unknown_type $user + */ + function fetch_line_by_project($projectid,$user='') + { + global $conf,$db,$langs; + + $langs->load('trips'); + + if($user->rights->expensereport->lire) { + + $sql = "SELECT de.fk_expensereport, de.date, de.comments, de.total_ht, de.total_ttc"; + $sql.= " FROM ".MAIN_DB_PREFIX."expensereport_det as de"; + $sql.= " WHERE de.fk_projet = ".$projectid; + + dol_syslog(get_class($this)."::fetch sql=".$sql, LOG_DEBUG); + $result = $db->query($sql) ; + if ($result) + { + $num = $db->num_rows($result); + $i = 0; + $total_HT = 0; + $total_TTC = 0; + + while ($i < $num) + { + + $objp = $db->fetch_object($result); + + $sql2 = "SELECT d.rowid, d.fk_user_author, d.ref_number, d.fk_c_expensereport_statuts"; + $sql2.= " FROM ".MAIN_DB_PREFIX."expensereport as d"; + $sql2.= " WHERE d.rowid = '".$objp->fk_expensereport."'"; + + $result2 = $db->query($sql2); + $obj = $db->fetch_object($result2); + + $objp->fk_user_author = $obj->fk_user_author; + $objp->ref_num = $obj->ref_number; + $objp->fk_c_expensereport_status = $obj->fk_c_expensereport_statuts; + $objp->rowid = $obj->rowid; + + $total_HT = $total_HT + $objp->total_ht; + $total_TTC = $total_TTC + $objp->total_ttc; + $author = new User($db); + $author->fetch($objp->fk_user_author); + + print ''; + print ''.$objp->ref_num.''; + print ''.dol_print_date($objp->date,'day').''; + print ''.$author->getNomUrl().''; + print ''.$objp->comments.''; + print ''.price($objp->total_ht).''; + print ''.price($objp->total_ttc).''; + print ''; + + switch($objp->fk_c_expensereport_status) { + case 4: + print img_picto($langs->trans('StatusOrderCanceled'),'statut5'); + break; + case 1: + print $langs->trans('Draft').' '.img_picto($langs->trans('Draft'),'statut0'); + break; + case 2: + print $langs->trans('TripForValid').' '.img_picto($langs->trans('TripForValid'),'statut3');; + break; + case 5: + print $langs->trans('TripForPaid').' '.img_picto($langs->trans('TripForPaid'),'statut3'); + break; + case 6: + print $langs->trans('TripPaid').' '.img_picto($langs->trans('TripPaid'),'statut4'); + break; + } + /* + if ($status==4) return img_picto($langs->trans('StatusOrderCanceled'),'statut5'); + if ($status==1) return img_picto($langs->trans('StatusOrderDraft'),'statut0'); + if ($status==2) return img_picto($langs->trans('StatusOrderValidated'),'statut1'); + if ($status==2) return img_picto($langs->trans('StatusOrderOnProcess'),'statut3'); + if ($status==5) return img_picto($langs->trans('StatusOrderToBill'),'statut4'); + if ($status==6) return img_picto($langs->trans('StatusOrderOnProcess'),'statut6'); + */ + print ''; + print ''; + + $i++; + } + + print ''.$langs->trans("Number").': '.$i.''; + print ''.$langs->trans("TotalHT").' : '.price($total_HT).''; + print ''.$langs->trans("TotalTTC").' : '.price($total_TTC).''; + print ' '; + print ''; + + } + else + { + $this->error=$db->error(); + return -1; + } + } + + } + + function recalculer($id){ + $sql = 'SELECT tt.total_ht, tt.total_ttc, tt.total_tva'; + $sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element_line.' as tt'; + $sql.= ' WHERE tt.'.$this->fk_element.' = '.$id; + + $total_ht = 0; $total_tva = 0; $total_ttc = 0; + + dol_syslog('ExpenseReport::recalculer sql='.$sql,LOG_DEBUG); + + $result = $this->db->query($sql); + if($result): + $num = $this->db->num_rows($result); + $i = 0; + while ($i < $num): + $objp = $this->db->fetch_object($result); + $total_ht+=$objp->total_ht; + $total_tva+=$objp->total_tva; + $i++; + endwhile; + + $total_ttc = $total_ht + $total_tva; + $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET"; + $sql.= " total_ht = ".$total_ht; + $sql.= " , total_ttc = ".$total_ttc; + $sql.= " , total_tva = ".$total_tva; + $sql.= " WHERE rowid = ".$id; + $result = $this->db->query($sql); + if($result): + $this->db->free($result); + return 1; + else: + $this->error=$this->db->error(); + dol_syslog('ExpenseReport::recalculer: Error '.$this->error,LOG_ERR); + return -3; + endif; + else: + $this->error=$this->db->error(); + dol_syslog('ExpenseReport::recalculer: Error '.$this->error,LOG_ERR); + return -3; + endif; + } + + function fetch_lines() + { + $sql = ' SELECT de.rowid, de.comments, de.qty, de.value_unit, de.date,'; + $sql.= ' de.'.$this->fk_element.', de.fk_c_type_fees, de.fk_projet, de.fk_c_tva,'; + $sql.= ' de.total_ht, de.total_tva, de.total_ttc,'; + $sql.= ' ctf.code as code_type_fees, ctf.label as libelle_type_fees,'; + $sql.= ' ctv.taux as taux_tva,'; + $sql.= ' p.ref as ref_projet, p.title as title_projet'; + $sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element_line.' as de'; + $sql.= ' INNER JOIN '.MAIN_DB_PREFIX.'c_type_fees ctf ON de.fk_c_type_fees = ctf.id'; + $sql.= ' INNER JOIN '.MAIN_DB_PREFIX.'c_tva ctv ON de.fk_c_tva = ctv.rowid'; + $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'projet p ON de.fk_projet = p.rowid'; + $sql.= ' WHERE de.'.$this->fk_element.' = '.$this->id; + + dol_syslog('ExpenseReport::fetch_lines sql='.$sql, LOG_DEBUG); + $result = $this->db->query($sql); + if ($result) + { + $num = $this->db->num_rows($result); + $i = 0; + while ($i < $num) + { + $objp = $this->db->fetch_object($result); + $deplig = new ExpenseReportLigne($this->db); + + $deplig->rowid = $objp->rowid; + $deplig->comments = $objp->comments; + $deplig->qty = $objp->qty; + $deplig->value_unit = $objp->value_unit; + $deplig->date = $objp->date; + + $deplig->fk_expensereport = $objp->fk_expensereport; + $deplig->fk_c_type_fees = $objp->fk_c_type_fees; + $deplig->fk_projet = $objp->fk_projet; + $deplig->fk_c_tva = $objp->fk_c_tva; + + $deplig->total_ht = $objp->total_ht; + $deplig->total_tva = $objp->total_tva; + $deplig->total_ttc = $objp->total_ttc; + + $deplig->type_fees_code = $objp->code_type_fees; + $deplig->type_fees_libelle = $objp->libelle_type_fees; + $deplig->tva_taux = $objp->taux_tva; + $deplig->projet_ref = $objp->ref_projet; + $deplig->projet_title = $objp->title_projet; + + $this->lignes[$i] = $deplig; + $i++; + } + $this->db->free($result); + return 1; + } + else + { + $this->error=$this->db->error(); + dol_syslog('ExpenseReport::fetch_lines: Error '.$this->error,LOG_ERR); + return -3; + } + } + + function delete($rowid=0) + { + global $user,$langs,$conf; + + if (!$rowid) $rowid=$this->id; + + $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element_line.' WHERE '.$this->fk_element.' = '.$rowid; + if ($this->db->query($sql)) + { + $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.' WHERE rowid = '.$rowid; + $resql=$this->db->query($sql); + if ($resql) + { + $this->db->commit(); + return 1; + } + else + { + $this->error=$this->db->error()." sql=".$sql; + dol_syslog("ExpenseReport.class::delete ".$this->error, LOG_ERR); + $this->db->rollback(); + return -6; + } + } + else + { + $this->error=$this->db->error()." sql=".$sql; + dol_syslog("ExpenseReport.class::delete ".$this->error, LOG_ERR); + $this->db->rollback(); + return -4; + } + } + + function set_save($user){ + global $conf,$langs; + + $expld_car = (empty($conf->global->NDF_EXPLODE_CHAR))?"-":$conf->global->NDF_EXPLODE_CHAR; + + // Sélection du numéro de ref suivant + $ref_next = $this->getNextNumRef(); + $ref_number_int = ($this->ref_number+1)-1; + + // Sélection de la date de début de la NDF + $sql = 'SELECT date_debut'; + $sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element; + $sql.= ' WHERE rowid = '.$this->id; + $result = $this->db->query($sql); + $objp = $this->db->fetch_object($result); + $this->date_debut = $objp->date_debut; + $expld_date_debut = explode("-",$this->date_debut); + $this->date_debut = $expld_date_debut[0].$expld_date_debut[1].$expld_date_debut[2]; + + // Création du ref_number suivant + if($ref_next): + $this->ref_number = strtoupper($user->login).$expld_car."NDF".$this->ref_number.$expld_car.$this->date_debut; + endif; + + if ($this->fk_c_expensereport_statuts != 2): + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; + $sql.= " SET ref_number = '".$this->ref_number."', fk_c_expensereport_statuts = 2"; + $sql.= " ,ref_number_int = $ref_number_int"; + $sql.= ' WHERE rowid = '.$this->id; + + dol_syslog(get_class($this)."::set_save sql=".$sql, LOG_DEBUG); + + if ($this->db->query($sql)): + return 1; + else: + $this->error=$this->db->error(); + return -1; + endif; + + else: + + dol_syslog(get_class($this)."::set_save expensereport already with save status", LOG_WARNING); + + endif; + } + + function set_save_from_refuse($user){ + global $conf,$langs; + + // Sélection de la date de début de la NDF + $sql = 'SELECT date_debut'; + $sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element; + $sql.= ' WHERE rowid = '.$this->id; + + $result = $this->db->query($sql); + + $objp = $this->db->fetch_object($result); + + $this->date_debut = $objp->date_debut; + $expld_date_debut = explode("-",$this->date_debut); + $this->date_debut = $expld_date_debut[0].$expld_date_debut[1].$expld_date_debut[2]; + + if ($this->fk_c_expensereport_statuts != 2): + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; + $sql.= " SET fk_c_expensereport_statuts = 2"; + $sql.= ' WHERE rowid = '.$this->id; + + dol_syslog(get_class($this)."::set_save_from_refuse sql=".$sql, LOG_DEBUG); + + if ($this->db->query($sql)): + return 1; + else: + $this->error=$this->db->error(); + return -1; + endif; + + else: + + dol_syslog(get_class($this)."::set_save_from_refuse expensereport already with save status", LOG_WARNING); + + endif; + } + + function set_valide($user){ + // date de validation + $this->date_valide = $this->db->idate(gmmktime()); + if ($this->fk_c_expensereport_statuts != 5): + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; + $sql.= " SET ref_number = '".$this->ref_number."', fk_c_expensereport_statuts = 5, fk_user_valid = ".$user->id; + $sql.= ', date_valide='.$this->date_valide; + $sql.= ' WHERE rowid = '.$this->id; + + dol_syslog(get_class($this)."::set_valide sql=".$sql, LOG_DEBUG); + + if ($this->db->query($sql)): + return 1; + else: + $this->error=$this->db->error(); + return -1; + endif; + else: + dol_syslog(get_class($this)."::set_valide expensereport already with valide status", LOG_WARNING); + endif; + } + + /** + * Refuse + * + * @param User $user User + * @param Details $details Details + */ + function set_refuse($user,$details) + { + // date de refus + $this->date_refuse = $this->db->idate(gmmktime()); + if ($this->fk_c_expensereport_statuts != 99): + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; + $sql.= " SET ref_number = '".$this->ref_number."', fk_c_expensereport_statuts = 99, fk_user_refuse = ".$user->id; + $sql.= ', date_refuse='.$this->date_refuse; + $sql.= ", detail_refuse='".addslashes($details)."'"; + $sql.= ' WHERE rowid = '.$this->id; + + dol_syslog(get_class($this)."::set_refuse sql=".$sql, LOG_DEBUG); + + if ($this->db->query($sql)): + return 1; + else: + $this->error=$this->db->error(); + return -1; + endif; + else: + dol_syslog(get_class($this)."::set_refuse expensereport already with refuse status", LOG_WARNING); + endif; + } + + function set_paid($user){ + $this->date_paiement = $this->db->idate(gmmktime()); + if ($this->fk_c_expensereport_statuts != 6): + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; + $sql.= " SET fk_c_expensereport_statuts = 6, fk_user_paid = ".$user->id; + $sql.= ', date_paiement='.$this->date_paiement; + $sql.= ' WHERE rowid = '.$this->id; + + dol_syslog(get_class($this)."::set_paid sql=".$sql, LOG_DEBUG); + + if ($this->db->query($sql)): + return 1; + else: + $this->error=$this->db->error(); + return -1; + endif; + else: + dol_syslog(get_class($this)."::set_paid expensereport already with paid status", LOG_WARNING); + endif; + } + + function set_unpaid($user) + { + if ($this->fk_c_expensereport_statuts != 5) + { + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; + $sql.= " SET fk_c_expensereport_statuts = 5"; + $sql.= ' WHERE rowid = '.$this->id; + + dol_syslog(get_class($this)."::set_unpaid sql=".$sql, LOG_DEBUG); + + if ($this->db->query($sql)): + return 1; + else: + $this->error=$this->db->error(); + return -1; + endif; + } + else + { + dol_syslog(get_class($this)."::set_unpaid expensereport already with unpaid status", LOG_WARNING); + } + } + + function set_draft($user) + { + if ($this->fk_c_expensereport_statuts != 1) + { + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; + $sql.= " SET fk_c_expensereport_statuts = 1,"; + //$sql.= " , ref_number = '(PROV".$this->id.")', ref_number_int = 0"; + $sql.= " ref_number_int = 0"; + $sql.= ' WHERE rowid = '.$this->id; + + dol_syslog(get_class($this)."::set_draft sql=".$sql, LOG_DEBUG); + + if ($this->db->query($sql)) return 1; + else + { + $this->error=$this->db->error(); + return -1; + } + } + else + { + dol_syslog(get_class($this)."::set_draft expensereport already with draft status", LOG_WARNING); + } + } + + function set_to_valide($user) + { + if ($this->fk_c_expensereport_statuts != 2): + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; + $sql.= " SET fk_c_expensereport_statuts = 2, fk_user_validator = ".$this->fk_user_validator; + $sql.= ' WHERE rowid = '.$this->id; + + dol_syslog(get_class($this)."::set_to_valide sql=".$sql, LOG_DEBUG); + + if ($this->db->query($sql)): + return 1; + else: + $this->error=$this->db->error(); + return -1; + endif; + else: + dol_syslog(get_class($this)."::set_to_valide expensereport already with to-valide status", LOG_WARNING); + endif; + } + + function set_cancel($user,$detail){ + $this->date_cancel = $this->db->idate(gmmktime()); + if ($this->fk_c_expensereport_statuts != 4): + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; + $sql.= " SET fk_c_expensereport_statuts = 4, fk_user_cancel = ".$user->id; + $sql.= ', date_cancel='.$this->date_cancel; + $sql.= " ,detail_cancel='".addslashes($detail)."'"; + $sql.= ' WHERE rowid = '.$this->id; + + dol_syslog(get_class($this)."::set_cancel sql=".$sql, LOG_DEBUG); + + if ($this->db->query($sql)): + return 1; + else: + $this->error=$this->db->error(); + return -1; + endif; + else: + dol_syslog(get_class($this)."::set_cancel expensereport already with cancel status", LOG_WARNING); + endif; + } + + function getNextNumRef(){ + global $conf; + + $expld_car = (empty($conf->global->NDF_EXPLODE_CHAR))?"-":$conf->global->NDF_EXPLODE_CHAR; + $num_car = (empty($conf->global->NDF_NUM_CAR_REF))?"5":$conf->global->NDF_NUM_CAR_REF; + + $sql = 'SELECT de.ref_number_int'; + $sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' de'; + $sql.= ' ORDER BY de.ref_number_int DESC'; + + $result = $this->db->query($sql); + + if($this->db->num_rows($result) > 0): + $objp = $this->db->fetch_object($result); + $this->ref_number = $objp->ref_number_int; + $this->ref_number++; + while(strlen($this->ref_number) < $num_car): + $this->ref_number = "0".$this->ref_number; + endwhile; + else: + $this->ref_number = 1; + while(strlen($this->ref_number) < $num_car): + $this->ref_number = "0".$this->ref_number; + endwhile; + endif; + + if ($result): + return 1; + else: + $this->error=$this->db->error(); + return -1; + endif; + } + + + /** + * Return clicable name (with picto eventually) + * + * @param int $withpicto 0=Pas de picto, 1=Inclut le picto dans le lien, 2=Picto seul + * @return string Chaine avec URL + */ + function getNomUrl($withpicto=0) + { + global $langs; + + $result=''; + + $lien = ''; + $lienfin=''; + + $picto='trip'; + + $label=$langs->trans("Show").': '.$this->ref; + + if ($withpicto) $result.=($lien.img_object($label,$picto).$lienfin); + if ($withpicto && $withpicto != 2) $result.=' '; + if ($withpicto != 2) $result.=$lien.$this->ref.$lienfin; + return $result; + } + + + function update_totaux_add($ligne_total_ht,$ligne_total_tva){ + $this->total_ht = $this->total_ht + $ligne_total_ht; + $this->total_tva = $this->total_tva + $ligne_total_tva; + $this->total_ttc = $this->total_ht + $this->total_tva; + + $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET"; + $sql.= " total_ht = ".$this->total_ht; + $sql.= " , total_ttc = ".$this->total_ttc; + $sql.= " , total_tva = ".$this->total_tva; + $sql.= " WHERE rowid = ".$this->id; + + $result = $this->db->query($sql); + if ($result): + return 1; + else: + $this->error=$this->db->error(); + return -1; + endif; + } + + function update_totaux_del($ligne_total_ht,$ligne_total_tva){ + $this->total_ht = $this->total_ht - $ligne_total_ht; + $this->total_tva = $this->total_tva - $ligne_total_tva; + $this->total_ttc = $this->total_ht + $this->total_tva; + + $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET"; + $sql.= " total_ht = ".$this->total_ht; + $sql.= " , total_ttc = ".$this->total_ttc; + $sql.= " , total_tva = ".$this->total_tva; + $sql.= " WHERE rowid = ".$this->id; + + $result = $this->db->query($sql); + if ($result): + return 1; + else: + $this->error=$this->db->error(); + return -1; + endif; + } + + + + function updateline($rowid, $type_fees_id, $projet_id, $c_tva, $comments, $qty, $value_unit, $date, $expensereport_id) + { + if ($this->fk_c_expensereport_statuts==1 || $this->fk_c_expensereport_statuts==99) + { + $this->db->begin(); + + // Select du taux de tva par rapport au code + $sql = "SELECT t.taux as taux_tva"; + $sql.= " FROM ".MAIN_DB_PREFIX."c_tva t"; + $sql.= " WHERE t.rowid = ".$c_tva; + $result = $this->db->query($sql); + $objp_tva = $this->db->fetch_object($result); + + // calcul de tous les totaux de la ligne + $total_ttc = $qty*$value_unit; + $total_ttc = number_format($total_ttc,2,'.',''); + + $tx_tva = $objp_tva->taux_tva/100; + $tx_tva = $tx_tva + 1; + $total_ht = $total_ttc/$tx_tva; + $total_ht = number_format($total_ht,2,'.',''); + + $total_tva = $total_ttc - $total_ht; + // fin calculs + + $ligne = new ExpenseReportLigne($this->db); + $ligne->comments = $comments; + $ligne->qty = $qty; + $ligne->value_unit = $value_unit; + $ligne->date = $date; + + $ligne->fk_expensereport = $expensereport_id; + $ligne->fk_c_type_fees = $type_fees_id; + $ligne->fk_projet = $projet_id; + $ligne->fk_c_tva = $c_tva; + + $ligne->total_ht = $total_ht; + $ligne->total_tva = $total_tva; + $ligne->total_ttc = $total_ttc; + $ligne->tva_taux = $objp_tva->taux_tva; + $ligne->rowid = $rowid; + + // Select des infos sur le type fees + $sql = "SELECT c.code as code_type_fees, c.label as libelle_type_fees"; + $sql.= " FROM ".MAIN_DB_PREFIX."c_type_fees c"; + $sql.= " WHERE c.id = ".$type_fees_id; + $result = $this->db->query($sql); + $objp_fees = $this->db->fetch_object($result); + $ligne->type_fees_code = $objp_fees->code_type_fees; + $ligne->type_fees_libelle = $objp_fees->libelle_type_fees; + + // Select des informations du projet + $sql = "SELECT p.ref as ref_projet, p.title as title_projet"; + $sql.= " FROM ".MAIN_DB_PREFIX."projet p"; + $sql.= " WHERE p.rowid = ".$projet_id; + $result = $this->db->query($sql); + $objp_projet = $this->db->fetch_object($result); + $ligne->projet_ref = $objp_projet->ref_projet; + $ligne->projet_title = $objp_projet->title_projet; + + $result = $ligne->update(); + if ($result > 0): + $this->db->commit(); + return 1; + else: + $this->error=$ligne->error; + $this->db->rollback(); + return -2; + endif; + + } + } + + /** + * deleteline + * + * @param unknown_type $rowid + * @param unknown_type $user + * @return number + */ + function deleteline($rowid, $user='') + { + $this->db->begin(); + + $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element_line; + $sql.= ' WHERE rowid = '.$rowid; + + dol_syslog(get_class($this)."::deleteline sql=".$sql); + $result = $this->db->query($sql); + if (!$result) + { + $this->error=$this->db->error(); + dol_syslog(get_class($this)."::deleteline Error ".$this->error, LOG_ERR); + $this->db->rollback(); + return -1; + } + + $this->db->commit(); + + return 1; + } + + /** + * dumpp + * + * @param unknown_type $value + */ + function dumpp($value) + { + echo '
'; + var_dump("
",$value,"
"); + echo '
'; + } + + /** + * periode_existe + * + * @param unknown_type $user + * @param unknown_type $date_debut + * @param unknown_type $date_fin + */ + function periode_existe($user,$date_debut,$date_fin) + { + $sql = "SELECT rowid,date_debut,date_fin"; + $sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element; + $sql.= " WHERE fk_user_author = '{$user->id}'"; + + dol_syslog(get_class($this)."::periode_existe sql=".$sql); + $result = $this->db->query($sql); + if($result): + $num_lignes = $this->db->num_rows($result); $i = 0; + + if($num_lignes>0): + $date_d_form = explode("-",$date_debut); // 1 + $date_f_form = explode("-",$date_fin); // 2 + $date_d_form = mktime(12,0,0,$date_d_form[1],$date_d_form[2],$date_d_form[0]); + $date_f_form = mktime(12,0,0,$date_f_form[1],$date_f_form[2],$date_f_form[0]); + + $existe = false; + + while ($i < $num_lignes): + $objp = $this->db->fetch_object($result); + + $date_d_req = explode("-",$objp->date_debut); // 3 + $date_f_req = explode("-",$objp->date_fin); // 4 + $date_d_req = mktime(12,0,0,$date_d_req[1],$date_d_req[2],$date_d_req[0]); + $date_f_req = mktime(12,0,0,$date_f_req[1],$date_f_req[2],$date_f_req[0]); + + if(!($date_f_form < $date_d_req OR $date_d_form > $date_f_req)) $existe = true; + + $i++; + endwhile; + + if($existe) return 1; + else return 0; + + else: + return 0; + endif; + else: + $this->error=$this->db->error(); + dol_syslog(get_class($this)."::periode_existe Error ".$this->error, LOG_ERR); + return -1; + endif; + } + + + /** + * Return list of people with permission to validate trips and expenses + * + * @return array Array of user ids + */ + function fetch_users_approver_expensereport() + { + $users_validator=array(); + + $sql = "SELECT fk_user"; + $sql.= " FROM ".MAIN_DB_PREFIX."user_rights as ur, ".MAIN_DB_PREFIX."rights_def as rd"; + $sql.= " WHERE ur.fk_id = rd.id and module = 'expensereport' AND perms = 'to_validate'"; // Permission 'Approve'; + + dol_syslog(get_class($this)."::fetch_users_approver_expensereport sql=".$sql); + $result = $this->db->query($sql); + if($result) + { + $num_lignes = $this->db->num_rows($result); $i = 0; + while ($i < $num_lignes) + { + $objp = $this->db->fetch_object($result); + array_push($users_validator,$objp->fk_user); + $i++; + } + return $users_validator; + } + else + { + $this->error=$this->db->lasterror(); + dol_syslog(get_class($this)."::fetch_users_approver_expensereport Error ".$this->error, LOG_ERR); + return -1; + } + } +} + + +/** + * Class of expense report details lines + */ +class ExpenseReportLigne +{ + var $db; + var $error; + + var $rowid; + var $comments; + var $qty; + var $value_unit; + var $date; + + var $fk_c_tva; + var $fk_c_type_fees; + var $fk_projet; + var $fk_expensereport; + + var $type_fees_code; + var $type_fees_libelle; + + var $projet_ref; + var $projet_title; + + var $tva_taux; + + var $total_ht; + var $total_tva; + var $total_ttc; + + + function ExpenseReportLigne($DB) + { + $this->db= $DB ; + } + + function fetch($rowid) + { + $sql = 'SELECT fde.rowid, fde.fk_expensereport, fde.fk_c_type_fees, fde.fk_projet, fde.date,'; + $sql.= ' fde.fk_c_tva, fde.comments, fde.qty, fde.value_unit, fde.total_ht, fde.total_tva, fde.total_ttc,'; + $sql.= ' ctf.code as type_fees_code, ctf.label as type_fees_libelle,'; + $sql.= ' pjt.rowid as projet_id, pjt.title as projet_title, pjt.ref as projet_ref,'; + $sql.= ' tva.rowid as tva_id, tva.taux as tva_taux'; + $sql.= ' FROM '.MAIN_DB_PREFIX.'expensereport_det fde'; + $sql.= ' INNER JOIN '.MAIN_DB_PREFIX.'c_type_fees ctf ON fde.fk_c_type_fees=ctf.id'; + $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'projet pjt ON fde.fk_projet=pjt.rowid'; + $sql.= ' INNER JOIN '.MAIN_DB_PREFIX.'c_tva tva ON fde.fk_c_tva=tva.rowid'; + $sql.= ' WHERE fde.rowid = '.$rowid; + + $result = $this->db->query($sql); + + if($result) { + $objp = $this->db->fetch_object($result); + + $this->rowid = $objp->rowid; + $this->fk_expensereport = $objp->fk_expensereport; + $this->comments = $objp->comments; + $this->qty = $objp->qty; + $this->date = $objp->date; + $this->value_unit = $objp->value_unit; + $this->fk_c_tva = $objp->fk_c_tva; + $this->fk_c_type_fees = $objp->fk_c_type_fees; + $this->fk_projet = $objp->fk_projet; + $this->type_fees_code = $objp->type_fees_code; + $this->type_fees_libelle = $objp->type_fees_libelle; + $this->projet_ref = $objp->projet_ref; + $this->projet_title = $objp->projet_title; + $this->tva_taux = $objp->tva_taux; + $this->total_ht = $objp->total_ht; + $this->total_tva = $objp->total_tva; + $this->total_ttc = $objp->total_ttc; + + $this->db->free($result); + } else { + dol_print_error($this->db); + } + } + + function insert($notrigger=0) + { + global $langs,$user,$conf; + + dol_syslog("ExpenseReportLigne::Insert rang=".$this->rang, LOG_DEBUG); + + // Clean parameters + $this->comments=trim($this->comments); + if (!$this->value_unit_HT) $this->value_unit_HT=0; + $this->qty = price2num($this->qty); + + $this->db->begin(); + + $sql = 'INSERT INTO '.MAIN_DB_PREFIX.'expensereport_det'; + $sql.= ' (fk_expensereport, fk_c_type_fees, fk_projet,'; + $sql.= ' fk_c_tva, comments, qty, value_unit, total_ht, total_tva, total_ttc, date)'; + $sql.= " VALUES (".$this->fk_expensereport.","; + $sql.= " ".$this->fk_c_type_fees.","; + $sql.= " ".($this->fk_projet>0?$this->fk_projet:'null').","; + $sql.= " ".$this->fk_c_tva.","; + $sql.= " '".$this->db->escape($this->comments)."',"; + $sql.= " ".$this->qty.","; + $sql.= " ".$this->value_unit.","; + $sql.= " ".$this->total_ht.","; + $sql.= " ".$this->total_tva.","; + $sql.= " ".$this->total_ttc.","; + $sql.= "'".$this->date."'"; + $sql.= ")"; + + dol_syslog("ExpenseReportLigne::insert sql=".$sql); + + $resql=$this->db->query($sql); + + if ($resql): + $this->rowid=$this->db->last_insert_id(MAIN_DB_PREFIX.'expensereport_det'); + $this->db->commit(); + return $this->rowid; + else: + $this->error=$this->db->error(); + dol_syslog("ExpenseReportLigne::insert Error ".$this->error, LOG_ERR); + $this->db->rollback(); + return -2; + endif; + } + + function update() + { + global $user,$langs,$conf; + + // Clean parameters + $this->comments=trim($this->comments); + + $this->db->begin(); + + // Mise a jour ligne en base + $sql = "UPDATE ".MAIN_DB_PREFIX."expensereport_det SET"; + $sql.= " comments='".addslashes($this->comments)."'"; + $sql.= ",value_unit=".$this->value_unit.""; + $sql.= ",qty=".$this->qty.""; + if ($this->date) { $sql.= ",date='".$this->date."'"; } + else { $sql.=',date=null'; } + $sql.= ",total_ht=".$this->total_ht.""; + $sql.= ",total_tva=".$this->total_tva.""; + $sql.= ",total_ttc=".$this->total_ttc.""; + if ($this->fk_c_type_fees) $sql.= ",fk_c_type_fees=".$this->fk_c_type_fees; + else $sql.= ",fk_c_type_fees=null"; + if ($this->fk_projet) $sql.= ",fk_projet=".$this->fk_projet; + else $sql.= ",fk_projet=null"; + if ($this->fk_c_tva) $sql.= ",fk_c_tva=".$this->fk_c_tva; + else $sql.= ",fk_c_tva=null"; + $sql.= " WHERE rowid = ".$this->rowid; + + dol_syslog("ExpenseReportLigne::update sql=".$sql); + + $resql=$this->db->query($sql); + if ($resql) + { + $this->db->commit(); + return 1; + } + else + { + $this->error=$this->db->error(); + dol_syslog("ExpenseReportLigne::update Error ".$this->error, LOG_ERR); + $this->db->rollback(); + return -2; + } + } + + function fetch_taux($id){ + $sql = "SELECT taux"; + $sql .= " FROM ".MAIN_DB_PREFIX ."c_tva"; + $sql .= " WHERE rowid = ".$id; + $resql=$this->db->query($sql); + $objp = $this->db->fetch_object($result); + $this->tva_taux = $objp->taux; + } +} + +/** + * Retourne la liste deroulante des differents etats d'une note de frais. + * Les valeurs de la liste sont les id de la table c_expensereport_statuts + * + * @param int $selected etat pre-selectionne + * @param string $htmlname Name of HTML select + * @param int $useempty 1=Add empty line + * @return string HTML select with sattus + */ +function select_expensereport_statut($selected='',$htmlname='fk_c_expensereport_statuts',$useempty=1) +{ + global $db; + + $tmpep=new ExpenseReport($db); + + print ''; +} + +/** + * + * @param unknown_type $selected + * @param unknown_type $filter + * @param unknown_type $htmlname + * + * TODO Utiliser le select project officiel + */ +function select_projet($selected='',$filter='', $htmlname='fk_projet') +{ + global $conf,$user,$langs,$db; + + $out=''; + + $sql = "SELECT p.rowid, p.ref, p.title"; + $sql.= " FROM ".MAIN_DB_PREFIX."projet as p"; + $sql.= " WHERE p.entity = ".$conf->entity; + if (is_numeric($selected)) $sql.= " AND p.rowid = ".$selected; + + dol_syslog("Form::select_projet sql=".$sql); + $resql=$db->query($sql); + if ($resql) + { + if ($conf->use_javascript_ajax && ! $forcecombo) + { + $minLength = (is_numeric($conf->global->COMPANY_USE_SEARCH_TO_SELECT)?$conf->global->COMPANY_USE_SEARCH_TO_SELECT:2); + + $projetid = 0; + + if ($selected) + { + $obj = $db->fetch_object($resql); + $projetid = $obj->rowid?$obj->rowid:''; + } + + $out.= "\n".''."\n"; + $out.= ''; + $out.= ''; + $out.= ''; + $out.= '
'; + if ($projetid == 0) { + $out.= ''; + } else { + $out.= ''; + } + $out.= ajax_autocompleter(($projetid?$projetid:-1),$htmlname,dol_buildpath('/expensereport/ajax/ajaxprojet.php',1).'?filter='.urlencode($filter), '', $minLength); + $out.= '
'; + } + + } + else + { + dol_print_error($db); + } + + return $out; +} + +/** + * Return list of types of notes with select value = id + * + * @param selected Preselected type + * @param htmlname Name of field in form + * @param showempty Add an empty field + * @return string Select html + */ +function select_type_fees_id($selected='',$htmlname='type',$showempty=0) +{ + global $db,$langs,$user; + $langs->load("trips"); + + print ''; +} diff --git a/htdocs/expensereport/class/expensereportstats.class.php b/htdocs/expensereport/class/expensereportstats.class.php new file mode 100644 index 00000000000..64d0aaf01ed --- /dev/null +++ b/htdocs/expensereport/class/expensereportstats.class.php @@ -0,0 +1,163 @@ + + * Copyright (c) 2005-2008 Laurent Destailleur + * Copyright (C) 2005-2009 Regis Houssin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/expensereport/class/expensereportstats.class.php + * \ingroup factures + * \brief Fichier de la classe de gestion des stats des expensereport et notes de frais + */ +include_once DOL_DOCUMENT_ROOT . '/core/class/stats.class.php'; +dol_include_once('/expensereport/class/expensereport.class.php'); + +/** + * Classe permettant la gestion des stats des expensereports et notes de frais + */ +class ExpenseReportStats extends Stats +{ + public $table_element; + + var $socid; + var $userid; + + var $from; + var $field; + var $where; + + /** + * Constructor + * + * @param DoliDB $db Database handler + * @param int $socid Id third party + * @param int $userid Id user for filter + * @return void + */ + function __construct($db, $socid=0, $userid=0) + { + global $conf; + + $this->db = $db; + $this->socid = $socid; + $this->userid = $userid; + + $object=new ExpenseReport($this->db); + $this->from = MAIN_DB_PREFIX.$object->table_element; + $this->field='total_ht'; + + $this->where = " fk_c_expensereport_statuts > 0 and date_valide > '2000-01-01'"; + //$this->where.= " AND entity = ".$conf->entity; + if ($this->socid) + { + $this->where.=" AND fk_soc = ".$this->socid; + } + if ($this->userid > 0) $this->where.=' AND fk_user_author = '.$this->userid; + } + + + /** + * Renvoie le nombre de facture par annee + * + * @return array Array of values + */ + function getNbByYear() + { + $sql = "SELECT YEAR(date_valide) as dm, count(*)"; + $sql.= " FROM ".$this->from; + $sql.= " GROUP BY dm DESC"; + $sql.= " WHERE ".$this->where; + + return $this->_getNbByYear($sql); + } + + + /** + * Renvoie le nombre de facture par mois pour une annee donnee + * + * @param string $year Year to scan + * @return array Array of values + */ + function getNbByMonth($year) + { + $sql = "SELECT MONTH(date_valide) as dm, count(*)"; + $sql.= " FROM ".$this->from; + $sql.= " WHERE YEAR(date_valide) = ".$year; + $sql.= " AND ".$this->where; + $sql.= " GROUP BY dm"; + $sql.= $this->db->order('dm','DESC'); + + $res=$this->_getNbByMonth($year, $sql); + //var_dump($res);print '
'; + return $res; + } + + + /** + * Renvoie le montant de facture par mois pour une annee donnee + * + * @param int $year Year to scan + * @return array Array of values + */ + function getAmountByMonth($year) + { + $sql = "SELECT date_format(date_valide,'%m') as dm, sum(".$this->field.")"; + $sql.= " FROM ".$this->from; + $sql.= " WHERE date_format(date_valide,'%Y') = '".$year."'"; + $sql.= " AND ".$this->where; + $sql.= " GROUP BY dm"; + $sql.= $this->db->order('dm','DESC'); + + $res=$this->_getAmountByMonth($year, $sql); + //var_dump($res);print '
'; + return $res; + } + + /** + * Return average amount + * + * @param int $year Year to scan + * @return array Array of values + */ + function getAverageByMonth($year) + { + $sql = "SELECT date_format(date_valide,'%m') as dm, avg(".$this->field.")"; + $sql.= " FROM ".$this->from; + $sql.= " WHERE date_format(date_valide,'%Y') = '".$year."'"; + $sql.= " AND ".$this->where; + $sql.= " GROUP BY dm"; + $sql.= $this->db->order('dm','DESC'); + + return $this->_getAverageByMonth($year, $sql); + } + + /** + * Return nb, total and average + * + * @return array Array of values + */ + function getAllByYear() + { + $sql = "SELECT date_format(date_valide,'%Y') as year, count(*) as nb, sum(".$this->field.") as total, avg(".$this->field.") as avg"; + $sql.= " FROM ".$this->from; + $sql.= " WHERE ".$this->where; + $sql.= " GROUP BY year"; + $sql.= $this->db->order('year','DESC'); + + return $this->_getAllByYear($sql); + } +} + diff --git a/htdocs/expensereport/document.php b/htdocs/expensereport/document.php new file mode 100644 index 00000000000..65ee2a1bbaa --- /dev/null +++ b/htdocs/expensereport/document.php @@ -0,0 +1,131 @@ + + * Copyright (C) 2004-2010 Laurent Destailleur + * Copyright (C) 2005 Marc Barilley / Ocebo + * Copyright (C) 2005-2009 Regis Houssin + * Copyright (C) 2005 Simon TOSSER + * Copyright (C) 2011-2012 Juanjo Menent + * Copyright (C) 2013 Cédric Salvador + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/compta/expensereport/document.php + * \ingroup expensereport + * \brief Page of linked files onto trip and expenses + */ + +require '../main.inc.php'; + +$langs->load("other"); +$langs->load("trips"); +$langs->load("companies"); +$langs->load("interventions"); + +$id = GETPOST('id','int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action','alpha'); +$confirm = GETPOST('confirm','alpha'); + +// Security check +if ($user->societe_id) $socid=$user->societe_id; +$result = restrictedArea($user, 'expensereport', $id, ''); + + +// Get parameters +$sortfield = GETPOST('sortfield','alpha'); +$sortorder = GETPOST('sortorder','alpha'); +$page = GETPOST('page','int'); +if ($page == -1) { $page = 0; } +$offset = $conf->liste_limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; +if (! $sortorder) $sortorder="ASC"; +if (! $sortfield) $sortfield="name"; + + +$object = new ExpenseReport($db); +$object->fetch($id, $ref); + +$upload_dir = $conf->expensereport->dir_output.'/'.dol_sanitizeFileName($object->ref); +$modulepart='trip'; + + +/* + * Actions + */ + +include_once DOL_DOCUMENT_ROOT . '/core/tpl/document_actions_pre_headers.tpl.php'; + + +/* + * View + */ + +$form = new Form($db); + +llxHeader("","",$langs->trans("TripCard")); + + +if ($object->id) +{ + $object->fetch_thirdparty(); + + $head=trip_prepare_head($object); + + dol_fiche_head($head, 'documents', $langs->trans("TripCard"), 0, 'trip'); + + + // Construit liste des fichiers + $filearray=dol_dir_list($upload_dir,"files",0,'','(\.meta|_preview\.png)$',$sortfield,(strtolower($sortorder)=='desc'?SORT_DESC:SORT_ASC),1); + $totalsize=0; + foreach($filearray as $key => $file) + { + $totalsize+=$file['size']; + } + + + print ''; + + $linkback = ''.$langs->trans("BackToList").''; + + // Ref + print ''; + + // Societe + //print ""; + + print ''; + print ''; + print '
'.$langs->trans("Ref").''; + print $form->showrefnav($object, 'id', $linkback, 1, 'rowid', 'ref', ''); + print '
".$langs->trans("Company")."".$object->client->getNomUrl(1)."
'.$langs->trans("NbOfAttachedFiles").''.count($filearray).'
'.$langs->trans("TotalSizeOfAttachedFiles").''.$totalsize.' '.$langs->trans("bytes").'
'; + + print ''; + + $modulepart = 'expensereport'; + $permission = $user->rights->expensereport->creer; + $param = '&id=' . $object->id; + include_once DOL_DOCUMENT_ROOT . '/core/tpl/document_actions_post_headers.tpl.php'; + +} +else +{ + print $langs->trans("ErrorUnknown"); +} + +llxFooter(); + +$db->close(); diff --git a/htdocs/expensereport/export_csv.php b/htdocs/expensereport/export_csv.php new file mode 100755 index 00000000000..07f4167b724 --- /dev/null +++ b/htdocs/expensereport/export_csv.php @@ -0,0 +1,199 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/expensereport/index.php + * \brief Page list of expenses + */ + +require '../main.inc.php'; +require_once(DOL_DOCUMENT_ROOT."/core/class/html.formfile.class.php"); +dol_include_once("/expensereport/class/expensereport.class.php"); + +$langs->load("users"); +$langs->load("trips"); + +if(!$user->rights->expensereport->export_csv) { + accessforbidden(); + exit(); +} + +// Security check +$socid = $_GET["socid"]?$_GET["socid"]:''; +if ($user->societe_id) $socid=$user->societe_id; +$result = restrictedArea($user, 'expensereport','',''); + +$req = "SELECT * FROM ".MAIN_DB_PREFIX."rights_def WHERE id = '178'"; +$result = $db->query($req); +$num = $db->num_rows($result); + +if($num < 1) { + + $insert = "INSERT INTO ".MAIN_DB_PREFIX."rights_def ("; + $insert.= "`id` ,"; + $insert.= "`libelle` ,"; + $insert.= "`module` ,"; + $insert.= "`entity` ,"; + $insert.= "`perms` ,"; + $insert.= "`subperms` ,"; + $insert.= "`type` ,"; + $insert.= "`bydefault`"; + $insert.= ")"; + $insert.= "VALUES ("; + $insert.= "'178', 'Exporter les notes de frais au format CSV', 'expensereport', '1', 'export_csv', NULL , 'r', '0'"; + $insert.= ")"; + + $req = $db->query($insert); + +} + + +/* + * View + */ + +llxHeader(); + +print_fiche_titre($langs->trans("ExportTripCSV")); + +print '
'; + +print '
'; +print ''; +print '

Choisir le mois à exporter : '; + +$year = date('Y', time()); +$month = date('m', time()); + +print ' '; + +print ' '; + +print ''; +print '

'; +print '
'."\n"; + +// Si c'est une action +if (isset($_POST['action'])) +{ + if($_POST['action'] == 'export') + { + $select_date = $_POST['annee'].'-'.$_POST['mois']; + + //var_dump($conf->expensereport->dir_output.'/export/'); + if (!file_exists($conf->expensereport->dir_output.'/export/')) + { + dol_mkdir($conf->expensereport->dir_output.'/export/'); + } + + $dir = $conf->expensereport->dir_output.'/export/expensereport-'.$select_date.'.csv'; + $outputlangs = $langs; + $outputlangs->charset_output = 'UTF-8'; + + $sql = "SELECT d.rowid, d.ref_number, d.date_paiement, d.total_ht, d.total_tva, d.total_ttc"; + $sql.= " FROM ".MAIN_DB_PREFIX."expensereport as d"; + $sql.= " WHERE date_paiement LIKE '".$select_date."%'"; + $sql.= " ORDER BY d.rowid"; + + $result = $db->query($sql); + $num = $db->num_rows($result); + if ($num) + { + $open = fopen($dir,"w+"); + + $ligne = "ID, Référence, ----, Date paiement, Montant HT, TVA, Montant TTC\n"; + for ($i = 0; $i < $num; $i++) + { + $ligne.= "----, ----, ----, ----, ----, ----, ----\n"; + $objet = $db->fetch_object($result); + $objet->total_ht = number_format($objet->total_ht,2); + $objet->total_tva = number_format($objet->total_tva,2); + $objet->total_ttc = number_format($objet->total_ttc,2); + $objet->ref_number = trim($objet->ref_number); + $ligne.= "{$objet->rowid}, {$objet->ref_number}, ----, {$objet->date_paiement}, {$objet->total_ht}, {$objet->total_tva}, {$objet->total_ttc}\n"; + + $ligne.= "--->, Ligne, Type, Description, ----, ----, ----\n"; + + + $sql2 = "SELECT de.rowid, t.label as libelle, de.comments, de.total_ht, de.total_tva, de.total_ttc"; + $sql2.= " FROM ".MAIN_DB_PREFIX."expensereport_det as de,"; + $sql2.= " ".MAIN_DB_PREFIX."c_type_fees as t"; + $sql2.= " WHERE de.fk_c_type_fees = t.id"; + $sql2.= " AND de.fk_expensereport = '".$objet->rowid."'"; + $sql2.= " ORDER BY de.date"; + + $result2 = $db->query($sql2); + $num2 = $db->num_rows($result2); + + if($num2) { + for ($a = 0; $a < $num2; $a++) + { + $objet2 = $db->fetch_object($result2); + $objet2->total_ht = number_format($objet2->total_ht,2); + $objet2->total_tva = number_format($objet2->total_tva,2); + $objet2->total_ttc = number_format($objet2->total_ttc,2); + $objet2->comments = str_replace(',',';',$objet2->comments); + $objet2->comments = str_replace("\r\n",' ',$objet2->comments); + $objet2->comments = str_replace("\n",' ',$objet2->comments); + + $ligne.= "--->, {$objet2->rowid}, {$objet2->libelle}, {$objet2->comments}, {$objet2->total_ht}, {$objet2->total_tva}, {$objet2->total_ttc}\n"; + } + } + + } + + $ligne = $outputlangs->convToOutputCharset($ligne); + + fwrite($open,$ligne); + fclose($open); + + print 'Télécharger le fichier expensereport-'.$select_date.'.csv'; + + } else { + + print ''.$langs->trans('NoTripsToExportCSV').''; + + } + } +} + +print '
'; + +llxFooter(); + +$db->close(); diff --git a/htdocs/expensereport/index.php b/htdocs/expensereport/index.php new file mode 100644 index 00000000000..aae513618db --- /dev/null +++ b/htdocs/expensereport/index.php @@ -0,0 +1,208 @@ + + * Copyright (C) 2004-2011 Laurent Destailleur + * Copyright (C) 2004 Eric Seigne + * Copyright (C) 2005-2011 Regis Houssin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/expensereport/index.php + * \brief Page list of expenses + */ + +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/compta/tva/class/tva.class.php'; +dol_include_once("/expensereport/class/expensereport.class.php"); + +$langs->load("companies"); +$langs->load("users"); +$langs->load("trips"); + +// Security check +$socid = GETPOST('socid','int'); +if ($user->societe_id) $socid=$user->societe_id; +$result = restrictedArea($user, 'expensereport','',''); + +$sortfield = GETPOST("sortfield",'alpha'); +$sortorder = GETPOST("sortorder",'alpha'); +$page = GETPOST("page",'int'); +if ($page == -1) { $page = 0; } +$offset = $conf->liste_limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; +if (! $sortorder) $sortorder="DESC"; +if (! $sortfield) $sortfield="d.date_create"; +$limit = $conf->liste_limit; + + +/* + * View + */ + +$tripandexpense_static=new ExpenseReport($db); + +$childids = $user->getAllChildIds(); +$childids[]=$user->id; + +//$help_url='EN:Module_Donations|FR:Module_Dons|ES:Módulo_Donaciones'; +$help_url=''; +llxHeader('',$langs->trans("ListOfFees"),$help_url); + + +$label=$somme=$nb=array(); + +$totalnb=$totalsum=0; +$sql = "SELECT tf.code, tf.label, count(de.rowid) as nb, sum(de.total_ht) as km"; +$sql.= " FROM ".MAIN_DB_PREFIX."expensereport as d, ".MAIN_DB_PREFIX."expensereport_det as de, ".MAIN_DB_PREFIX."c_type_fees as tf"; +$sql.= " WHERE de.fk_expensereport = d.rowid AND de.fk_c_type_fees = tf.id"; +if (empty($user->rights->expensereport->readall) && empty($user->rights->expensereport->lire_tous)) $sql.=' AND d.fk_user_author IN ('.join(',',$childids).')'; +$sql.= " GROUP BY tf.code, tf.label"; + +$result = $db->query($sql); +if ($result) +{ + $num = $db->num_rows($result); + $i = 0; + while ($i < $num) + { + $objp = $db->fetch_object($result); + + $somme[$objp->code] = $objp->km; + $nb[$objp->code] = $objp->nb; + $label[$objp->code] = $objp->label; + $totalnb += $objp->nb; + $totalsum += $objp->km; + $i++; + } + $db->free($result); +} else { + dol_print_error($db); +} + + +print_fiche_titre($langs->trans("ExpensesArea")); + + +print '
'; + + +print ''; +print ''; +print ''; +print "\n"; + +//$listoftype=$tripandexpense_static->listOfTypes(); +$listoftype=$label; +foreach ($listoftype as $code => $label) +{ + $dataseries[]=array('label'=>$label,'data'=>(isset($somme[$code])?(int) $somme[$code]:0)); +} + +if ($conf->use_javascript_ajax) +{ + print ''; +} + +print ''; +print ''; +print ''; +print ''; + +print '
'.$langs->trans("Statistics").'
'; + $data=array('series'=>$dataseries); + dol_print_graph('stats',320,180,$data,1,'pie',0); + print '
'.$langs->trans("Total").''.price($totalsum,1,$langs,0,0,0,$conf->currency).'
'; + + + +// Right area +print '
'; + + +$max=10; + +$langs->load("boxes"); + +$sql = "SELECT u.rowid as uid, u.lastname, u.firstname, d.rowid, d.date_debut as dated, d.date_fin as datef, d.date_create as dm, d.total_ht, d.total_ttc, d.fk_c_expensereport_statuts as fk_status"; +$sql.= " FROM ".MAIN_DB_PREFIX."expensereport as d, ".MAIN_DB_PREFIX."user as u"; +if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= ", ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."societe_commerciaux as sc"; +$sql.= " WHERE u.rowid = d.fk_user_author"; +if (empty($user->rights->expensereport->readall) && empty($user->rights->expensereport->lire_tous)) $sql.=' AND d.fk_user_author IN ('.join(',',$childids).')'; +//$sql.= " AND d.entity = ".$conf->entity; +if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= " AND d.fk_user_author = s.rowid AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id; +if ($socid) $sql.= " AND d.fk_user_author = ".$socid; +$sql.= $db->order($sortfield,$sortorder); +$sql.= $db->plimit($max, 0); + +$result = $db->query($sql); +if ($result) +{ + $var=false; + $num = $db->num_rows($result); + + $i = 0; + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + if ($num) + { + $total_ttc = $totalam = $total = 0; + + $expensereportstatic=new ExpenseReport($db); + $userstatic=new User($db); + while ($i < $num && $i < $max) + { + $obj = $db->fetch_object($result); + $expensereportstatic->ref=$obj->rowid; + $expensereportstatic->id=$obj->rowid; + $userstatic->id=$obj->uid; + $userstatic->lastname=$obj->lastname; + $userstatic->firstname=$obj->firstname; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + $var=!$var; + $i++; + } + + } + else + { + print ''; + } + print '
'.$langs->trans("BoxTitleLastModifiedExpenses",min($max,$num)).''.$langs->trans("AmountHT").''.$langs->trans("AmountTTC").''.$langs->trans("DateModificationShort").' 
'.$expensereportstatic->getNomUrl(1).''.$userstatic->getNomUrl(1).''.$obj->total_ht.''.$obj->total_ttc.''.dol_print_date($db->jdate($obj->dm),'day').''; + //print $obj->libelle; + print $expensereportstatic->LibStatut($obj->fk_status,3); + print '
'.$langs->trans("None").'

'; +} +else dol_print_error($db); + +print '
'; + +llxFooter(); + +$db->close(); diff --git a/htdocs/expensereport/info.php b/htdocs/expensereport/info.php new file mode 100644 index 00000000000..866e67ec04b --- /dev/null +++ b/htdocs/expensereport/info.php @@ -0,0 +1,63 @@ + + * Copyright (C) 2004-2005 Laurent Destailleur + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/expensereport/info.php + * \ingroup trip + * \brief Page to show a trip information + */ + +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/trip.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/compta/expensereport/class/expensereport.class.php'; + +$langs->load("trips"); + +// Security check +$id = GETPOST('id','int'); +if ($user->societe_id) $socid=$user->societe_id; +$result = restrictedArea($user, 'expensereport', $id, ''); + + +/* + * View + */ + +llxHeader(); + +if ($id) +{ + $object = new ExpenseReport($db); + $object->fetch($id); + $object->info($id); + + $head = trip_prepare_head($object); + + dol_fiche_head($head, 'info', $langs->trans("TripCard"), 0, 'trip'); + + print '
'; + dol_print_object_info($object); + print '
'; + + print ''; +} + +$db->close(); + +llxFooter(); diff --git a/htdocs/expensereport/list.php b/htdocs/expensereport/list.php new file mode 100755 index 00000000000..c9a965b5587 --- /dev/null +++ b/htdocs/expensereport/list.php @@ -0,0 +1,316 @@ + + * Copyright (C) 2004-2008 Laurent Destailleur + * Copyright (C) 2004 Eric Seigne + * Copyright (C) 2005-2009 Regis Houssin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/** + * \file htdocs/expensereport/index.php + * \brief Page liste des expensereports + */ + +require "../main.inc.php"; +dol_include_once("/expensereport/class/expensereport.class.php"); +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; + +$langs->load("companies"); +$langs->load("users"); +$langs->load("trips"); + +// Security check +$socid = $_GET["socid"]?$_GET["socid"]:''; +if ($user->societe_id) $socid=$user->societe_id; +$result = restrictedArea($user, 'expensereport','',''); + +$search_ref=GETPOST('search_ref'); + + +/* + * View + */ + +$html = new Form($db); +$formother = new FormOther($db); +$expensereporttmp=new ExpenseReport($db); + +llxHeader(); + +$max_year = 5; +$min_year = 5; + +$sortorder = $_GET["sortorder"]; +$sortfield = $_GET["sortfield"]; +$page = $_GET["page"]; + +$search_ref = $_GET['search_ref']; + +$month_start = $_GET['month_start']; +$year_start = $_GET['year_start']; +$month_end = $_GET['month_end']; +$year_end = $_GET['year_end']; + +$search_user = $_GET['search_user']; + +$search_state = $_GET['search_state']; + + +if (!$sortorder) $sortorder="DESC"; +if (!$sortfield) $sortfield="d.date_debut"; + +if ($page == -1) { + $page = 0 ; +} + +$limit = $conf->liste_limit; +$offset = $limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; + +$sql = "SELECT d.rowid, d.ref_number, d.total_ht, d.total_tva, d.total_ttc, d.fk_c_expensereport_statuts,"; +$sql.= " d.date_debut, d.date_fin,"; +$sql.= " u.rowid as id_user, u.firstname, u.lastname"; +$sql.= " FROM ".MAIN_DB_PREFIX."expensereport d\n"; +$sql.= " INNER JOIN ".MAIN_DB_PREFIX."user u ON d.fk_user_author = u.rowid\n"; + +// WHERE +if(!empty($search_ref)){ + $sql.= " WHERE d.ref_number LIKE '%".$db->escape($search_ref)."%'\n"; +}else{ + $sql.= " WHERE 1 = 1\n"; +} + +// DATE START +if ($month_start > 0) { + if ($year_start > 0) { + if($month_end > 0) { + if($year_end > 0) { + $sql.= " AND date_format(d.date_debut, '%Y-%m') >= '$year_start-$month_start'"; + $sql.= " AND date_format(d.date_fin, '%Y-%m') <= '$year_end-$month_end'"; + } else { + $sql.= " AND date_format(d.date_debut, '%Y-%m') >= '$year_start-$month_start'"; + $sql.= " AND date_format(d.date_fin, '%m') <= '$month_end'"; + } + } else { + if($year_end > 0) { + $sql.= " AND date_format(d.date_debut, '%Y-%m') >= '$year_start-$month_start'"; + $sql.= " AND date_format(d.date_fin, '%Y') <= '$year_end'"; + } else { + $sql.= " AND date_format(d.date_debut, '%Y-%m') >= '$year_start-$month_start'"; + } + } + } else { + $sql.= " AND date_format(d.date_debut, '%m') >= '$month_start'"; + } +} else { + if ($year_start > 0) { + if($month_end > 0) { + if($year_end > 0) { + $sql.= " AND date_format(d.date_debut, '%Y') >= '$year_start'"; + $sql.= " AND date_format(d.date_fin, '%Y-%m') <= '$year_end-$month_end'"; + } else { + $sql.= " AND date_format(d.date_debut, '%Y') >= '$year_start'"; + $sql.= " AND date_format(d.date_fin, '%m') <= '$month_end'"; + } + } else { + if($year_end > 0) { + $sql.= " AND date_format(d.date_debut, '%Y') >= '$year_start'"; + $sql.= " AND date_format(d.date_fin, '%Y') <= '$year_end'"; + } else { + $sql.= " AND date_format(d.date_debut, '%Y') >= '$year_start'"; + } + } + } else { + if($month_end > 0) { + if($year_end > 0) { + $sql.= " AND date_format(d.date_debut, '%Y') >= '$year_start'"; + $sql.= " AND date_format(d.date_fin, '%Y-%m') <= '$year_end-$month_end'"; + } else { + $sql.= " AND date_format(d.date_debut, '%Y') >= '$year_start'"; + $sql.= " AND date_format(d.date_fin, '%m') <= '$month_end'"; + } + } else { + if($year_end > 0) { + $sql.= " AND date_format(d.date_debut, '%Y') >= '$year_start'"; + $sql.= " AND date_format(d.date_fin, '%Y') <= '$year_end'"; + } + } + } +} + +if(!empty($search_user) && $search_user != -1) { + $sql.= " AND d.fk_user_author = '$search_user'\n"; +} + +if(!empty($search_state)) { + $sql.= " AND d.fk_c_expensereport_statuts = '$search_state'\n"; +} + +// RESTRICT RIGHTS +if (empty($user->rights->expensereport->readall) && empty($user->rights->expensereport->lire_tous)){ + $sql.= " AND d.fk_user_author = '{$user->id}'\n"; +} + +// ORDER +$sql.= " ORDER BY $sortfield $sortorder " . $db->plimit( $limit + 1 ,$offset); + +if($_GET['debug']=='ok'){ + var_dump("
",$sql,"
"); exit(); +} + +//print $sql; +$resql=$db->query($sql); +if ($resql) +{ + $num = $db->num_rows($resql); + + $i = 0; + print_barre_liste($langs->trans("ListTripsAndExpenses"), $page, $_SERVER["PHP_SELF"],$param,$sortfield,$sortorder,'',$num,$nbtotalofrecords); + + print '
'."\n"; + print ''; + print ""; + print_liste_field_titre($langs->trans("Ref"),$_SERVER["PHP_SELF"],"d.rowid","",$param,'',$sortfield,$sortorder); + print_liste_field_titre($langs->trans("DateStart"),$_SERVER["PHP_SELF"],"d.date_debut","",$param,'align="center"',$sortfield,$sortorder); + print_liste_field_titre($langs->trans("DateEnd"),$_SERVER["PHP_SELF"],"d.date_fin","",$param,'align="center"',$sortfield,$sortorder); + print_liste_field_titre($langs->trans("Person"),$_SERVER["PHP_SELF"],"u.lastname","",$param,'',$sortfield,$sortorder); + print_liste_field_titre($langs->trans("TotalHT"),$_SERVER["PHP_SELF"],"d.total_ht","",$param,'align="right"',$sortfield,$sortorder); + print_liste_field_titre($langs->trans("TotalVAT"),$_SERVER["PHP_SELF"],"d.total_tva","",$param,'align="right"',$sortfield,$sortorder); + print_liste_field_titre($langs->trans("TotalTTC"),$_SERVER["PHP_SELF"],"d.total_ttc","",$param,'align="right"',$sortfield,$sortorder); + print_liste_field_titre($langs->trans("Statut"),$_SERVER["PHP_SELF"],"","",$param,'align="right"',$sortfield,$sortorder); + print_liste_field_titre(); + print "\n"; + + // FILTRES + print ''; + print ''; + + // Date end + print ''; + + // User + if ($user->rights->expensereport->readall || $user->rights->expensereport->lire_tous){ + print ''; + } else { + print ''; + } + + + print ''; + + print ''; + + print '"; + + // Status + print ''; + print '"; + + print "\n"; + + $var=true; + + $total_total_ht = 0; + $total_total_ttc = 0; + $total_total_tva = 0; + + if($num>0) + { + while ($i < $num) + { + $objp = $db->fetch_object($resql); + + $var=!$var; + print ""; + print ''; + print ''; + print ''; + print ''; + /*print ''; + print ''; + print ''; + */ + print ''; + print ''; + print ''; + + $expensereporttmp->status=$objp->statut; + print ''; + print "\n"; + + $total_total_ht = $total_total_ht + $objp->total_ht; + $total_total_tva = $total_total_tva + $objp->total_tva; + $total_total_ttc = $total_total_ttc + $objp->total_ttc; + + $i++; + } + + print ''; + print ''; + /* + print ''; + print ''; + print ''; + */ + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + } + else + { + print ''; + } + print "
'; + print ''; + + // Date start + print ''; + print ''; + $formother->select_year($year_start,'year_start',1, $min_year, $max_year); + print ''; + print ''; + $formother->select_year($year_end,'year_end',1, $min_year, $max_year); + print ''; + $html->select_users($search_user,"search_user",1,"",0,''); + print '   '; + print "'; + select_expensereport_statut($search_state,'search_state'); + print ''; + print ' '; + print "
'.img_object($langs->trans("ShowTrip"),"trip").' '.$objp->ref_number.''.($objp->date_debut > 0 ? dol_print_date($objp->date_debut, 'day') : '').''.($objp->date_fin > 0 ? dol_print_date($objp->date_fin, 'day') : '').''.img_object($langs->trans("ShowUser"),"user").' '.dolGetFirstLastname($objp->firstname, $objp->lastname).''.price($objp->total_tva, '', $langs, 0, 'MT', 0, $conf->currency).''.price($objp->total_ht, '', $langs, 0, 'MT', 0, $conf->currency).''.price($objp->total_ttc, '', $langs, 0, 'MT', 0, $conf->currency).''.price($objp->total_ht).''.price($objp->total_tva).''.price($objp->total_ttc).''.$expensereporttmp->getLibStatut(5).'
'.$langs->trans("Total").''.price($total_total_tva, '', $langs, 0, 'MT', 0, $conf->currency).''.price($total_total_ht, '', $langs, 0, 'MT', 0, $conf->currency).''.price($total_total_ttc, '', $langs, 0, 'MT', 0, $conf->currency).''.$total_total_ht.''.$total_total_tva.''.$total_total_ttc.'
'.$langs->trans("NoRecordFound").'
"; + + print "
"; + + print '
'; + print 'Ajouter une note de frais'; + print '
'; + + $db->free($resql); +} +else +{ + dol_print_error($db); +} + + +llxFooter(); + +$db->close(); diff --git a/htdocs/expensereport/stats/index.php b/htdocs/expensereport/stats/index.php new file mode 100755 index 00000000000..07843985b00 --- /dev/null +++ b/htdocs/expensereport/stats/index.php @@ -0,0 +1,297 @@ + + * Copyright (c) 2004-2012 Laurent Destailleur + * Copyright (C) 2012 Marcos García + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/expensereport/stats/index.php + * \ingroup expensereport + * \brief Page for statistics of module trips and expenses + */ + +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/dolgraph.class.php'; +require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereportstats.class.php'; + +$langs->load("trips"); + +$WIDTH=DolGraph::getDefaultGraphSizeForStats('width'); +$HEIGHT=DolGraph::getDefaultGraphSizeForStats('height'); + +$userid=GETPOST('userid','int'); +$socid=GETPOST('socid','int'); if ($socid < 0) $socid=0; +$id = GETPOST('id','int'); + +// Security check +if ($user->societe_id > 0) +{ + $action = ''; + $socid = $user->societe_id; +} +if ($user->societe_id) $socid=$user->societe_id; +$result = restrictedArea($user, 'expensereport', $id,''); + +$nowyear=strftime("%Y", dol_now()); +$year = GETPOST('year')>0?GETPOST('year'):$nowyear; +//$startyear=$year-2; +$startyear=$year-1; +$endyear=$year; + +$mode=GETPOST("mode")?GETPOST("mode"):'customer'; + + +/* + * View + */ + +$form=new Form($db); + +llxHeader(); + +$title=$langs->trans("TripsAndExpensesStatistics"); +$dir=$conf->expensereport->dir_temp; + +print_fiche_titre($title, $mesg); + +dol_mkdir($dir); + +$stats = new ExpenseReportStats($db, $socid, $userid); + + +// Build graphic number of object +// $data = array(array('Lib',val1,val2,val3),...) +//print "$endyear, $startyear"; +$data = $stats->getNbByMonthWithPrevYear($endyear,$startyear); +//var_dump($data); + +$filenamenb = $dir."/tripsexpensesnbinyear-".$year.".png"; +$fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=tripsexpensesstats&file=tripsexpensesnbinyear-'.$year.'.png'; + +$px1 = new DolGraph(); +$mesg = $px1->isGraphKo(); +if (! $mesg) +{ + $px1->SetData($data); + $px1->SetPrecisionY(0); + $i=$startyear;$legend=array(); + while ($i <= $endyear) + { + $legend[]=$i; + $i++; + } + $px1->SetLegend($legend); + $px1->SetMaxValue($px1->GetCeilMaxValue()); + $px1->SetWidth($WIDTH); + $px1->SetHeight($HEIGHT); + $px1->SetYLabel($langs->trans("Number")); + $px1->SetShading(3); + $px1->SetHorizTickIncrement(1); + $px1->SetPrecisionY(0); + $px1->mode='depth'; + $px1->SetTitle($langs->trans("NumberByMonth")); + + $px1->draw($filenamenb,$fileurlnb); +} + +// Build graphic amount of object +$data = $stats->getAmountByMonthWithPrevYear($endyear,$startyear); +//var_dump($data); +// $data = array(array('Lib',val1,val2,val3),...) + +$filenameamount = $dir."/tripsexpensesamountinyear-".$year.".png"; +$fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=tripsexpensesstats&file=tripsexpensesamountinyear-'.$year.'.png'; + +$px2 = new DolGraph(); +$mesg = $px2->isGraphKo(); +if (! $mesg) +{ + $px2->SetData($data); + $i=$startyear;$legend=array(); + while ($i <= $endyear) + { + $legend[]=$i; + $i++; + } + $px2->SetLegend($legend); + $px2->SetMaxValue($px2->GetCeilMaxValue()); + $px2->SetMinValue(min(0,$px2->GetFloorMinValue())); + $px2->SetWidth($WIDTH); + $px2->SetHeight($HEIGHT); + $px2->SetYLabel($langs->trans("Amount")); + $px2->SetShading(3); + $px2->SetHorizTickIncrement(1); + $px2->SetPrecisionY(0); + $px2->mode='depth'; + $px2->SetTitle($langs->trans("AmountTotal")); + + $px2->draw($filenameamount,$fileurlamount); +} + + +$data = $stats->getAverageByMonthWithPrevYear($endyear, $startyear); + +if (!$user->rights->societe->client->voir || $user->societe_id) +{ + $filename_avg = $dir.'/ordersaverage-'.$user->id.'-'.$year.'.png'; + if ($mode == 'customer') $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersaverage-'.$user->id.'-'.$year.'.png'; + if ($mode == 'supplier') $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersaverage-'.$user->id.'-'.$year.'.png'; +} +else +{ + $filename_avg = $dir.'/ordersaverage-'.$year.'.png'; + if ($mode == 'customer') $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstats&file=ordersaverage-'.$year.'.png'; + if ($mode == 'supplier') $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersaverage-'.$year.'.png'; +} + +$px3 = new DolGraph(); +$mesg = $px3->isGraphKo(); +if (! $mesg) +{ + $px3->SetData($data); + $i = $startyear;$legend=array(); + while ($i <= $endyear) + { + $legend[]=$i; + $i++; + } + $px3->SetLegend($legend); + $px3->SetYLabel($langs->trans("AmountAverage")); + $px3->SetMaxValue($px3->GetCeilMaxValue()); + $px3->SetMinValue($px3->GetFloorMinValue()); + $px3->SetWidth($WIDTH); + $px3->SetHeight($HEIGHT); + $px3->SetShading(3); + $px3->SetHorizTickIncrement(1); + $px3->SetPrecisionY(0); + $px3->mode='depth'; + $px3->SetTitle($langs->trans("AmountAverage")); + + $px3->draw($filename_avg,$fileurl_avg); +} + + +// Show array +$data = $stats->getAllByYear(); +$arrayyears=array(); +foreach($data as $val) { + $arrayyears[$val['year']]=$val['year']; +} +if (! count($arrayyears)) $arrayyears[$nowyear]=$nowyear; + + +$h=0; +$head = array(); +$head[$h][0] = DOL_URL_ROOT . '/compta/expensereport/stats/index.php'; +$head[$h][1] = $langs->trans("ByMonthYear"); +$head[$h][2] = 'byyear'; +$h++; + +complete_head_from_modules($conf,$langs,null,$head,$h,'trip_stats'); + +dol_fiche_head($head,'byyear',$langs->trans("Statistics")); + + +print '
'; + + +// Show filter box +print '
'; +print ''; +print ''; +print ''; +// Company +/* +print ''; +*/ +// User +print ''; +// Year +print ''; +print ''; +print '
'.$langs->trans("Filter").'
'.$langs->trans("ThirdParty").''; +$filter=''; +print $form->select_company($socid,'socid',$filter,1,1); +print '
'.$langs->trans("User").''; +print $form->select_dolusers($userid,'userid',1); +print '
'.$langs->trans("Year").''; +if (! in_array($year,$arrayyears)) $arrayyears[$year]=$year; +arsort($arrayyears); +print $form->selectarray('year',$arrayyears,$year,0); +print '
'; +print '
'; +print '

'; + +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +$oldyear=0; +foreach ($data as $val) +{ + $year = $val['year']; + while ($year && $oldyear > $year+1) + { // If we have empty year + $oldyear--; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + } + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + $oldyear=$year; +} + +print '
'.$langs->trans("Year").''.$langs->trans("Number").''.$langs->trans("AmountTotal").''.$langs->trans("AmountAverage").'
'.$oldyear.'000
'.$year.''.$val['nb'].''.price(price2num($val['total'],'MT'),1).''.price(price2num($val['avg'],'MT'),1).'
'; + + +print '
'; + + +// Show graphs +print '
'; +if ($mesg) { print $mesg; } +else { + print $px1->show(); + print "
\n"; + print $px2->show(); + print "
\n"; + print $px3->show(); +} +print '
'; + + +print '
'; +print '
'; + + +dol_fiche_end(); + + +llxFooter(); + +$db->close(); diff --git a/htdocs/expensereport/synchro_compta.php b/htdocs/expensereport/synchro_compta.php new file mode 100755 index 00000000000..3f94da6eb1b --- /dev/null +++ b/htdocs/expensereport/synchro_compta.php @@ -0,0 +1,196 @@ +load("companies"); +$langs->load("users"); +$langs->load("trips"); +$langs->load("banks"); + +$idAccount=isset($_GET["account"])?$_GET["account"]:$_POST["account"]; + +if ($_GET["action"] == 'confirm_ndf_to_account' && $_GET["confirm"] == "yes"): + + $idTrip = $_GET['idTrip']; + + $expensereport = new ExpenseReport($db); + $expensereport->fetch($idTrip,$user); + + $datePaiement = explode("-",$expensereport->date_paiement); + + $dateop = dol_mktime(12,0,0,$datePaiement[1],$datePaiement[2],$datePaiement[0]); + $operation = $expensereport->code_paiement; + $label = "Règlement ".$expensereport->ref_number; + $amount = - price2num($expensereport->total_ttc); + $num_chq = ''; + $cat1 = ''; + + $user = new User($db); + $user->fetch($expensereport->fk_user_paid); + + $acct=new Account($db,$idAccount); + $insertid = $acct->addline($dateop, $operation, $label, $amount, $num_chq, $cat1, $user); + + if ($insertid > 0): + $sql = " UPDATE ".MAIN_DB_PREFIX."expensereport d"; + $sql.= " SET integration_compta = 1, fk_bank_account = $idAccount"; + $sql.= " WHERE rowid = $idTrip"; + $resql=$db->query($sql); + if($result): + Header("Location: synchro_compta.php?account=".$idAccount); + exit; + else: + dol_print_error($db); + endif; + else: + dol_print_error($db,$acct->error); + endif; +endif; + +if ($_GET["action"] == 'confirm_account_to_ndf' && $_GET["confirm"] == "yes"): + + $idTrip = $_GET['idTrip']; + + $expensereport = new ExpenseReport($db); + $expensereport->fetch($idTrip,$user); + + $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank"; + $sql.= " WHERE label LIKE '%".$expensereport->ref_number."%'"; + $resql=$db->query($sql); + if ($resql > 0): + $sql = " UPDATE ".MAIN_DB_PREFIX."expensereport d"; + $sql.= " SET integration_compta = 0, fk_bank_account = 0"; + $sql.= " WHERE rowid = $idTrip"; + $resql=$db->query($sql); + if($result): + Header("Location: synchro_compta.php?account=".$idAccount); + exit; + else: + dol_print_error($db); + endif; + else: + dol_print_error($db); + endif; +endif; + + +/* + * Actions + */ + +llxHeader(); + +$html = new Form($db); + +$submit = isset($_POST['submit'])?true:false; +$idAccount=isset($_GET["account"])?$_GET["account"]:$_POST["account"]; + +print_fiche_titre($langs->trans("TripSynch")); + + +dol_fiche_head(''); + + +if ($_GET["action"] == 'ndfTOaccount'): + $idTrip = $_GET['idTrip']; + $ret=$html->form_confirm("synchro_compta.php?idTrip=".$idTrip."&account=".$idAccount,$langs->trans("ndfToAccount"),$langs->trans("ConfirmNdfToAccount"),"confirm_ndf_to_account","","",1); + if ($ret == 'html') print '
'; +endif; + +if ($_GET["action"] == 'accountTOndf'): + $idTrip = $_GET['idTrip']; + $ret=$html->form_confirm("synchro_compta.php?idTrip=".$idTrip."&account=".$idAccount,$langs->trans("AccountToNdf"),$langs->trans("ConfirmAccountToNdf"),"confirm_account_to_ndf","","",1); + if ($ret == 'html') print '
'; +endif; + +if(empty($submit) && empty($idAccount)): + + print "
"; + print 'Choix du compte  '; + print $html->select_comptes($_POST['account'],'account',0,'',1); + print ' '; + print "
"; + +else: + + print "
"; + print 'Choix du compte  '; + print $html->select_comptes($idAccount,'account',0,'',1); + print ' '; + print "
"; + + $sql = "SELECT d.fk_bank_account, d.ref_number, d.rowid, d.date_valide, d.fk_user_author, d.total_ttc, d.integration_compta, d.fk_c_expensereport_statuts"; + $sql.= " ,CONCAT(u.firstname,' ',u.lastname) as declarant_NDF"; + $sql.= " FROM ".MAIN_DB_PREFIX."expensereport d"; + $sql.= " INNER JOIN ".MAIN_DB_PREFIX."user u ON d.fk_user_author = u.rowid"; + $sql.= " WHERE d.fk_c_expensereport_statuts = 6"; + $sql.= " ORDER BY d.date_valide DESC"; + + $resql=$db->query($sql); + if ($resql): + $num = $db->num_rows($resql); $i = 0; + if($num>0): + + $account=new Account($db); + $account->fetch($idAccount); + + print '
'; + + print ""; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + while($i<$num): + $objp = $db->fetch_object($resql); + $var=!$var; + print ""; + print ''; + print ''; + print ''; + print ''; + + if($objp->integration_compta): + print ''; + else: + print ''; + endif; + + print ''; + + if($objp->integration_compta): + print ''; + else: + print ''; + endif; + + print ""; + $i++; + endwhile; + + print "
'.$langs->trans("Ref").''.$langs->trans("DateValidation").''.$langs->trans("USER_AUTHOR").''.$langs->trans("TotalTTC").'ActionsCompteInt.
'.$objp->ref_number.''.dol_print_date($db->jdate($objp->date_valide),'day').''.img_object($langs->trans("ShowUser"),"user").' '.$objp->declarant_NDF.''.$objp->total_ttc.' '.$langs->trans("EURO").'Compte vers NDFNDF vers Compte'.$account->label.'Intégration OKIntégration Non OK
"; + + else: + print '
'.$langs->trans("AucuneTripToSynch").'
'; + endif; + + $db->free($resql); + else: + dol_print_error($db); + endif; + +endif; + +dol_fiche_end(); + +llxFooter(); + +$db->close(); \ No newline at end of file diff --git a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql index 1f61a1a5a9b..0acea91984b 100755 --- a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql +++ b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql @@ -111,3 +111,77 @@ ALTER TABLE llx_commande_fournisseur_dispatch ADD COLUMN sellby date DEFAULT NUL ALTER TABLE llx_stock_mouvement ADD COLUMN batch varchar(30) DEFAULT NULL; ALTER TABLE llx_stock_mouvement ADD COLUMN eatby date DEFAULT NULL; ALTER TABLE llx_stock_mouvement ADD COLUMN sellby date DEFAULT NULL; + + + + +CREATE TABLE llx_expensereport ( + rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY, + ref_number varchar(50) NOT NULL, + entity integer DEFAULT 1 NOT NULL, -- multi company id + ref_number_int integer DEFAULT NULL, + ref_ext integer, + total_ht double(24,8) DEFAULT 0, + total_tva double(24,8) DEFAULT 0, + localtax1 double(24,8) DEFAULT 0, -- amount total localtax1 + localtax2 double(24,8) DEFAULT 0, -- amount total localtax2 + total_ttc double(24,8) DEFAULT 0, + date_debut date NOT NULL, + date_fin date NOT NULL, + date_paiement datetime, + date_valide datetime, + date_create datetime NOT NULL, + fk_user_author integer NOT NULL, + fk_user_modif integer DEFAULT NULL, + fk_user_validator integer DEFAULT NULL, + fk_c_expensereport_statuts integer NOT NULL, -- 1=brouillon, 2=validé (attente approb), 4=annulé, 5=approuvé, 6=payed, 99=refusé + fk_c_paiement integer DEFAULT NULL, + note text, + note_private text, + fk_user_valid integer DEFAULT NULL, + fk_user_paid integer DEFAULT NULL, + detail_refuse varchar(255) DEFAULT NULL, + date_cancel datetime, + date_refuse datetime, + detail_cancel varchar(255) DEFAULT NULL, + fk_user_cancel integer DEFAULT NULL, + fk_user_refuse integer DEFAULT NULL, + integration_compta integer DEFAULT NULL, + fk_bank_account integer DEFAULT NULL, + model_pdf varchar(50) DEFAULT NULL +) ENGINE=innodb; + + + + +CREATE TABLE llx_expensereport_det +( + rowid integer PRIMARY KEY NOT NULL, + fk_expensereport integer NOT NULL, + fk_c_type_fees integer NOT NULL, + fk_projet integer NOT NULL, + fk_c_tva integer NOT NULL, + comments text NOT NULL, + product_type integer DEFAULT -1, + qty real NOT NULL, + value_unit real NOT NULL, + remise_percent real, + tva_tx double(6,3), -- Vat rat + localtax1_tx double(6,3) DEFAULT 0, -- localtax1 rate + localtax1_type varchar(10) NULL, -- localtax1 type + localtax2_tx double(6,3) DEFAULT 0, -- localtax2 rate + localtax2_type varchar(10) NULL, -- localtax2 type + total_ht double(24,8) DEFAULT 0 NOT NULL, + total_tva double(24,8) DEFAULT 0 NOT NULL, + total_localtax1 double(24,8) DEFAULT 0, -- Total LocalTax1 for total quantity of line + total_localtax2 double(24,8) DEFAULT 0, -- total LocalTax2 for total quantity of line + total_ttc double(24,8) DEFAULT 0 NOT NULL, + date date NOT NULL, + info_bits integer DEFAULT 0, -- TVA NPR ou non + special_code integer DEFAULT 0, -- code pour les lignes speciales + rang integer DEFAULT 0, -- position of line + import_key varchar(14) +) ENGINE=innodb; + + + diff --git a/htdocs/install/mysql/tables/llx_expensereport.sql b/htdocs/install/mysql/tables/llx_expensereport.sql new file mode 100755 index 00000000000..6fcdfa92291 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_expensereport.sql @@ -0,0 +1,54 @@ +-- ============================================================================ +-- Copyright (C) 2015 Laurent Destailleur +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . +-- +-- ============================================================================ + +CREATE TABLE llx_expensereport ( + rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY, + ref_number varchar(50) NOT NULL, + entity integer DEFAULT 1 NOT NULL, -- multi company id + ref_number_int integer DEFAULT NULL, + ref_ext integer, + total_ht double(24,8) DEFAULT 0, + total_tva double(24,8) DEFAULT 0, + localtax1 double(24,8) DEFAULT 0, -- amount total localtax1 + localtax2 double(24,8) DEFAULT 0, -- amount total localtax2 + total_ttc double(24,8) DEFAULT 0, + date_debut date NOT NULL, + date_fin date NOT NULL, + date_paiement datetime, + date_valide datetime, + date_create datetime NOT NULL, + fk_user_author integer NOT NULL, + fk_user_modif integer DEFAULT NULL, + fk_user_validator integer DEFAULT NULL, + fk_c_expensereport_statuts integer NOT NULL, -- 1=brouillon, 2=validé (attente approb), 4=annulé, 5=approuvé, 6=payed, 99=refusé + fk_c_paiement integer DEFAULT NULL, + note text, + note_private text, + fk_user_valid integer DEFAULT NULL, + fk_user_paid integer DEFAULT NULL, + detail_refuse varchar(255) DEFAULT NULL, + date_cancel datetime, + date_refuse datetime, + detail_cancel varchar(255) DEFAULT NULL, + fk_user_cancel integer DEFAULT NULL, + fk_user_refuse integer DEFAULT NULL, + integration_compta integer DEFAULT NULL, + fk_bank_account integer DEFAULT NULL, + model_pdf varchar(50) DEFAULT NULL +) ENGINE=innodb; + diff --git a/htdocs/install/mysql/tables/llx_expensereport_det.sql b/htdocs/install/mysql/tables/llx_expensereport_det.sql new file mode 100644 index 00000000000..644668f5713 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_expensereport_det.sql @@ -0,0 +1,46 @@ +-- ============================================================================ +-- Copyright (C) 2015 Laurent Destailleur +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . +-- +-- ============================================================================ + +CREATE TABLE llx_expensereport_det +( + rowid integer PRIMARY KEY NOT NULL, + fk_expensereport integer NOT NULL, + fk_c_type_fees integer NOT NULL, + fk_projet integer NOT NULL, + fk_c_tva integer NOT NULL, + comments text NOT NULL, + product_type integer DEFAULT -1, + qty real NOT NULL, + value_unit real NOT NULL, + remise_percent real, + tva_tx double(6,3), -- Vat rat + localtax1_tx double(6,3) DEFAULT 0, -- localtax1 rate + localtax1_type varchar(10) NULL, -- localtax1 type + localtax2_tx double(6,3) DEFAULT 0, -- localtax2 rate + localtax2_type varchar(10) NULL, -- localtax2 type + total_ht double(24,8) DEFAULT 0 NOT NULL, + total_tva double(24,8) DEFAULT 0 NOT NULL, + total_localtax1 double(24,8) DEFAULT 0, -- Total LocalTax1 for total quantity of line + total_localtax2 double(24,8) DEFAULT 0, -- total LocalTax2 for total quantity of line + total_ttc double(24,8) DEFAULT 0 NOT NULL, + date date NOT NULL, + info_bits integer DEFAULT 0, -- TVA NPR ou non + special_code integer DEFAULT 0, -- code pour les lignes speciales + rang integer DEFAULT 0, -- position of line + import_key varchar(14) +) ENGINE=innodb; \ No newline at end of file diff --git a/htdocs/install/mysql/tables/llx_facturedet.sql b/htdocs/install/mysql/tables/llx_facturedet.sql index 2c01234f4b9..d663adf4e1c 100644 --- a/htdocs/install/mysql/tables/llx_facturedet.sql +++ b/htdocs/install/mysql/tables/llx_facturedet.sql @@ -30,7 +30,7 @@ create table llx_facturedet fk_product integer NULL, -- Doit pouvoir etre nul pour ligne detail sans produits label varchar(255) DEFAULT NULL, description text, - tva_tx double(6,3), -- Taux tva produit/service (exemple 19.6) + tva_tx double(6,3), -- Vat rate (example 20%) localtax1_tx double(6,3) DEFAULT 0, -- localtax1 rate localtax1_type varchar(10) NULL, -- localtax1 type localtax2_tx double(6,3) DEFAULT 0, -- localtax2 rate @@ -43,8 +43,8 @@ create table llx_facturedet price double(24,8), -- Deprecated (Do not use) total_ht double(24,8), -- Total HT de la ligne toute quantite et incluant remise ligne et globale total_tva double(24,8), -- Total TVA de la ligne toute quantite et incluant remise ligne et globale - total_localtax1 double(24,8) DEFAULT 0, -- Total LocalTax1 for total quantity of line - total_localtax2 double(24,8) DEFAULT 0, -- total LocalTax2 for total quantity of line + total_localtax1 double(24,8) DEFAULT 0, -- Total LocalTax1 for total quantity of line + total_localtax2 double(24,8) DEFAULT 0, -- total LocalTax2 for total quantity of line total_ttc double(24,8), -- Total TTC de la ligne toute quantite et incluant remise ligne et globale product_type integer DEFAULT 0, date_start datetime DEFAULT NULL, -- date debut si service @@ -55,8 +55,8 @@ create table llx_facturedet fk_product_fournisseur_price integer DEFAULT NULL, -- reference of supplier price when line was added (may be used to update buy_price_ht current price when future invoice will be created) fk_code_ventilation integer DEFAULT 0 NOT NULL, - special_code integer UNSIGNED DEFAULT 0, -- code pour les lignes speciales - rang integer DEFAULT 0, -- ordre d'affichage + special_code integer DEFAULT 0, -- code pour les lignes speciales + rang integer DEFAULT 0, -- position of line import_key varchar(14), situation_percent real, -- % progression of lines invoicing diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index ed39be9426c..345f2342244 100755 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -493,10 +493,14 @@ Module600Name=Notifications Module600Desc=Send EMail notifications on some Dolibarr business events to third-party contacts (setup defined on each thirdparty) Module700Name=Donations Module700Desc=Donation management +Module770Name=Expense Report +Module770Desc=Management and claim expense reports (transportation, meal, ...) Module1200Name=Mantis Module1200Desc=Mantis integration Module1400Name=Accounting Module1400Desc=Accounting management (double parties) +Module1520Name=Document Generation +Module1520Desc=Mass mail document generation Module1780Name=Categories Module1780Desc=Category management (products, suppliers and customers) Module2000Name=WYSIWYG editor @@ -711,6 +715,13 @@ Permission538=Export services Permission701=Read donations Permission702=Create/modify donations Permission703=Delete donations +Permission771=Read expense reports (own and his subordinates) +Permission772=Create/modify expense reports +Permission773=Delete expense reports +Permission774=Read all expense reports (even for user not subordinates) +Permission775=Approve expense reports +Permission776=Pay expense reports +Permission779=Export expense reports Permission1001=Read stocks Permission1002=Create/modify warehouses Permission1003=Delete warehouses diff --git a/htdocs/langs/en_US/trips.lang b/htdocs/langs/en_US/trips.lang index 64adbeb0dd6..e34f58715d8 100644 --- a/htdocs/langs/en_US/trips.lang +++ b/htdocs/langs/en_US/trips.lang @@ -1,22 +1,127 @@ # Dolibarr language file - Source file is en_US - trips -Trip=Trip -Trips=Trips -TripsAndExpenses=Trips and expenses -TripsAndExpensesStatistics=Trips and expenses statistics -TripCard=Trip card -AddTrip=Create trip -ListOfTrips=List of trips +Trip=Expense report +Trips=Expense reports +TripsAndExpenses=Expenses reports +TripsAndExpensesStatistics=Expense reports statistics +TripCard=Expense report card +AddTrip=Create expense report +ListOfTrips=List of expense report ListOfFees=List of fees -NewTrip=New trip +NewTrip=New expense report CompanyVisited=Company/foundation visited Kilometers=Kilometers FeesKilometersOrAmout=Amount or kilometers -DeleteTrip=Delete trip -ConfirmDeleteTrip=Are you sure you want to delete this trip ? +DeleteTrip=Delete expense report +ConfirmDeleteTrip=Are you sure you want to delete this expense report ? +ListTripsAndExpenses=List of expense reports +ExpensesArea=Expense reports area +SearchATripAndExpense=Search an expense report +ClassifyRefunded=Classify 'Refunded' + +TripId=Id expense report +AnyOtherInThisListCanValidate=Person to inform for validation. +TripSociete=Information company +TripSalarie=Informations user +TripNDF=Informations expense report + +DeleteLine=Delete a ligne of the expense report +ConfirmDeleteLine=Are you sure you want to delete this line ? + TF_OTHER=Other TF_LUNCH=Lunch -TF_TRIP=Trip -ListTripsAndExpenses=List of trips and expenses -ExpensesArea=Trips and expenses area -SearchATripAndExpense=Search a trip and expense -ClassifyRefunded=Classify 'Refunded' \ No newline at end of file +TF_METRO=Metro +TF_TRAIN=Train +TF_BUS=Bus +TF_PEAGE=Toll +TF_ESSENCE=Fuel +TF_HOTEL=Hostel +TF_TAXI=Taxi + +ErrorDoubleDeclaration=ERREUR : Vous avez déclaré au moins une note de frais dans le même intervalle. +ListTripsAndExpenses=Liste des notes de frais +AucuneNDF=Il n'y a aucune note de frais déclarée correspondante à votre recherche! +AucuneLigne=Il n'y a aucune ligne de déclarée dans cette note de frais! +AddLine=Ajouter une ligne +AddLineMini=Ajouter +TotalHT=Montant HT +TotalTTC=Montant TTC +TotalTVA=Total TVA + +Date_DEBUT=Date de début période +Date_FIN=Date de fin période +ModePaiement=Mode de paiement +Note=Note +Project=Projet + +VALIDATOR=Utilisateur informé pour validation +VALIDOR=Validée par +AUTHOR=Enregistrée par +AUTHORPAIEMENT=Payée par +REFUSEUR=Refusée par +CANCEL_USER=Annulée par + +MOTIF_REFUS=Motif de refus +MOTIF_CANCEL=Motif d'annulation + +DATE_REFUS=Date du refus +DATE_CANCEL=Date annulation +DATE_VALIDE=Date de validation +DATE_PAIEMENT=Date de paiement +DATE_SAVE=Date d'enregistrement + +REFUSE=Refuse +TO_PAID=Pay +BROUILLONNER=Reopen +SendToValid=Sent to approve +ModifyInfoGen=Edit + +NOT_VALIDATOR=Vous n'êtes pas la personne habilitée à valider cette note de frais! +NOT_AUTHOR=Vous n'êtes pas l'auteur de cette note de frais, impossible de réaliser l'opération voulue! +NOT_VALIDOR=Vous n'êtes pas le valideur de cette note de frais, vous ne pouvez donc pas réaliser cette opération! +NotUserRightToView=Vous n'avez pas le droit d'afficher cette note de frais. + +RefuseTrip=Refuser une note de frais +ConfirmRefuseTrip=Êtes vous sûr de vouloir refuser cette note de frais ? + +ValideTrip=Valider une note de frais +ConfirmValideTrip=Êtes vous sûr de vouloir valider cette note de frais ? + +PaidTrip=Payer une note de frais +ConfirmPaidTrip=Êtes vous sûr de vouloir payer cette note de frais ? + +CancelTrip=Annuler une note de frais +ConfirmCancelTrip=Êtes vous sûr de vouloir annuler cette note de frais ? + +BrouillonnerTrip=Remettre une note de frais en brouillon +ConfirmBrouillonnerTrip=Êtes vous sûr de vouloir remettre cette note de frais en brouillon ? + +SaveTrip=Enregistrement de votre note de frais +ConfirmSaveTrip=Êtes vous sûr de vouloir enregistrer cette note de frais? (elle sera transmise par mail pour validation) + +INFOS_DATES=Infos Workflow +INFOS_NDF=Infos générales note de frais + +StatsTrip=Statistiques +Synchro_Compta=NDF <-> Compte + +TripSynch=Synchronisation : Notes de frais <-> Compte courant +TripToSynch=Notes de frais à intégrer dans la compta +AucuneTripToSynch=Aucune note de frais n'est en statut "Payée". +ViewAccountSynch=Voir le compte + +ConfirmNdfToAccount=Êtes-vous sûr de vouloir intégrer cette note de frais dans le compte courant? +ndfToAccount=Note de frais - Intégration + +ConfirmAccountToNdf=Êtes-vous sûr de vouloir retirer cette note de frais du compte courant? +AccountToNdf=Note de frais - Retrait + +LINE_NOT_ADDED=Ligne non ajoutée : +NO_PROJECT=Aucun projet sélectionné. +NO_DATE=Aucune date sélectionnée. +NO_PRICE=Aucun prix indiqué. + +TripForValid=à Valider +TripForPaid=à Payer +TripPaid=Payée + +NoTripsToExportCSV=No expense report to export for this period. diff --git a/htdocs/langs/fr_FR/expensereport.lang b/htdocs/langs/fr_FR/expensereport.lang new file mode 100755 index 00000000000..6af74164f2d --- /dev/null +++ b/htdocs/langs/fr_FR/expensereport.lang @@ -0,0 +1,137 @@ +# Dolibarr language file - fr_FR - trips +CHARSET=UTF-8 +Trip=Note de frais +Trips=Notes de frais +TripsAndExpenses=Notes de frais +TripId=Id note de frais +TripCard=Fiche note de frais +AddTrip=Ajouter note de frais +ListOfTrips=Liste des notes de frais +ListOfFees=Liste des notes de frais +NewTrip=Nouvelle note de frais +CancelAddTrip=Annuler +ExportTripCSV=Exporter en CSV +AnyOtherInThisListCanValidate=Toute personne dans la liste pourra valider. Le choix détermine qui sera informé. +TripSociete=Informations société +TripSalarie=Informations salarié +TripNDF=Informations note de frais + +DeleteTrip=Supprimer note de frais +ConfirmDeleteTrip=Êtes vous sûr de vouloir supprimer cette note de frais ? + +DeleteLine=Supprimer une ligne de la note de frais +ConfirmDeleteLine=Êtes vous sûr de vouloir supprimer cette ligne ? + +TF_OTHER=Autre +TF_LUNCH=Repas +TF_METRO=Métro +TF_TRAIN=Train +TF_RATP=Ratp +TF_BUS=Bus +TF_PEAGE=Péage +TF_ESSENCE=Essence +TF_SNCF=SNCF (Autre) +TF_HOTEL=Hôtel +TF_TRANSPORT=SNCF (Train) +TF_TAXI=Taxi + +ErrorDoubleDeclaration=ERREUR : Vous avez déclaré au moins une note de frais dans le même intervalle. +ListTripsAndExpenses=Liste des notes de frais +AucuneNDF=Il n'y a aucune note de frais déclarée correspondante à votre recherche! +AucuneLigne=Il n'y a aucune ligne de déclarée dans cette note de frais! +AddLine=Ajouter une ligne +AddLineMini=Ajouter +TotalHT=Montant HT +TotalTTC=Montant TTC +TotalTVA=Total TVA + +Date_DEBUT=Date de début période +Date_FIN=Date de fin période +ModePaiement=Mode de paiement +Note=Note +Project=Projet + +VALIDATOR=Utilisateur informé pour validation +VALIDOR=Validée par +AUTHOR=Enregistrée par +AUTHORPAIEMENT=Payée par +REFUSEUR=Refusée par +CANCEL_USER=Annulée par + +MOTIF_REFUS=Motif de refus +MOTIF_CANCEL=Motif d'annulation + +DATE_REFUS=Date du refus +DATE_CANCEL=Date annulation +DATE_VALIDE=Date de validation +DATE_PAIEMENT=Date de paiement +DATE_SAVE=Date d'enregistrement + +VALIDATE=Valider +REFUSE=Refuser +CANCEL=Annuler +TO_PAID=Payer +BROUILLONNER=Remettre en brouillon +SendToValid=Envoyer en validation +ModifyInfoGen=Modifier les infos générales + +Module20130304Name=Notes de frais +Module20130304Desc=Gestion des notes de frais et déplacement (par ') + +NOT_VALIDATOR=Vous n'êtes pas la personne habilitée à valider cette note de frais! +NOT_AUTHOR=Vous n'êtes pas l'auteur de cette note de frais, impossible de réaliser l'opération voulue! +NOT_VALIDOR=Vous n'êtes pas le valideur de cette note de frais, vous ne pouvez donc pas réaliser cette opération! +NotUserRightToView=Vous n'avez pas le droit d'afficher cette note de frais. + +RefuseTrip=Refuser une note de frais +ConfirmRefuseTrip=Êtes vous sûr de vouloir refuser cette note de frais ? + +ValideTrip=Valider une note de frais +ConfirmValideTrip=Êtes vous sûr de vouloir valider cette note de frais ? + +PaidTrip=Payer une note de frais +ConfirmPaidTrip=Êtes vous sûr de vouloir payer cette note de frais ? + +CancelTrip=Annuler une note de frais +ConfirmCancelTrip=Êtes vous sûr de vouloir annuler cette note de frais ? + +BrouillonnerTrip=Remettre une note de frais en brouillon +ConfirmBrouillonnerTrip=Êtes vous sûr de vouloir remettre cette note de frais en brouillon ? + +SaveTrip=Enregistrement de votre note de frais +ConfirmSaveTrip=Êtes vous sûr de vouloir enregistrer cette note de frais? (elle sera transmise par mail pour validation) + +INFOS_DATES=Infos Workflow +INFOS_NDF=Infos générales note de frais + +EURO=€ +PriceUNITAIRE=Prix U. (TTC) + +StatsTrip=Statistiques +Synchro_Compta=NDF <-> Compte + +TripSynch=Synchronisation : Notes de frais <-> Compte courant +TripToSynch=Notes de frais à intégrer dans la compta +AucuneTripToSynch=Aucune note de frais n'est en statut "Payée". +ViewAccountSynch=Voir le compte + +ConfirmNdfToAccount=Êtes-vous sûr de vouloir intégrer cette note de frais dans le compte courant? +ndfToAccount=Note de frais - Intégration + +ConfirmAccountToNdf=Êtes-vous sûr de vouloir retirer cette note de frais du compte courant? +AccountToNdf=Note de frais - Retrait + +USER_AUTHOR=Auteur +PU=P.U. +Q=Q + +LINE_NOT_ADDED=Ligne non ajoutée : +NO_PROJECT=Aucun projet sélectionné. +NO_DATE=Aucune date sélectionnée. +NO_PRICE=Aucun prix indiqué. + +TripForValid=à Valider +TripForPaid=à Payer +TripPaid=Payée + +NoTripsToExportCSV=Il n'y a pas de notes de frais à exporter pour cette période. \ No newline at end of file From 4e6d5e1cd1d680365ffe1172ae8f6ed659293c0a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 14 Feb 2015 19:10:40 +0100 Subject: [PATCH 113/173] New: Add filter fields on the subscription list --- htdocs/adherents/cotisations.php | 136 +++++++++++++++++++++++-------- htdocs/adherents/list.php | 4 +- 2 files changed, 105 insertions(+), 35 deletions(-) diff --git a/htdocs/adherents/cotisations.php b/htdocs/adherents/cotisations.php index 160f47365fa..40d34f58881 100644 --- a/htdocs/adherents/cotisations.php +++ b/htdocs/adherents/cotisations.php @@ -32,6 +32,12 @@ $langs->load("members"); $filter=$_GET["filter"]; $statut=isset($_GET["statut"])?$_GET["statut"]:1; +$search_ref=GETPOST('search_ref'); +$search_lastname=GETPOST('search_lastname'); +$search_login=GETPOST('search_login'); +$search_note=GETPOST('search_note'); +$search_account=GETPOST('search_account','int'); +$search_amount=GETPOST('search_amount','int'); $sortfield = GETPOST("sortfield",'alpha'); $sortorder = GETPOST("sortorder",'alpha'); @@ -43,7 +49,6 @@ $pagenext = $page + 1; if (! $sortorder) { $sortorder="DESC"; } if (! $sortfield) { $sortfield="c.dateadh"; } -$msg=''; $date_select=isset($_GET["date_select"])?$_GET["date_select"]:$_POST["date_select"]; // Security check @@ -54,14 +59,27 @@ $result=restrictedArea($user,'adherent','','','cotisation'); * Actions */ +if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter")) // Both test are required to be compatible with all browsers +{ + $search=""; + $search_ref=""; + $search_lastname=""; + $search_firstname=""; + $search_login=""; + $search_note=""; + $search_amount=""; + $search_account=""; +} + /* * View */ +$form=new Form($db); + llxHeader('',$langs->trans("ListOfSubscriptions"),'EN:Module_Foundations|FR:Module_Adhérents|ES:Módulo_Miembros'); -if ($msg) print $msg.'
'; // List of subscriptions $sql = "SELECT d.rowid, d.login, d.firstname, d.lastname, d.societe,"; @@ -77,6 +95,31 @@ if (isset($date_select) && $date_select != '') { $sql.= " AND c.dateadh LIKE '".$date_select."%'"; } +if ($search_ref) +{ + if (is_numeric($search_ref)) $sql.= " AND (c.rowid = ".$db->escape($search_ref).")"; + else $sql.=" AND 1 = 2"; // Always wrong +} +if ($search_lastname) +{ + $sql.= " AND (d.firstname LIKE '%".$db->escape($search_lastname)."%' OR d.lastname LIKE '%".$db->escape($search_lastname)."%' OR d.societe LIKE '%".$db->escape($search_lastname)."%')"; +} +if ($search_login) +{ + $sql.= " AND d.login LIKE '%".$db->escape($search_login)."%'"; +} +if ($search_note) +{ + $sql.= " AND c.note LIKE '%".$db->escape($search_note)."%'"; +} +if ($search_account > 0) +{ + $sql.= " AND b.fk_account = ".$search_account; +} +if ($search_amount) +{ + $sql.=" AND c.cotisation = ".$db->escape($search_amount); +} $sql.= $db->order($sortfield,$sortorder); $sql.= $db->plimit($conf->liste_limit+1, $offset); @@ -90,10 +133,23 @@ if ($result) if (! empty($date_select)) $title.=' ('.$langs->trans("Year").' '.$date_select.')'; $param=""; - $param.="&statut=$statut&date_select=$date_select"; + $param.="&statut=$statut&date_select=$date_select"; + + if ($search_lastname) $param.="&search_lastname=".$search_lastname; + if ($search_login) $param.="&search_login=".$search_login; + if ($search_acount) $param.="&search_account=".$search_account; + if ($search_amount) $param.="&search_amount=".$search_amount; print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder,'',$num); + if ($sall) + { + print $langs->trans("Filter")." (".$langs->trans("Ref").", ".$langs->trans("Lastname").", ".$langs->trans("Firstname").", ".$langs->trans("EMail").", ".$langs->trans("Address")." ".$langs->trans("or")." ".$langs->trans("Town")."): ".$sall; + } + $param=""; + $param.="&statut=$statut&date_select=$date_select"; + + print '
'; print ''; print ''; @@ -107,9 +163,47 @@ if ($result) } print_liste_field_titre($langs->trans("Date"),$_SERVER["PHP_SELF"],"c.dateadh",$param,"",'align="center"',$sortfield,$sortorder); print_liste_field_titre($langs->trans("DateEnd"),$_SERVER["PHP_SELF"],"c.datef",$param,"",'align="center"',$sortfield,$sortorder); - print_liste_field_titre($langs->trans("Amount"),$_SERVER["PHP_SELF"],"c.cotisation",$param,"",'align="right"',$sortfield,$sortorder); + print_liste_field_titre($langs->trans("Amount"),$_SERVER["PHP_SELF"],"c.cotisation",$param,"",'colspan="2" align="right"',$sortfield,$sortorder); print "\n"; + + // Line for filters fields + print ''; + + print ''; + + print ''; + + print ''; + + print ''; + + if (! empty($conf->banque->enabled)) + { + print ''; + } + + print ''; + + print ''; + + print ''; + + print "\n"; + + // Static objects $cotisation=new Cotisation($db); $adherent=new Adherent($db); @@ -133,11 +227,6 @@ if ($result) $var=!$var; - if ($allowinsertbankafter && ! $objp->fk_account && ! empty($conf->banque->enabled) && $objp->cotisation) - { - print ""; - print ''; - } print ""; // Ref @@ -167,19 +256,6 @@ if ($result) else { print "\n"; } } @@ -191,13 +267,10 @@ if ($result) print '\n"; // Price - print ''; + print ''; print ""; - if ($allowinsertbankafter && ! $objp->fk_account && ! empty($conf->banque->enabled) && $objp->cotisation) - { - print "\n"; - } + $i++; } @@ -214,13 +287,11 @@ if ($result) } print ''; print ''; - print "\n"; + print '\n"; print "\n"; print "
'; + print ''; + print ''; + print ''; + print ''; + print $form->select_comptes($search_account, 'search_account', 0, '', 1); + print '  '; + print ''; + print ''; + print ''; + print ' '; + print ''; + print '
"; - if ($allowinsertbankafter && $objp->cotisation) - { - print ''; - print ''; - $form->select_comptes('','accountid',0,'',1); - print '
'; - $form->select_types_paiements('','paymenttypeid'); - print ''; - } - else - { - print ' '; - } print "
'.dol_print_date($db->jdate($objp->datef),'day')."'.price($objp->cotisation).''.price($objp->cotisation).'
  ".price($total)."'.price($total)."
"; - print "
\n"; - - + print ''; } else { @@ -228,6 +299,5 @@ else } -$db->close(); - llxFooter(); +$db->close(); diff --git a/htdocs/adherents/list.php b/htdocs/adherents/list.php index b88a39c76af..0bb34d14153 100644 --- a/htdocs/adherents/list.php +++ b/htdocs/adherents/list.php @@ -233,7 +233,7 @@ if ($resql) print_liste_field_titre($langs->trans("Action"),$_SERVER["PHP_SELF"],"",$param,"",'width="60" align="center"',$sortfield,$sortorder); print "\n"; - // Lignes des champs de filtre + // Line for filters fields print ''; print ''; @@ -263,7 +263,7 @@ if ($resql) print ''; print ''; - print "\n"; + print "\n"; $var=True; while ($i < $num && $i < $conf->liste_limit) From 3b09dc53cd186d99887f7158f76ea898268b1cca Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 14 Feb 2015 20:32:11 +0100 Subject: [PATCH 114/173] Fix regression on total visible on invoice since situation invoice. --- .../modules/facture/doc/pdf_crabe.modules.php | 79 ++++++------------- htdocs/langs/en_US/main.lang | 1 + 2 files changed, 24 insertions(+), 56 deletions(-) diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index 06c3df85f4d..4c340a12cfa 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -68,7 +68,7 @@ class pdf_crabe extends ModelePDFFactures */ public $posxprogress; - + /** * Constructor * @@ -293,7 +293,8 @@ class pdf_crabe extends ModelePDFFactures } // Situation invoice handling - if ($object->situation_cycle_ref) { + if ($object->situation_cycle_ref) + { $this->situationinvoice = True; $progress_width = 14; $this->posxtva -= $progress_width; @@ -472,16 +473,19 @@ class pdf_crabe extends ModelePDFFactures $pdf->MultiCell($this->posxprogress-$this->posxdiscount+2, 3, $remise_percent, 0, 'R'); } - // Situation progress - $progress = pdf_getlineprogress($object, $i, $outputlangs, $hidedetails); - $pdf->SetXY($this->posxprogress, $curY); - $pdf->MultiCell($this->postotalht-$this->posxprogress, 3, $progress, 0, 'R'); // Enough for 6 chars + if ($this->situationinvoice) + { + // Situation progress + $progress = pdf_getlineprogress($object, $i, $outputlangs, $hidedetails); + $pdf->SetXY($this->posxprogress, $curY); + $pdf->MultiCell($this->postotalht-$this->posxprogress, 3, $progress, 0, 'R'); + } // Total HT line $total_excl_tax = pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails); $pdf->SetXY($this->postotalht, $curY); $pdf->MultiCell($this->page_largeur-$this->marge_droite-$this->postotalht, 3, $total_excl_tax, 0, 'R', 0); - + // Collecte des totaux par valeur de tva dans $this->tva["taux"]=total_tva $prev_progress = $object->lines[$i]->get_prev_progress(); if ($prev_progress > 0) // Compute progress from previous situation @@ -948,7 +952,7 @@ class pdf_crabe extends ModelePDFFactures $pdf->SetFont('','', $default_font_size - 1); // Tableau total - $col1x = 120; $col2x = $this->postotalht; + $col1x = 120; $col2x = 170; if ($this->page_largeur < 210) // To work with US executive format { $col2x-=20; @@ -958,44 +962,11 @@ class pdf_crabe extends ModelePDFFactures $useborder=0; $index = 0; - // Previous situations summary - if ($object->situation_cycle_ref && $object->situation_counter > 1) { - // Situations total w/out VAT - $counter = ' 1'; - for ($i = 2; $i <= $object->situation_counter; $i++) { - $counter .= ' + ' . $i; - } - - $prevsits = $object->get_prev_sits(); - $prevsits_total_amount = 0; - foreach ($prevsits as $situation) { - $prevsits_total_amount += $situation->total_ht; - } - $prevsits_total_amount += $object->total_ht; - - $pdf->SetFillColor(255, 255, 255); - $pdf->SetXY($col1x, $tab2_top + 0); - $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("SituationAmount") . $counter, 0, 'L', 1); - $pdf->SetXY($col2x, $tab2_top + 0); - $pdf->MultiCell($largcol2, $tab2_hl, price($prevsits_total_amount), 0, 'R', 1); - - // Previous situations deduction - $pdf->Line($col2x, 0, $col2x, 100000); - for ($i = 0; $i < count($prevsits); $i++) { - $index++; - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("SituationDeduction") . ' ' . ($i + 1) . ' (' . $prevsits[$i]->ref . ')', 0, 'L', 1); - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); - $pdf->MultiCell($largcol2, $tab2_hl, ' - ' . price($prevsits[$i]->total_ht), 0, 'R', 1); - } - $index++; - } - // Total HT $pdf->SetFillColor(255,255,255); - $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index); + $pdf->SetXY($col1x, $tab2_top + 0); $pdf->MultiCell($col2x-$col1x, $tab2_hl, $outputlangs->transnoentities("TotalHT"), 0, 'L', 1); - $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index); + $pdf->SetXY($col2x, $tab2_top + 0); $pdf->MultiCell($largcol2, $tab2_hl, price($sign * ($object->total_ht + (! empty($object->remise)?$object->remise:0)), 0, $outputlangs), 0, 'R', 1); // Show VAT by rates and total @@ -1334,21 +1305,19 @@ class pdf_crabe extends ModelePDFFactures $pdf->SetXY($this->posxqty-1, $tab_top+1); $pdf->MultiCell($this->posxdiscount-$this->posxqty-1,2, $outputlangs->transnoentities("Qty"),'','C'); } + $pdf->line($this->posxdiscount-1, $tab_top, $this->posxdiscount-1, $tab_top + $tab_height); - if ($this->atleastonediscount) { - $pdf->line($this->posxprogress, $tab_top, $this->posxprogress, $tab_top + $tab_height); - if (empty($hidetop)) { - $pdf->SetXY($this->posxdiscount - 1, $tab_top + 1); - $pdf->MultiCell($this->posxprogress - $this->posxdiscount + 1, 2, $outputlangs->transnoentities("ReductionShort"), '', 'C'); + if (empty($hidetop)) + { + if ($this->atleastonediscount) + { + $pdf->SetXY($this->posxdiscount-1, $tab_top+1); + $pdf->MultiCell($this->postotalht-$this->posxdiscount+1,2, $outputlangs->transnoentities("ReductionShort"),'','C'); } } - - if ($this->situationinvoice) { + if ($this->atleastonediscount) + { $pdf->line($this->postotalht, $tab_top, $this->postotalht, $tab_top + $tab_height); - if (empty($hidetop)) { - $pdf->SetXY($this->posxprogress - 1, $tab_top + 1); - $pdf->MultiCell($this->postotalht - $this->posxprogress - 1, 2, $outputlangs->transnoentities("Progress"), '', 'C'); - } } if (empty($hidetop)) { @@ -1424,8 +1393,6 @@ class pdf_crabe extends ModelePDFFactures if ($object->type == 2) $title=$outputlangs->transnoentities("InvoiceAvoir"); if ($object->type == 3) $title=$outputlangs->transnoentities("InvoiceDeposit"); if ($object->type == 4) $title=$outputlangs->transnoentities("InvoiceProFormat"); - if ($object->type == 5 && $object->situation_final == 0) $title = $outputlangs->transnoentities("InvoiceSituation").' n°'.$object->situation_counter; - if ($object->type == 5 && $object->situation_final == 1) $title = 'Situation n°'.$object->situation_counter.' : '.$outputlangs->transnoentities("InvoiceSituationLast"); $pdf->MultiCell(100, 3, $title, '', 'R'); $pdf->SetFont('','B',$default_font_size); diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 1bc5b2a8c36..d7e82aa43b8 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -688,6 +688,7 @@ PublicUrl=Public URL AddBox=Add box SelectElementAndClickRefresh=Select an element and click Refresh PrintFile=Print File %s +ShowTransaction=Show transaction # Week day Monday=Monday Tuesday=Tuesday From bedaa483ade79e8e876c4cf7da60e93c08ab7c3c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 14 Feb 2015 20:40:10 +0100 Subject: [PATCH 115/173] br useless --- htdocs/compta/facture.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/facture.php b/htdocs/compta/facture.php index 943389bc7c2..cc4d2cff7e7 100644 --- a/htdocs/compta/facture.php +++ b/htdocs/compta/facture.php @@ -592,7 +592,7 @@ if (empty($reshook)) $discount->fk_facture_source = $object->id; $error = 0; - + foreach ($amount_ht as $tva_tx => $xxx) { $discount->amount_ht = abs($amount_ht [$tva_tx]); $discount->amount_tva = abs($amount_tva [$tva_tx]); @@ -3744,7 +3744,7 @@ if ($action == 'create') $i ++; } print ''; - print '
 
'; + print '
 
'; print ''; $db->free($resqlorderlist); } else { From 09ef15ea241ec045f2e1ddcc44a57e3e91788f0c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 15 Feb 2015 13:42:21 +0100 Subject: [PATCH 116/173] phpcs --- htdocs/expensereport/card.php | 2 +- .../class/expensereport.class.php | 160 +++++++++--------- htdocs/expensereport/list.php | 3 +- 3 files changed, 87 insertions(+), 78 deletions(-) diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index 7d52ac5b538..5a6f3a29b07 100755 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -747,7 +747,7 @@ if ($action == "addline") $tx_tva = $tx_tva + 1; $object_ligne->total_ht = $object_ligne->total_ttc / $tx_tva; - $object_ligne->total_ht = number_format($object_ligne->total_ht,2,'.',''); + $object_ligne->total_ht = price2num($object_ligne->total_ht,'MT'); $object_ligne->total_tva = $object_ligne->total_ttc - $object_ligne->total_ht; // Fin calculs des totos diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php index c54090dfe2f..092a642b4b4 100755 --- a/htdocs/expensereport/class/expensereport.class.php +++ b/htdocs/expensereport/class/expensereport.class.php @@ -244,12 +244,15 @@ class ExpenseReport extends CommonObject /** * Load an object from database + * + * @param int $id Id + * @param User $user User we want expense report for */ function fetch($id,$user='') { global $conf,$db; - if(!$user->rights->expensereport->lire): + if (!$user->rights->expensereport->lire): $restrict = " AND fk_user_author = ".$user->id; else: $restrict = ""; @@ -299,18 +302,29 @@ class ExpenseReport extends CommonObject $this->fk_user_refuse = $obj->fk_user_refuse; $this->fk_user_cancel = $obj->fk_user_cancel; - $this->user_author_infos = $this->fetch_names($this->fk_user_author); - $this->user_validator_infos = $this->fetch_names($this->fk_user_validator); + $user_author = new User($this->db); + $user_author->fetch($this->fk_user_author); + $this->user_author_infos = dolGetFirstLastname($user_author->firstname, $user_author->lastname); - $this->fk_c_expensereport_statuts = $obj->fk_c_expensereport_statuts; - $this->fk_c_paiement = $obj->fk_c_paiement; + $user_approver = new User($this->db); + $user_approver->fetch($this->fk_user_validator); + $this->user_validator_infos = dolGetFirstLastname($user_approver->firstname, $user_approver->lastname); - if($this->fk_c_expensereport_statuts==5 || $this->fk_c_expensereport_statuts==6){ - $this->user_valid_infos = $this->fetch_names($this->fk_user_valid); + $this->fk_c_expensereport_statuts = $obj->fk_c_expensereport_statuts; + $this->fk_c_paiement = $obj->fk_c_paiement; + + if ($this->fk_c_expensereport_statuts==5 || $this->fk_c_expensereport_statuts==6) + { + $user_valid = new User($this->db); + $user_valid->fetch($this->fk_user_valid); + $this->user_valid_infos = dolGetFirstLastname($user_valid->firstname, $user_valid->lastname); } - if($this->fk_c_expensereport_statuts==6){ - $this->user_paid_infos = $this->fetch_names($this->fk_user_paid); + if ($this->fk_c_expensereport_statuts==6) + { + $user_paid = new User($this->db); + $user_paid->fetch($this->fk_user_paid); + $this->user_paid_infos = dolGetFirstLastname($user_paid->firstname, $user_paid->lastname); } $this->libelle_statut = $obj->libelle_statut; @@ -375,22 +389,6 @@ class ExpenseReport extends CommonObject } - /** - * - * @param unknown_type $id - * @return unknown - */ - function fetch_names($id) - { - global $db; - - $sql = "SELECT lastname, firstname, email, user_mobile, office_phone "; - $sql.= "FROM ".MAIN_DB_PREFIX."user "; - $sql.= "WHERE rowid = ".$id; - $result = $db->query($sql); - $obj = $db->fetch_object($result); - return $obj; - } /** * @@ -1056,9 +1054,9 @@ class ExpenseReport extends CommonObject /** * deleteline * - * @param unknown_type $rowid - * @param unknown_type $user - * @return number + * @param int $rowid Row id + * @param User $user User + * @return int <0 if KO, >0 if OK */ function deleteline($rowid, $user='') { @@ -1082,24 +1080,13 @@ class ExpenseReport extends CommonObject return 1; } - /** - * dumpp - * - * @param unknown_type $value - */ - function dumpp($value) - { - echo '
'; - var_dump("
",$value,"
"); - echo '
'; - } - /** * periode_existe * - * @param unknown_type $user - * @param unknown_type $date_debut - * @param unknown_type $date_fin + * @param User $user User + * @param Date $date_debut Start date + * @param Date $date_fin End date + * @return int <0 if KO, >0 if OK */ function periode_existe($user,$date_debut,$date_fin) { @@ -1109,10 +1096,12 @@ class ExpenseReport extends CommonObject dol_syslog(get_class($this)."::periode_existe sql=".$sql); $result = $this->db->query($sql); - if($result): + if($result) + { $num_lignes = $this->db->num_rows($result); $i = 0; - if($num_lignes>0): + if ($num_lignes>0) + { $date_d_form = explode("-",$date_debut); // 1 $date_f_form = explode("-",$date_fin); // 2 $date_d_form = mktime(12,0,0,$date_d_form[1],$date_d_form[2],$date_d_form[0]); @@ -1120,7 +1109,8 @@ class ExpenseReport extends CommonObject $existe = false; - while ($i < $num_lignes): + while ($i < $num_lignes) + { $objp = $this->db->fetch_object($result); $date_d_req = explode("-",$objp->date_debut); // 3 @@ -1131,19 +1121,22 @@ class ExpenseReport extends CommonObject if(!($date_f_form < $date_d_req OR $date_d_form > $date_f_req)) $existe = true; $i++; - endwhile; + } if($existe) return 1; else return 0; - - else: + } + else + { return 0; - endif; - else: - $this->error=$this->db->error(); + } + } + else + { + $this->error=$this->db->lasterror(); dol_syslog(get_class($this)."::periode_existe Error ".$this->error, LOG_ERR); return -1; - endif; + } } @@ -1214,12 +1207,22 @@ class ExpenseReportLigne var $total_tva; var $total_ttc; - - function ExpenseReportLigne($DB) + /** + * Constructor + * + * @param DoliDB $db Handlet database + */ + function ExpenseReportLigne($db) { - $this->db= $DB ; + $this->db= $db; } + /** + * fetch record + * + * @param int $rowid Row id to fetch + * @return int <0 if KO, >0 if OK + */ function fetch($rowid) { $sql = 'SELECT fde.rowid, fde.fk_expensereport, fde.fk_c_type_fees, fde.fk_projet, fde.date,'; @@ -1262,6 +1265,12 @@ class ExpenseReportLigne } } + /** + * insert + * + * @param int $notrigger 1=No trigger + * @return int <0 if KO, >0 if OK + */ function insert($notrigger=0) { global $langs,$user,$conf; @@ -1307,7 +1316,13 @@ class ExpenseReportLigne endif; } - function update() + /** + * update + * + * @param User $user User + * @return int <0 if KO, >0 if OK + */ + function update($user) { global $user,$langs,$conf; @@ -1318,7 +1333,7 @@ class ExpenseReportLigne // Mise a jour ligne en base $sql = "UPDATE ".MAIN_DB_PREFIX."expensereport_det SET"; - $sql.= " comments='".addslashes($this->comments)."'"; + $sql.= " comments='".$this->db->escape($this->comments)."'"; $sql.= ",value_unit=".$this->value_unit.""; $sql.= ",qty=".$this->qty.""; if ($this->date) { $sql.= ",date='".$this->date."'"; } @@ -1350,17 +1365,9 @@ class ExpenseReportLigne return -2; } } - - function fetch_taux($id){ - $sql = "SELECT taux"; - $sql .= " FROM ".MAIN_DB_PREFIX ."c_tva"; - $sql .= " WHERE rowid = ".$id; - $resql=$this->db->query($sql); - $objp = $this->db->fetch_object($result); - $this->tva_taux = $objp->taux; - } } + /** * Retourne la liste deroulante des differents etats d'une note de frais. * Les valeurs de la liste sont les id de la table c_expensereport_statuts @@ -1395,12 +1402,13 @@ function select_expensereport_statut($selected='',$htmlname='fk_c_expensereport_ } /** - * - * @param unknown_type $selected - * @param unknown_type $filter - * @param unknown_type $htmlname - * + * select_projet * TODO Utiliser le select project officiel + * + * @param int $selected Id selected + * @param string $filter Filter + * @param string $htmlname Select name + * @return int <0 if KO, >0 if OK */ function select_projet($selected='',$filter='', $htmlname='fk_projet') { @@ -1455,10 +1463,10 @@ function select_projet($selected='',$filter='', $htmlname='fk_projet') /** * Return list of types of notes with select value = id * - * @param selected Preselected type - * @param htmlname Name of field in form - * @param showempty Add an empty field - * @return string Select html + * @param int $selected Preselected type + * @param string $htmlname Name of field in form + * @param int $showempty Add an empty field + * @return string Select html */ function select_type_fees_id($selected='',$htmlname='type',$showempty=0) { diff --git a/htdocs/expensereport/list.php b/htdocs/expensereport/list.php index c9a965b5587..0d2be8a7c45 100755 --- a/htdocs/expensereport/list.php +++ b/htdocs/expensereport/list.php @@ -166,7 +166,8 @@ if (empty($user->rights->expensereport->readall) && empty($user->rights->expense } // ORDER -$sql.= " ORDER BY $sortfield $sortorder " . $db->plimit( $limit + 1 ,$offset); +$sql.= $db->order($sortfield,$sortorder); +$sql.= $db->plimit($limit+1, $offset); if($_GET['debug']=='ok'){ var_dump("
",$sql,"
"); exit(); From d1f73499e90e1a01d796ec9c9f12e02bddcf328e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Sun, 15 Feb 2015 15:01:28 +0100 Subject: [PATCH 117/173] Refactored dashboard indicator --- htdocs/adherents/class/adherent.class.php | 26 ++- htdocs/comm/action/class/actioncomm.class.php | 30 ++-- htdocs/comm/mailing/card.php | 4 +- htdocs/comm/propal/class/propal.class.php | 39 +++-- htdocs/commande/class/commande.class.php | 29 ++-- htdocs/compta/bank/class/account.class.php | 28 +-- htdocs/compta/facture/class/facture.class.php | 29 ++-- .../cheque/class/remisecheque.class.php | 27 ++- htdocs/contrat/class/contrat.class.php | 40 +++-- htdocs/core/class/BoardResponse.class.php | 69 ++++++++ .../class/fournisseur.commande.class.php | 24 ++- .../fourn/class/fournisseur.facture.class.php | 24 ++- htdocs/index.php | 161 ++++-------------- 13 files changed, 296 insertions(+), 234 deletions(-) create mode 100644 htdocs/core/class/BoardResponse.class.php diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 98d971acbd0..1f8ae82dcbd 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -1725,17 +1725,15 @@ class Adherent extends CommonObject * Load indicators for dashboard (this->nbtodo and this->nbtodolate) * * @param User $user Objet user - * @return int <0 if KO, >0 if OK + * @return BoardResponse|int <0 if KO, BoardResponse if OK */ function load_board($user) { - global $conf; - - $now=dol_now(); + global $conf, $langs; if ($user->societe_id) return -1; // protection pour eviter appel par utilisateur externe - $this->nbtodo=$this->nbtodolate=0; + $now=dol_now(); $sql = "SELECT a.rowid, a.datefin"; $sql.= " FROM ".MAIN_DB_PREFIX."adherent as a"; @@ -1746,12 +1744,24 @@ class Adherent extends CommonObject $resql=$this->db->query($sql); if ($resql) { + $langs->load("members"); + + $response = new BoardResponse(); + $response->warning_delay=$conf->adherent->cotisation->warning_delay/60/60/24; + $response->label=$langs->trans("MembersWithSubscriptionToReceive"); + $response->url=DOL_URL_ROOT.'/adherents/list.php?mainmenu=members&statut=1'; + $response->img=img_object($langs->trans("Members"),"user"); + while ($obj=$this->db->fetch_object($resql)) { - $this->nbtodo++; - if ($this->db->jdate($obj->datefin) < ($now - $conf->adherent->cotisation->warning_delay)) $this->nbtodolate++; + $response->nbtodo++; + + if ($this->db->jdate($obj->datefin) < ($now - $conf->adherent->cotisation->warning_delay)) { + $response->nbtodolate++; + } } - return 1; + + return $response; } else { diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index b20a3afa3ea..d13f32f157c 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -712,18 +712,14 @@ class ActionComm extends CommonObject } /** - * Load indicators for dashboard (this->nbtodo and this->nbtodolate) + * Load indicators for dashboard (this->nbtodo and this->nbtodolate) * - * @param User $user Objet user - * @return int <0 if KO, >0 if OK + * @param User $user Objet user + * @return BoardResponse|int <0 if KO, BoardResponse if OK */ function load_board($user) { - global $conf, $user; - - $now=dol_now(); - - $this->nbtodo=$this->nbtodolate=0; + global $conf, $user, $langs; $sql = "SELECT a.id, a.datep as dp"; $sql.= " FROM (".MAIN_DB_PREFIX."actioncomm as a"; @@ -739,13 +735,25 @@ class ActionComm extends CommonObject $resql=$this->db->query($sql); if ($resql) { + $now = dol_now(); + + $response = new BoardResponse(); + $response->warning_delay = $conf->actions->warning_delay/60/60/24; + $response->label = $langs->trans("ActionsToDo"); + $response->url = DOL_URL_ROOT.'/comm/action/listactions.php?status=todo&mainmenu=agenda'; + $response->img = img_object($langs->trans("Actions"),"action"); + // This assignment in condition is not a bug. It allows walking the results. while ($obj=$this->db->fetch_object($resql)) { - $this->nbtodo++; - if (isset($obj->dp) && $this->db->jdate($obj->dp) < ($now - $conf->actions->warning_delay)) $this->nbtodolate++; + $response->nbtodo++; + + if (isset($obj->dp) && $this->db->jdate($obj->dp) < ($now - $conf->actions->warning_delay)) { + $response->nbtodolate++; + } } - return 1; + + return $response; } else { diff --git a/htdocs/comm/mailing/card.php b/htdocs/comm/mailing/card.php index 267fde415f6..1a574fa434a 100644 --- a/htdocs/comm/mailing/card.php +++ b/htdocs/comm/mailing/card.php @@ -140,9 +140,7 @@ if (empty($reshook)) { if (empty($conf->global->MAILING_LIMIT_SENDBYWEB)) { - //TODO: What is this for? - // Pour des raisons de securite, on ne permet pas cette fonction via l'IHM, - // on affiche donc juste un message + // As security measure, we don't allow send from the GUI setEventMessage($langs->trans("MailingNeedCommand"), 'warnings'); setEventMessage('', 'warnings'); setEventMessage($langs->trans("MailingNeedCommand2"), 'warnings'); diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index 8fae698ba94..2c20e5ea1c7 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -116,10 +116,6 @@ class Propal extends CommonObject var $labelstatut=array(); var $labelstatut_short=array(); - // Pour board - var $nbtodo; - var $nbtodolate; - var $specimen; @@ -2349,15 +2345,12 @@ class Propal extends CommonObject * * @param User $user Object user * @param int $mode "opened" for proposal to close, "signed" for proposal to invoice - * @return int <0 if KO, >0 if OK + * @return BoardResponse|int <0 if KO, BoardResponse if OK */ function load_board($user,$mode) { - global $conf, $user; + global $conf, $user, $langs; - $now=dol_now(); - - $this->nbtodo=$this->nbtodolate=0; $clause = " WHERE"; $sql = "SELECT p.rowid, p.ref, p.datec as datec, p.fin_validite as datefin"; @@ -2376,25 +2369,43 @@ class Propal extends CommonObject $resql=$this->db->query($sql); if ($resql) { - if ($mode == 'opened') $delay_warning=$conf->propal->cloture->warning_delay; - if ($mode == 'signed') $delay_warning=$conf->propal->facturation->warning_delay; + $langs->load("propal"); + $now=dol_now(); + + if ($mode == 'opened') { + $delay_warning=$conf->propal->cloture->warning_delay; + $statut = 1; + $label = $langs->trans("PropalsToClose"); + } + if ($mode == 'signed') { + $delay_warning=$conf->propal->facturation->warning_delay; + $statut = 2; + $label = $langs->trans("PropalsToBill"); + } + + $response = new BoardResponse(); + $response->warning_delay = $delay_warning; + $response->label = $label; + $response->url = DOL_URL_ROOT.'/comm/propal/list.php?viewstatut='.$statut; + $response->img = img_object($langs->trans("Propals"),"propal"); // This assignment in condition is not a bug. It allows walking the results. while ($obj=$this->db->fetch_object($resql)) { - $this->nbtodo++; + $response->nbtodo++; if ($mode == 'opened') { $datelimit = $this->db->jdate($obj->datefin); if ($datelimit < ($now - $delay_warning)) { - $this->nbtodolate++; + $response->nbtodolate++; } } // TODO Definir regle des propales a facturer en retard // if ($mode == 'signed' && ! count($this->FactureListeArray($obj->rowid))) $this->nbtodolate++; } - return 1; + + return $response; } else { diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 27c320b3326..511af75a967 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -106,10 +106,6 @@ class Commande extends CommonOrder var $lines = array(); - // Pour board - var $nbtodo; - var $nbtodolate; - /** * Constructor @@ -2729,15 +2725,12 @@ class Commande extends CommonOrder * Load indicators for dashboard (this->nbtodo and this->nbtodolate) * * @param User $user Object user - * @return int <0 if KO, >0 if OK + * @return BoardResponse|int <0 if KO, BoardResponse if OK */ function load_board($user) { - global $conf, $user; + global $conf, $user, $langs; - $now=dol_now(); - - $this->nbtodo=$this->nbtodolate=0; $clause = " WHERE"; $sql = "SELECT c.rowid, c.date_creation as datec, c.date_livraison as delivery_date, c.fk_statut"; @@ -2756,14 +2749,26 @@ class Commande extends CommonOrder $resql=$this->db->query($sql); if ($resql) { + $now=dol_now(); + + $response = new BoardResponse(); + $response->warning_delay=$conf->commande->client->warning_delay/60/60/24; + $response->label=$langs->trans("OrdersToProcess"); + $response->url=DOL_URL_ROOT.'/commande/list.php?viewstatut=-3'; + $response->img=img_object($langs->trans("Orders"),"order"); + while ($obj=$this->db->fetch_object($resql)) { - $this->nbtodo++; + $response->nbtodo++; $date_to_test = empty($obj->delivery_date) ? $obj->datec : $obj->delivery_date; - if ($obj->fk_statut != 3 && $this->db->jdate($date_to_test) < ($now - $conf->commande->client->warning_delay)) $this->nbtodolate++; + + if ($obj->fk_statut != 3 && $this->db->jdate($date_to_test) < ($now - $conf->commande->client->warning_delay)) { + $response->nbtodolate++; + } } - return 1; + + return $response; } else { diff --git a/htdocs/compta/bank/class/account.class.php b/htdocs/compta/bank/class/account.class.php index 598ccc2c8d8..c2929fb33a4 100644 --- a/htdocs/compta/bank/class/account.class.php +++ b/htdocs/compta/bank/class/account.class.php @@ -881,18 +881,14 @@ class Account extends CommonObject * * @param User $user Objet user * @param int $filteraccountid To get info for a particular account id - * @return int <0 if KO, 0=Nothing to show, >0 if OK + * @return BoardResponse|int <0 if KO, BoardResponse if OK */ function load_board($user,$filteraccountid=0) { - global $conf; + global $conf, $langs; if ($user->societe_id) return -1; // protection pour eviter appel par utilisateur externe - $now=dol_now(); - - $this->nbtodo=$this->nbtodolate=0; - $sql = "SELECT b.rowid, b.datev as datefin"; $sql.= " FROM ".MAIN_DB_PREFIX."bank as b,"; $sql.= " ".MAIN_DB_PREFIX."bank_account as ba"; @@ -902,17 +898,27 @@ class Account extends CommonObject $sql.= " AND (ba.rappro = 1 AND ba.courant != 2)"; // Compte rapprochable if ($filteraccountid) $sql.=" AND ba.rowid = ".$filteraccountid; - //print $sql; $resql=$this->db->query($sql); if ($resql) { - $num=$this->db->num_rows($resql); + $langs->load("banks"); + $now=dol_now(); + + $response = new BoardResponse(); + $response->warning_delay=$conf->bank->rappro->warning_delay/60/60/24; + $response->label=$langs->trans("TransactionsToConciliate"); + $response->url=DOL_URL_ROOT.'/compta/bank/index.php?leftmenu=bank&mainmenu=bank'; + $response->img=img_object($langs->trans("TransactionsToConciliate"),"payment"); + while ($obj=$this->db->fetch_object($resql)) { - $this->nbtodo++; - if ($this->db->jdate($obj->datefin) < ($now - $conf->bank->rappro->warning_delay)) $this->nbtodolate++; + $response->nbtodo++; + if ($this->db->jdate($obj->datefin) < ($now - $conf->bank->rappro->warning_delay)) { + $response->nbtodolate++; + } } - return $num; + + return $response; } else { diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 5c645783cc1..3bbf76c79fe 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -117,9 +117,6 @@ class Facture extends CommonInvoice var $lines=array(); var $line; var $extraparams=array(); - //! Pour board - var $nbtodo; - var $nbtodolate; var $specimen; var $fac_rec; @@ -3088,15 +3085,12 @@ class Facture extends CommonInvoice * Load indicators for dashboard (this->nbtodo and this->nbtodolate) * * @param User $user Object user - * @return int <0 if KO, >0 if OK + * @return BoardResponse|int <0 if KO, BoardResponse if OK */ function load_board($user) { - global $conf, $user; + global $conf, $user, $langs; - $now=dol_now(); - - $this->nbtodo=$this->nbtodolate=0; $clause = " WHERE"; $sql = "SELECT f.rowid, f.date_lim_reglement as datefin"; @@ -3115,12 +3109,25 @@ class Facture extends CommonInvoice $resql=$this->db->query($sql); if ($resql) { + $langs->load("bills"); + $now=dol_now(); + + $response = new BoardResponse(); + $response->warning_delay=$conf->facture->client->warning_delay/60/60/24; + $response->label=$langs->trans("CustomerBillsUnpaid"); + $response->url=DOL_URL_ROOT.'/compta/facture/impayees.php'; + $response->img=img_object($langs->trans("Bills"),"bill"); + while ($obj=$this->db->fetch_object($resql)) { - $this->nbtodo++; - if ($this->db->jdate($obj->datefin) < ($now - $conf->facture->client->warning_delay)) $this->nbtodolate++; + $response->nbtodo++; + + if ($this->db->jdate($obj->datefin) < ($now - $conf->facture->client->warning_delay)) { + $response->nbtodolate++; + } } - return 1; + + return $response; } else { diff --git a/htdocs/compta/paiement/cheque/class/remisecheque.class.php b/htdocs/compta/paiement/cheque/class/remisecheque.class.php index 11a61874e7e..6bb1429d0a0 100644 --- a/htdocs/compta/paiement/cheque/class/remisecheque.class.php +++ b/htdocs/compta/paiement/cheque/class/remisecheque.class.php @@ -432,18 +432,14 @@ class RemiseCheque extends CommonObject * Load indicators for dashboard (this->nbtodo and this->nbtodolate) * * @param User $user Objet user - * @return int <0 if KO, >0 if OK + * @return BoardResponse|int <0 if KO, BoardResponse if OK */ function load_board($user) { - global $conf; + global $conf, $langs; if ($user->societe_id) return -1; // protection pour eviter appel par utilisateur externe - $now=dol_now(); - - $this->nbtodo=$this->nbtodolate=0; - $sql = "SELECT b.rowid, b.datev as datefin"; $sql.= " FROM ".MAIN_DB_PREFIX."bank as b"; $sql.= ", ".MAIN_DB_PREFIX."bank_account as ba"; @@ -456,12 +452,25 @@ class RemiseCheque extends CommonObject $resql=$this->db->query($sql); if ($resql) { + $langs->load("banks"); + $now=dol_now(); + + $response = new BoardResponse(); + $response->warning_delay=$conf->bank->cheque->warning_delay/60/60/24; + $response->label=$langs->trans("BankChecksToReceipt"); + $response->url=DOL_URL_ROOT.'/compta/paiement/cheque/index.php?leftmenu=checks&mainmenu=accountancy'; + $response->img=img_object($langs->trans("BankChecksToReceipt"),"payment"); + while ($obj=$this->db->fetch_object($resql)) { - $this->nbtodo++; - if ($this->db->jdate($obj->datefin) < ($now - $conf->bank->cheque->warning_delay)) $this->nbtodolate++; + $response->nbtodo++; + + if ($this->db->jdate($obj->datefin) < ($now - $conf->bank->cheque->warning_delay)) { + $response->nbtodolate++; + } } - return 1; + + return $response; } else { diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index bbecab53a30..19001edf92c 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -1881,15 +1881,11 @@ class Contrat extends CommonObject * * @param User $user Objet user * @param string $mode "inactive" pour services a activer, "expired" pour services expires - * @return int <0 if KO, >0 if OK + * @return BoardResponse|int <0 if KO, BoardResponse if OK */ function load_board($user,$mode) { - global $conf, $user; - - $now=dol_now(); - - $this->nbtodo=$this->nbtodolate=0; + global $conf, $user, $langs; $this->from = " FROM ".MAIN_DB_PREFIX."contrat as c"; $this->from.= ", ".MAIN_DB_PREFIX."contratdet as cd"; @@ -1920,15 +1916,35 @@ class Contrat extends CommonObject $resql=$this->db->query($sql); if ($resql) { + $langs->load("contracts"); + $now=dol_now(); + + if ($mode == 'inactives') { + $warning_delay = $conf->contrat->services->inactifs->warning_delay; + $label = $langs->trans("BoardNotActivatedServices"); + $url = DOL_URL_ROOT.'/contrat/services.php?mainmenu=commercial&leftmenu=contracts&mode=0'; + } else { + $warning_delay = $conf->contrat->services->expires->warning_delay; + $url = DOL_URL_ROOT.'/contrat/services.php?mainmenu=commercial&leftmenu=contracts&mode=4&filter=expired'; + $label = $langs->trans("BoardRunningServices"); + } + + $response = new BoardResponse(); + $response->warning_delay = $warning_delay/60/60/24; + $response->label = $label; + $response->url = $url; + $response->img = img_object($langs->trans("Contract"),"contract"); + while ($obj=$this->db->fetch_object($resql)) { - $this->nbtodo++; - if ($mode == 'inactives') - if ($obj->datefin && $this->db->jdate($obj->datefin) < ($now - $conf->contrat->services->inactifs->warning_delay)) $this->nbtodolate++; - if ($mode == 'expired') - if ($obj->datefin && $this->db->jdate($obj->datefin) < ($now - $conf->contrat->services->expires->warning_delay)) $this->nbtodolate++; + $response->nbtodo++; + + if ($obj->datefin && $this->db->jdate($obj->datefin) < ($now - $warning_delay)) { + $response->nbtodolate++; + } } - return 1; + + return $response; } else { diff --git a/htdocs/core/class/BoardResponse.class.php b/htdocs/core/class/BoardResponse.class.php new file mode 100644 index 00000000000..9cf12e7a702 --- /dev/null +++ b/htdocs/core/class/BoardResponse.class.php @@ -0,0 +1,69 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/core/class/BoardResponse.class.php + * \brief Class that represents response of load_board functions + */ + +class BoardResponse +{ + + /** + * Image URL to represent the board item + * @var string + */ + public $img; + + /** + * Label of the warning + * @var string + */ + public $label; + + /** + * URL to list to do items + * @var string + */ + public $url; + + /** + * Delay time to mark an item as late + * @var int + */ + public $warning_delay; + + /** + * (optional) If set, to do late items will link to this url + * @var string + */ + public $lateurl; + + /** + * Number of items to do + * @var int + */ + public $nbtodo = 0; + + /** + * Number of to do items which are late + * @var int + */ + public $nbtodolate = 0; + +} \ No newline at end of file diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 64131be840b..c5765772c3b 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -2000,15 +2000,12 @@ class CommandeFournisseur extends CommonOrder * Load indicators for dashboard (this->nbtodo and this->nbtodolate) * * @param User $user Objet user - * @return int <0 if KO, >0 if OK + * @return BoardResponse|int <0 if KO, BoardResponse if OK */ function load_board($user) { - global $conf, $user; + global $conf, $user, $langs; - $now=dol_now(); - - $this->nbtodo=$this->nbtodolate=0; $clause = " WHERE"; $sql = "SELECT c.rowid, c.date_creation as datec, c.fk_statut,c.date_livraison as delivery_date"; @@ -2026,14 +2023,25 @@ class CommandeFournisseur extends CommonOrder $resql=$this->db->query($sql); if ($resql) { + $now=dol_now(); + + $response = new BoardResponse(); + $response->warning_delay=$conf->commande->fournisseur->warning_delay/60/60/24; + $response->label=$langs->trans("SuppliersOrdersToProcess"); + $response->url=DOL_URL_ROOT.'/fourn/commande/index.php'; + $response->img=img_object($langs->trans("Orders"),"order"); + while ($obj=$this->db->fetch_object($resql)) { - $this->nbtodo++; + $response->nbtodo++; $date_to_test = empty($obj->delivery_date) ? $obj->datec : $obj->delivery_date; - if ($obj->fk_statut != 3 && $this->db->jdate($date_to_test) < ($now - $conf->commande->fournisseur->warning_delay)) $this->nbtodolate++; + if ($obj->fk_statut != 3 && $this->db->jdate($date_to_test) < ($now - $conf->commande->fournisseur->warning_delay)) { + $response->nbtodolate++; + } } - return 1; + + return $response; } else { diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php index 71e5c320dfa..3b029eff79c 100644 --- a/htdocs/fourn/class/fournisseur.facture.class.php +++ b/htdocs/fourn/class/fournisseur.facture.class.php @@ -1421,15 +1421,12 @@ class FactureFournisseur extends CommonInvoice * Load indicators for dashboard (this->nbtodo and this->nbtodolate) * * @param User $user Object user - * @return int <0 if KO, >0 if OK + * @return BoardResponse|int <0 if KO, BoardResponse if OK */ function load_board($user) { - global $conf, $user; + global $conf, $user, $langs; - $now=dol_now(); - - $this->nbtodo=$this->nbtodolate=0; $sql = 'SELECT ff.rowid, ff.date_lim_reglement as datefin'; $sql.= ' FROM '.MAIN_DB_PREFIX.'facture_fourn as ff'; if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; @@ -1442,13 +1439,24 @@ class FactureFournisseur extends CommonInvoice $resql=$this->db->query($sql); if ($resql) { + $langs->load("bills"); + $now=dol_now(); + + $response = new BoardResponse(); + $response->warning_delay=$conf->facture->fournisseur->warning_delay/60/60/24; + $response->label=$langs->trans("SupplierBillsToPay"); + $response->url=DOL_URL_ROOT.'/fourn/facture/list.php?filtre=paye:0'; + $response->img=img_object($langs->trans("Bills"),"bill"); + while ($obj=$this->db->fetch_object($resql)) { - $this->nbtodo++; - if (! empty($obj->datefin) && $this->db->jdate($obj->datefin) < ($now - $conf->facture->fournisseur->warning_delay)) $this->nbtodolate++; + $response->nbtodo++; + if (! empty($obj->datefin) && $this->db->jdate($obj->datefin) < ($now - $conf->facture->fournisseur->warning_delay)) { + $response->nbtodolate++; + } } $this->db->free($resql); - return 1; + return $response; } else { diff --git a/htdocs/index.php b/htdocs/index.php index 55252f6533f..9439e14995d 100644 --- a/htdocs/index.php +++ b/htdocs/index.php @@ -291,7 +291,8 @@ print '
'; * Dolibarr Working Board with weather */ $showweather=empty($conf->global->MAIN_DISABLE_METEO)?1:0; -$rowspan=0; + +//Array that contains all BoardResponse classes to process them $dashboardlines=array(); print ''."\n"; @@ -309,18 +310,14 @@ print ''."\n"; // Do not include sections without management permission // +require DOL_DOCUMENT_ROOT.'/core/class/BoardResponse.class.php'; + // Number of actions to do (late) if (! empty($conf->agenda->enabled) && $user->rights->agenda->myactions->read) { include_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; $board=new ActionComm($db); - $board->load_board($user); - $board->warning_delay=$conf->actions->warning_delay/60/60/24; - $board->label=$langs->trans("ActionsToDo"); - $board->url=DOL_URL_ROOT.'/comm/action/listactions.php?status=todo&mainmenu=agenda'; - $board->img=img_object($langs->trans("Actions"),"action"); - $rowspan++; - $dashboardlines[]=$board; + $dashboardlines[] = $board->load_board($user); } // Number of customer orders a deal @@ -328,13 +325,8 @@ if (! empty($conf->commande->enabled) && $user->rights->commande->lire) { include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; $board=new Commande($db); - $board->load_board($user); - $board->warning_delay=$conf->commande->client->warning_delay/60/60/24; - $board->label=$langs->trans("OrdersToProcess"); - $board->url=DOL_URL_ROOT.'/commande/list.php?viewstatut=-3'; - $board->img=img_object($langs->trans("Orders"),"order"); - $rowspan++; - $dashboardlines[]=$board; + + $dashboardlines[] = $board->load_board($user); } // Number of suppliers orders a deal @@ -342,172 +334,89 @@ if (! empty($conf->fournisseur->enabled) && $user->rights->fournisseur->commande { include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php'; $board=new CommandeFournisseur($db); - $board->load_board($user); - $board->warning_delay=$conf->commande->fournisseur->warning_delay/60/60/24; - $board->label=$langs->trans("SuppliersOrdersToProcess"); - $board->url=DOL_URL_ROOT.'/fourn/commande/index.php'; - $board->img=img_object($langs->trans("Orders"),"order"); - $rowspan++; - $dashboardlines[]=$board; + + $dashboardlines[] = $board->load_board($user); } // Number of commercial proposals opened (expired) if (! empty($conf->propal->enabled) && $user->rights->propale->lire) { - $langs->load("propal"); - include_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; $board=new Propal($db); - $board->load_board($user,"opened"); - $board->warning_delay=$conf->propal->cloture->warning_delay/60/60/24; - $board->label=$langs->trans("PropalsToClose"); - $board->url=DOL_URL_ROOT.'/comm/propal/list.php?viewstatut=1'; - $board->img=img_object($langs->trans("Propals"),"propal"); - $rowspan++; - $dashboardlines[]=$board; -} + $dashboardlines[] = $board->load_board($user,"opened"); -// Number of commercial proposals CLOSED signed (billed) -if (! empty($conf->propal->enabled) && $user->rights->propale->lire) -{ - $langs->load("propal"); - - include_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; - $board=new Propal($db); - $board->load_board($user,"signed"); - $board->warning_delay=$conf->propal->facturation->warning_delay/60/60/24; - $board->label=$langs->trans("PropalsToBill"); - $board->url=DOL_URL_ROOT.'/comm/propal/list.php?viewstatut=2'; - $board->img=img_object($langs->trans("Propals"),"propal"); - $rowspan++; - $dashboardlines[]=$board; + // Number of commercial proposals CLOSED signed (billed) + $dashboardlines[] = $board->load_board($user,"signed"); } // Number of services enabled (delayed) if (! empty($conf->contrat->enabled) && $user->rights->contrat->lire) { - $langs->load("contracts"); - include_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php'; $board=new Contrat($db); - $board->load_board($user,"inactives"); - $board->warning_delay=$conf->contrat->services->inactifs->warning_delay/60/60/24; - $board->label=$langs->trans("BoardNotActivatedServices"); - $board->url=DOL_URL_ROOT.'/contrat/services.php?mainmenu=commercial&leftmenu=contracts&mode=0'; - $board->img=img_object($langs->trans("Contract"),"contract"); - $rowspan++; - $dashboardlines[]=$board; -} + $dashboardlines[] = $board->load_board($user,"inactives"); -// Number of active services (expired) -if (! empty($conf->contrat->enabled) && $user->rights->contrat->lire) -{ - $langs->load("contracts"); - - include_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php'; - $board=new Contrat($db); - $board->load_board($user,"expired"); - $board->warning_delay=$conf->contrat->services->expires->warning_delay/60/60/24; - $board->label=$langs->trans("BoardRunningServices"); - $board->url=DOL_URL_ROOT.'/contrat/services.php?mainmenu=commercial&leftmenu=contracts&mode=4&filter=expired'; - $board->img=img_object($langs->trans("Contract"),"contract"); - $rowspan++; - $dashboardlines[]=$board; + // Number of active services (expired) + $dashboardlines[] = $board->load_board($user,"expired"); } // Number of invoices customers (has paid) if (! empty($conf->facture->enabled) && $user->rights->facture->lire) { - $langs->load("bills"); - include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; $board=new Facture($db); - $board->load_board($user); - $board->warning_delay=$conf->facture->client->warning_delay/60/60/24; - $board->label=$langs->trans("CustomerBillsUnpaid"); - $board->url=DOL_URL_ROOT.'/compta/facture/impayees.php'; - $board->img=img_object($langs->trans("Bills"),"bill"); - $rowspan++; - $dashboardlines[]=$board; + $dashboardlines[] = $board->load_board($user); } // Number of supplier invoices (has paid) if (! empty($conf->fournisseur->enabled) && ! empty($conf->facture->enabled) && $user->rights->facture->lire) { - $langs->load("bills"); - include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php'; $board=new FactureFournisseur($db); - $board->load_board($user); - $board->warning_delay=$conf->facture->fournisseur->warning_delay/60/60/24; - $board->label=$langs->trans("SupplierBillsToPay"); - $board->url=DOL_URL_ROOT.'/fourn/facture/list.php?filtre=paye:0'; - $board->img=img_object($langs->trans("Bills"),"bill"); - $rowspan++; - $dashboardlines[]=$board; + $dashboardlines[] = $board->load_board($user); } // Number of transactions to conciliate if (! empty($conf->banque->enabled) && $user->rights->banque->lire && ! $user->societe_id) { - $langs->load("banks"); - include_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; $board=new Account($db); - $found=$board->load_board($user); - if ($found > 0) - { - $board->warning_delay=$conf->bank->rappro->warning_delay/60/60/24; - $board->label=$langs->trans("TransactionsToConciliate"); - $board->url=DOL_URL_ROOT.'/compta/bank/index.php?leftmenu=bank&mainmenu=bank'; - $board->img=img_object($langs->trans("TransactionsToConciliate"),"payment"); - $rowspan++; - $dashboardlines[]=$board; - } + $dashboardlines[] = $board->load_board($user); } // Number of cheque to send if (! empty($conf->banque->enabled) && $user->rights->banque->lire && ! $user->societe_id) { - $langs->load("banks"); - include_once DOL_DOCUMENT_ROOT.'/compta/paiement/cheque/class/remisecheque.class.php'; $board=new RemiseCheque($db); - $board->load_board($user); - $board->warning_delay=$conf->bank->cheque->warning_delay/60/60/24; - $board->label=$langs->trans("BankChecksToReceipt"); - $board->url=DOL_URL_ROOT.'/compta/paiement/cheque/index.php?leftmenu=checks&mainmenu=accountancy'; - $board->img=img_object($langs->trans("BankChecksToReceipt"),"payment"); - $rowspan++; - $dashboardlines[]=$board; + $dashboardlines[] = $board->load_board($user); } // Number of foundation members if (! empty($conf->adherent->enabled) && $user->rights->adherent->lire && ! $user->societe_id) { - $langs->load("members"); - include_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php'; $board=new Adherent($db); - $board->load_board($user); - $board->warning_delay=$conf->adherent->cotisation->warning_delay/60/60/24; - $board->label=$langs->trans("MembersWithSubscriptionToReceive"); - $board->url=DOL_URL_ROOT.'/adherents/list.php?mainmenu=members&statut=1'; - $board->img=img_object($langs->trans("Members"),"user"); - $rowspan++; - $dashboardlines[]=$board; + $dashboardlines[] = $board->load_board($user); } // Calculate total nb of late $totallate=0; -foreach($dashboardlines as $key => $board) -{ - if ($board->nbtodolate > 0) $totallate+=$board->nbtodolate; -} - -// Show dashboard $var=true; -foreach($dashboardlines as $key => $board) + +$valid_dashboardlines = array_filter($dashboardlines, function ($board) { + return $board instanceof BoardResponse; +}); + +$rowspan = count($valid_dashboardlines); + +foreach($valid_dashboardlines as $board) { + if ($board->nbtodolate > 0) { + $totallate += $board->nbtodolate; + } + + // Show dashboard + $var=!$var; print ''; print ''; @@ -531,8 +440,6 @@ foreach($dashboardlines as $key => $board) if ($rowspan <= 2) $options='height="24"'; // Weather logo is smaller if dashboard has few elements else if ($rowspan <= 3) $options='height="48"'; // Weather logo is smaller if dashboard has few elements print showWeather($totallate,$text,$options); - //print showWeather(0,''); - //print showWeather(40,$text); print ''; $showweather=0; } From bab0163c44ce34516f1c828d8064ad43e3ecf88f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Sun, 15 Feb 2015 15:07:24 +0100 Subject: [PATCH 118/173] Missing Copyright info --- htdocs/adherents/class/adherent.class.php | 1 + htdocs/comm/action/class/actioncomm.class.php | 1 + htdocs/comm/propal/class/propal.class.php | 2 +- htdocs/commande/class/commande.class.php | 2 +- htdocs/compta/bank/class/account.class.php | 1 + htdocs/compta/facture/class/facture.class.php | 2 +- htdocs/compta/paiement/cheque/class/remisecheque.class.php | 1 + htdocs/contrat/class/contrat.class.php | 2 +- htdocs/fourn/class/fournisseur.commande.class.php | 2 +- htdocs/fourn/class/fournisseur.facture.class.php | 2 +- htdocs/index.php | 1 + 11 files changed, 11 insertions(+), 6 deletions(-) diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 1f8ae82dcbd..890458b9a30 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -6,6 +6,7 @@ * Copyright (C) 2004 Benoit Mortier * Copyright (C) 2009-2012 Regis Houssin * Copyright (C) 2014 Alexandre Spangaro + * Copyright (C) 2015 Marcos García * * 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 diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index d13f32f157c..c0628635374 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -3,6 +3,7 @@ * Copyright (C) 2004-2011 Laurent Destailleur * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2011 Juanjo Menent + * Copyright (C) 2015 Marcos García * * 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 diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index 2c20e5ea1c7..cc24bcb219a 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -10,7 +10,7 @@ * Copyright (C) 2010-2011 Philippe Grand * Copyright (C) 2012-2014 Christophe Battarel * Copyright (C) 2013 Florian Henry - * Copyright (C) 2014 Marcos García + * Copyright (C) 2014-2015 Marcos García * * 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 diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 511af75a967..0b5df167931 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -7,7 +7,7 @@ * Copyright (C) 2011 Jean Heimburger * Copyright (C) 2012-2014 Christophe Battarel * Copyright (C) 2013 Florian Henry - * Copyright (C) 2014 Marcos García + * Copyright (C) 2014-2015 Marcos García * * 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 diff --git a/htdocs/compta/bank/class/account.class.php b/htdocs/compta/bank/class/account.class.php index c2929fb33a4..d2d9db7b378 100644 --- a/htdocs/compta/bank/class/account.class.php +++ b/htdocs/compta/bank/class/account.class.php @@ -5,6 +5,7 @@ * Copyright (C) 2004 Christophe Combelles * Copyright (C) 2005-2010 Regis Houssin * Copytight (C) 2013 Florian Henry + * Copyright (C) 2015 Marcos García * * 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 diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 3bbf76c79fe..fe7d48ee6b4 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -9,7 +9,7 @@ * Copyright (C) 2007 Franky Van Liedekerke * Copyright (C) 2010-2014 Juanjo Menent * Copyright (C) 2012-2014 Christophe Battarel - * Copyright (C) 2012-2014 Marcos García + * Copyright (C) 2012-2015 Marcos García * Copyright (C) 2012 Cédric Salvador * Copyright (C) 2012-2014 Raphaël Doursenaud * Copyright (C) 2013 Cedric Gross diff --git a/htdocs/compta/paiement/cheque/class/remisecheque.class.php b/htdocs/compta/paiement/cheque/class/remisecheque.class.php index 6bb1429d0a0..66083d3a84d 100644 --- a/htdocs/compta/paiement/cheque/class/remisecheque.class.php +++ b/htdocs/compta/paiement/cheque/class/remisecheque.class.php @@ -3,6 +3,7 @@ * Copyright (C) 2007-2011 Laurent Destailleur * Copyright (C) 2005-2009 Regis Houssin * Copyright (C) 2011 Juanjo Menent + * Copyright (C) 2015 Marcos García * * 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 diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 19001edf92c..14f406017ae 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -7,7 +7,7 @@ * Copyright (C) 2010-2014 Juanjo Menent * Copyright (C) 2013 Christophe Battarel * Copyright (C) 2013 Florian Henry - * Copyright (C) 2014 Marcos García + * Copyright (C) 2014-2015 Marcos García * * 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 diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index c5765772c3b..bebce59806a 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -5,7 +5,7 @@ * Copyright (C) 2007 Franky Van Liedekerke * Copyright (C) 2010-2014 Juanjo Menent * Copyright (C) 2010-2014 Philippe Grand - * Copyright (C) 2012-2014 Marcos García + * Copyright (C) 2012-2015 Marcos García * Copyright (C) 2013 Florian Henry * Copyright (C) 2013 Cédric Salvador * diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php index 3b029eff79c..b9d77903b60 100644 --- a/htdocs/fourn/class/fournisseur.facture.class.php +++ b/htdocs/fourn/class/fournisseur.facture.class.php @@ -7,7 +7,7 @@ * Copyright (C) 2010-2014 Juanjo Menent * Copyright (C) 2013 Philippe Grand * Copyright (C) 2013 Florian Henry - * Copyright (C) 2014 Marcos García + * Copyright (C) 2014-2015 Marcos García * * 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 diff --git a/htdocs/index.php b/htdocs/index.php index 9439e14995d..f79413e51ab 100644 --- a/htdocs/index.php +++ b/htdocs/index.php @@ -3,6 +3,7 @@ * Copyright (C) 2004-2013 Laurent Destailleur * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2011-2012 Juanjo Menent + * Copyright (C) 2015 Marcos García * * 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 From d5fd20e9119f148d82a8c67bd9f4f94e5a1182ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Sun, 15 Feb 2015 15:10:51 +0100 Subject: [PATCH 119/173] Renamed BoardResponse to WorkBoardResponse --- htdocs/adherents/class/adherent.class.php | 4 ++-- htdocs/comm/action/class/actioncomm.class.php | 4 ++-- htdocs/comm/propal/class/propal.class.php | 4 ++-- htdocs/commande/class/commande.class.php | 4 ++-- htdocs/compta/bank/class/account.class.php | 4 ++-- htdocs/compta/facture/class/facture.class.php | 4 ++-- .../compta/paiement/cheque/class/remisecheque.class.php | 4 ++-- htdocs/contrat/class/contrat.class.php | 4 ++-- ...oardResponse.class.php => WorkBoardResponse.class.php} | 4 ++-- htdocs/fourn/class/fournisseur.commande.class.php | 4 ++-- htdocs/fourn/class/fournisseur.facture.class.php | 4 ++-- htdocs/index.php | 8 +++++--- 12 files changed, 27 insertions(+), 25 deletions(-) rename htdocs/core/class/{BoardResponse.class.php => WorkBoardResponse.class.php} (94%) diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 890458b9a30..b275369be4e 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -1726,7 +1726,7 @@ class Adherent extends CommonObject * Load indicators for dashboard (this->nbtodo and this->nbtodolate) * * @param User $user Objet user - * @return BoardResponse|int <0 if KO, BoardResponse if OK + * @return WorkBoardResponse|int <0 if KO, WorkBoardResponse if OK */ function load_board($user) { @@ -1747,7 +1747,7 @@ class Adherent extends CommonObject { $langs->load("members"); - $response = new BoardResponse(); + $response = new WorkBoardResponse(); $response->warning_delay=$conf->adherent->cotisation->warning_delay/60/60/24; $response->label=$langs->trans("MembersWithSubscriptionToReceive"); $response->url=DOL_URL_ROOT.'/adherents/list.php?mainmenu=members&statut=1'; diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index c0628635374..e49b67604d5 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -716,7 +716,7 @@ class ActionComm extends CommonObject * Load indicators for dashboard (this->nbtodo and this->nbtodolate) * * @param User $user Objet user - * @return BoardResponse|int <0 if KO, BoardResponse if OK + * @return WorkBoardResponse|int <0 if KO, WorkBoardResponse if OK */ function load_board($user) { @@ -738,7 +738,7 @@ class ActionComm extends CommonObject { $now = dol_now(); - $response = new BoardResponse(); + $response = new WorkBoardResponse(); $response->warning_delay = $conf->actions->warning_delay/60/60/24; $response->label = $langs->trans("ActionsToDo"); $response->url = DOL_URL_ROOT.'/comm/action/listactions.php?status=todo&mainmenu=agenda'; diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index cc24bcb219a..80cfb5b3266 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -2345,7 +2345,7 @@ class Propal extends CommonObject * * @param User $user Object user * @param int $mode "opened" for proposal to close, "signed" for proposal to invoice - * @return BoardResponse|int <0 if KO, BoardResponse if OK + * @return WorkBoardResponse|int <0 if KO, WorkBoardResponse if OK */ function load_board($user,$mode) { @@ -2383,7 +2383,7 @@ class Propal extends CommonObject $label = $langs->trans("PropalsToBill"); } - $response = new BoardResponse(); + $response = new WorkBoardResponse(); $response->warning_delay = $delay_warning; $response->label = $label; $response->url = DOL_URL_ROOT.'/comm/propal/list.php?viewstatut='.$statut; diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 0b5df167931..19fd5c98a2b 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -2725,7 +2725,7 @@ class Commande extends CommonOrder * Load indicators for dashboard (this->nbtodo and this->nbtodolate) * * @param User $user Object user - * @return BoardResponse|int <0 if KO, BoardResponse if OK + * @return WorkBoardResponse|int <0 if KO, WorkBoardResponse if OK */ function load_board($user) { @@ -2751,7 +2751,7 @@ class Commande extends CommonOrder { $now=dol_now(); - $response = new BoardResponse(); + $response = new WorkBoardResponse(); $response->warning_delay=$conf->commande->client->warning_delay/60/60/24; $response->label=$langs->trans("OrdersToProcess"); $response->url=DOL_URL_ROOT.'/commande/list.php?viewstatut=-3'; diff --git a/htdocs/compta/bank/class/account.class.php b/htdocs/compta/bank/class/account.class.php index d2d9db7b378..85a6ad24b85 100644 --- a/htdocs/compta/bank/class/account.class.php +++ b/htdocs/compta/bank/class/account.class.php @@ -882,7 +882,7 @@ class Account extends CommonObject * * @param User $user Objet user * @param int $filteraccountid To get info for a particular account id - * @return BoardResponse|int <0 if KO, BoardResponse if OK + * @return WorkBoardResponse|int <0 if KO, WorkBoardResponse if OK */ function load_board($user,$filteraccountid=0) { @@ -905,7 +905,7 @@ class Account extends CommonObject $langs->load("banks"); $now=dol_now(); - $response = new BoardResponse(); + $response = new WorkBoardResponse(); $response->warning_delay=$conf->bank->rappro->warning_delay/60/60/24; $response->label=$langs->trans("TransactionsToConciliate"); $response->url=DOL_URL_ROOT.'/compta/bank/index.php?leftmenu=bank&mainmenu=bank'; diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index fe7d48ee6b4..71328871323 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -3085,7 +3085,7 @@ class Facture extends CommonInvoice * Load indicators for dashboard (this->nbtodo and this->nbtodolate) * * @param User $user Object user - * @return BoardResponse|int <0 if KO, BoardResponse if OK + * @return WorkBoardResponse|int <0 if KO, WorkBoardResponse if OK */ function load_board($user) { @@ -3112,7 +3112,7 @@ class Facture extends CommonInvoice $langs->load("bills"); $now=dol_now(); - $response = new BoardResponse(); + $response = new WorkBoardResponse(); $response->warning_delay=$conf->facture->client->warning_delay/60/60/24; $response->label=$langs->trans("CustomerBillsUnpaid"); $response->url=DOL_URL_ROOT.'/compta/facture/impayees.php'; diff --git a/htdocs/compta/paiement/cheque/class/remisecheque.class.php b/htdocs/compta/paiement/cheque/class/remisecheque.class.php index 66083d3a84d..88f9d573737 100644 --- a/htdocs/compta/paiement/cheque/class/remisecheque.class.php +++ b/htdocs/compta/paiement/cheque/class/remisecheque.class.php @@ -433,7 +433,7 @@ class RemiseCheque extends CommonObject * Load indicators for dashboard (this->nbtodo and this->nbtodolate) * * @param User $user Objet user - * @return BoardResponse|int <0 if KO, BoardResponse if OK + * @return WorkBoardResponse|int <0 if KO, WorkBoardResponse if OK */ function load_board($user) { @@ -456,7 +456,7 @@ class RemiseCheque extends CommonObject $langs->load("banks"); $now=dol_now(); - $response = new BoardResponse(); + $response = new WorkBoardResponse(); $response->warning_delay=$conf->bank->cheque->warning_delay/60/60/24; $response->label=$langs->trans("BankChecksToReceipt"); $response->url=DOL_URL_ROOT.'/compta/paiement/cheque/index.php?leftmenu=checks&mainmenu=accountancy'; diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 14f406017ae..9a5afc0aea1 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -1881,7 +1881,7 @@ class Contrat extends CommonObject * * @param User $user Objet user * @param string $mode "inactive" pour services a activer, "expired" pour services expires - * @return BoardResponse|int <0 if KO, BoardResponse if OK + * @return WorkBoardResponse|int <0 if KO, WorkBoardResponse if OK */ function load_board($user,$mode) { @@ -1929,7 +1929,7 @@ class Contrat extends CommonObject $label = $langs->trans("BoardRunningServices"); } - $response = new BoardResponse(); + $response = new WorkBoardResponse(); $response->warning_delay = $warning_delay/60/60/24; $response->label = $label; $response->url = $url; diff --git a/htdocs/core/class/BoardResponse.class.php b/htdocs/core/class/WorkBoardResponse.class.php similarity index 94% rename from htdocs/core/class/BoardResponse.class.php rename to htdocs/core/class/WorkBoardResponse.class.php index 9cf12e7a702..4cb0a1be0e7 100644 --- a/htdocs/core/class/BoardResponse.class.php +++ b/htdocs/core/class/WorkBoardResponse.class.php @@ -17,11 +17,11 @@ */ /** - * \file htdocs/core/class/BoardResponse.class.php + * \file htdocs/core/class/WorkBoardResponse.class.php * \brief Class that represents response of load_board functions */ -class BoardResponse +class WorkBoardResponse { /** diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index bebce59806a..300a1ad1260 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -2000,7 +2000,7 @@ class CommandeFournisseur extends CommonOrder * Load indicators for dashboard (this->nbtodo and this->nbtodolate) * * @param User $user Objet user - * @return BoardResponse|int <0 if KO, BoardResponse if OK + * @return WorkBoardResponse|int <0 if KO, WorkBoardResponse if OK */ function load_board($user) { @@ -2025,7 +2025,7 @@ class CommandeFournisseur extends CommonOrder { $now=dol_now(); - $response = new BoardResponse(); + $response = new WorkBoardResponse(); $response->warning_delay=$conf->commande->fournisseur->warning_delay/60/60/24; $response->label=$langs->trans("SuppliersOrdersToProcess"); $response->url=DOL_URL_ROOT.'/fourn/commande/index.php'; diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php index b9d77903b60..c8735362cca 100644 --- a/htdocs/fourn/class/fournisseur.facture.class.php +++ b/htdocs/fourn/class/fournisseur.facture.class.php @@ -1421,7 +1421,7 @@ class FactureFournisseur extends CommonInvoice * Load indicators for dashboard (this->nbtodo and this->nbtodolate) * * @param User $user Object user - * @return BoardResponse|int <0 if KO, BoardResponse if OK + * @return WorkBoardResponse|int <0 if KO, WorkBoardResponse if OK */ function load_board($user) { @@ -1442,7 +1442,7 @@ class FactureFournisseur extends CommonInvoice $langs->load("bills"); $now=dol_now(); - $response = new BoardResponse(); + $response = new WorkBoardResponse(); $response->warning_delay=$conf->facture->fournisseur->warning_delay/60/60/24; $response->label=$langs->trans("SupplierBillsToPay"); $response->url=DOL_URL_ROOT.'/fourn/facture/list.php?filtre=paye:0'; diff --git a/htdocs/index.php b/htdocs/index.php index f79413e51ab..54cda381489 100644 --- a/htdocs/index.php +++ b/htdocs/index.php @@ -293,7 +293,7 @@ print '
'; */ $showweather=empty($conf->global->MAIN_DISABLE_METEO)?1:0; -//Array that contains all BoardResponse classes to process them +//Array that contains all WorkBoardResponse classes to process them $dashboardlines=array(); print '
'.$board->img.''.$board->label.''.$board->nbtodo.'
'."\n"; @@ -311,7 +311,7 @@ print ''."\n"; // Do not include sections without management permission // -require DOL_DOCUMENT_ROOT.'/core/class/BoardResponse.class.php'; +require DOL_DOCUMENT_ROOT.'/core/class/WorkBoardResponse.class.php'; // Number of actions to do (late) if (! empty($conf->agenda->enabled) && $user->rights->agenda->myactions->read) @@ -404,8 +404,10 @@ if (! empty($conf->adherent->enabled) && $user->rights->adherent->lire && ! $use $totallate=0; $var=true; +//Remove any invalid response +//load_board can return an integer if failed or WorkBoardResponse if OK $valid_dashboardlines = array_filter($dashboardlines, function ($board) { - return $board instanceof BoardResponse; + return $board instanceof WorkBoardResponse; }); $rowspan = count($valid_dashboardlines); From 8a7d4ea71d229dce3afaf82911ebb3f3cf49523a Mon Sep 17 00:00:00 2001 From: delcroix Patrick Date: Sun, 15 Feb 2015 17:01:47 +0100 Subject: [PATCH 120/173] export on user to be able to choose the user for reporting purpose (no column named Name in the user table) --- htdocs/core/modules/modProjet.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/modProjet.class.php b/htdocs/core/modules/modProjet.class.php index 97ddc6afaba..4a534c937cc 100644 --- a/htdocs/core/modules/modProjet.class.php +++ b/htdocs/core/modules/modProjet.class.php @@ -194,7 +194,7 @@ class modProjet extends DolibarrModules 's.phone'=>'Text','s.siren'=>'Text','s.siret'=>'Text','s.ape'=>'Text','s.idprof4'=>'Text','s.code_compta'=>'Text','s.code_compta_fournisseur'=>'Text', 'p.rowid'=>"List:projet:ref",'p.ref'=>"Text",'p.datec'=>"Date",'p.dateo'=>"Date",'p.datee'=>"Date",'p.fk_statut'=>'Status','p.description'=>"Text", 'pt.dateo'=>"Date",'pt.datee'=>"Date",'pt.duration_effective'=>"Duree",'pt.planned_workload'=>"Number",'pt.progress'=>"Number",'pt.description'=>"Text", - 'ptt.task_date'=>'Date','ptt.task_duration'=>"Duree",'ptt.fk_user'=>"List:user:Name",'ptt.note'=>"Text"); + 'ptt.task_date'=>'Date','ptt.task_duration'=>"Duree",'ptt.fk_user'=>"List:user:CONCAT(lastname,' ',firstname)",'ptt.note'=>"Text"); $this->export_entities_array[$r]=array('s.rowid'=>"company",'s.nom'=>'company','s.address'=>'company','s.zip'=>'company','s.town'=>'company','s.fk_pays'=>'company', 's.phone'=>'company','s.siren'=>'company','s.siret'=>'company','s.ape'=>'company','s.idprof4'=>'company','s.code_compta'=>'company','s.code_compta_fournisseur'=>'company', From b00de9707aa322175f77d7a5b6ea76497d96648f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 15 Feb 2015 19:13:16 +0100 Subject: [PATCH 121/173] Work on expensereport module --- htdocs/compta/facture.php | 21 +-- .../pdf_standard.modules.php} | 17 +-- .../expensereport/modules_deplacement.php | 17 +++ .../core/modules/modExpenseReport.class.php | 16 +- htdocs/expensereport/ajax/ajaxprojet.php | 4 +- htdocs/expensereport/card.php | 60 +++++--- .../class/expensereport.class.php | 138 +++++++++--------- htdocs/expensereport/document.php | 1 + htdocs/expensereport/index.php | 1 + htdocs/expensereport/info.php | 7 +- htdocs/expensereport/list.php | 13 +- htdocs/expensereport/synchro_compta.php | 16 ++ 12 files changed, 183 insertions(+), 128 deletions(-) rename htdocs/core/modules/expensereport/{pdf_teclib.modules.php => doc/pdf_standard.modules.php} (97%) diff --git a/htdocs/compta/facture.php b/htdocs/compta/facture.php index cc4d2cff7e7..1f54c0b6805 100644 --- a/htdocs/compta/facture.php +++ b/htdocs/compta/facture.php @@ -569,11 +569,13 @@ if (empty($reshook)) // Boucle sur chaque taux de tva $i = 0; - foreach ($object->lines as $line) { - if($line->total_ht!=0) { // no need to create discount if amount is null - $amount_ht [$line->tva_tx] += $line->total_ht; - $amount_tva [$line->tva_tx] += $line->total_tva; - $amount_ttc [$line->tva_tx] += $line->total_ttc; + foreach ($object->lines as $line) + { + if ($line->total_ht!=0) + { // no need to create discount if amount is null + $amount_ht[$line->tva_tx] += $line->total_ht; + $amount_tva[$line->tva_tx] += $line->total_tva; + $amount_ttc[$line->tva_tx] += $line->total_ttc; $i ++; } } @@ -593,10 +595,11 @@ if (empty($reshook)) $error = 0; - foreach ($amount_ht as $tva_tx => $xxx) { - $discount->amount_ht = abs($amount_ht [$tva_tx]); - $discount->amount_tva = abs($amount_tva [$tva_tx]); - $discount->amount_ttc = abs($amount_ttc [$tva_tx]); + foreach ($amount_ht as $tva_tx => $xxx) + { + $discount->amount_ht = abs($amount_ht[$tva_tx]); + $discount->amount_tva = abs($amount_tva[$tva_tx]); + $discount->amount_ttc = abs($amount_ttc[$tva_tx]); $discount->tva_tx = abs($tva_tx); $result = $discount->create($user); diff --git a/htdocs/core/modules/expensereport/pdf_teclib.modules.php b/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php similarity index 97% rename from htdocs/core/modules/expensereport/pdf_teclib.modules.php rename to htdocs/core/modules/expensereport/doc/pdf_standard.modules.php index 6b3b59639e5..450007a0dc6 100755 --- a/htdocs/core/modules/expensereport/pdf_teclib.modules.php +++ b/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php @@ -1,8 +1,5 @@ - * Copyright (C) 2005-2010 Regis Houssin - * Copyright (C) 2008 Raphael Bertrand - * Copyright (C) 2010 Juanjo Menent +/* Copyright (C) 2015 Laurent Destailleur * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,16 +12,14 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * along with this program. If not, see . * or see http://www.gnu.org/ */ /** - * \file htdocs/expensereport/core/modules/expensereport/pdf_.modules.php - * \ingroup facture - * \brief File of class to generate invoices from crab model - * \author Laurent Destailleur + * \file htdocs/core/modules/expensereport/doc/pdf_standard.modules.php + * \ingroup expensereport + * \brief File of class to generate invoices from standard model */ dol_include_once("/expensereport/core/modules/expensereport/modules_expensereport.php"); @@ -664,7 +659,7 @@ class pdf_ extends ModeleExpenseReport /** * Affiche la grille des lignes de factures - * + * * @param $pdf Objet PDF * @param $tab_top Tab top * @param $tab_height Tab height diff --git a/htdocs/core/modules/expensereport/modules_deplacement.php b/htdocs/core/modules/expensereport/modules_deplacement.php index 707eaad54b8..86fa894dbaf 100755 --- a/htdocs/core/modules/expensereport/modules_deplacement.php +++ b/htdocs/core/modules/expensereport/modules_deplacement.php @@ -1,4 +1,21 @@ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see http://www.gnu.org/ + */ + require_once DOL_DOCUMENT_ROOT.'/core/class/commondocgenerator.class.php'; diff --git a/htdocs/core/modules/modExpenseReport.class.php b/htdocs/core/modules/modExpenseReport.class.php index 54d0496a4dd..edee0952b00 100755 --- a/htdocs/core/modules/modExpenseReport.class.php +++ b/htdocs/core/modules/modExpenseReport.class.php @@ -1,8 +1,6 @@ - * Copyright (C) 2004-2009 Laurent Destailleur - * Copyright (C) 2005-2010 Regis Houssin - * Copyright (C) 2011 Dimitri Mouillard +/* Copyright (C) 2011 Dimitri Mouillard + * Copyright (C) 2015 Laurent Destailleur * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,8 +13,8 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * along with this program. If not, see . + * or see http://www.gnu.org/ */ /** @@ -329,12 +327,12 @@ class modExpenseReport extends DolibarrModules } /** - * Function called when module is disabled. + * Function called when module is disabled. * Remove from database constants, boxes and permissions from Dolibarr database. * Data directories are not deleted. * - * @param string Options - * @return int 1 if OK, 0 if KO + * @param string $options Options + * @return int 1 if OK, 0 if KO */ function remove($options='') { diff --git a/htdocs/expensereport/ajax/ajaxprojet.php b/htdocs/expensereport/ajax/ajaxprojet.php index 0ab75543309..5246e7eb5d9 100755 --- a/htdocs/expensereport/ajax/ajaxprojet.php +++ b/htdocs/expensereport/ajax/ajaxprojet.php @@ -15,8 +15,8 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * along with this program. If not, see . + * or see http://www.gnu.org/ */ /** diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index 5a6f3a29b07..5b7045fd628 100755 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -14,8 +14,8 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * along with this program. If not, see . + * or see http://www.gnu.org/ */ /** @@ -927,7 +927,7 @@ else if ($action == 'remove_file') * View */ -llxHeader(); +llxHeader('', $langs->trans("ExpenseReport")); $html = new Form($db); $formfile = new FormFile($db); @@ -1028,7 +1028,7 @@ else $object = new ExpenseReport($db); $result = $object->fetch($id,$user); - if($result) + if ($result) { if ($object->fk_user_author != $user->id) { @@ -1237,7 +1237,7 @@ else } print ''; print ''; - print ''; + print ''; print ''; print ''; print ''; @@ -1261,9 +1261,12 @@ else print ''; print ''; print ''; } elseif($object->fk_c_expensereport_statuts==4) @@ -1271,9 +1274,12 @@ else print ''; print ''; print ''; print ''; print ''; @@ -1289,9 +1295,12 @@ else print ''; print ''; print ''; print ''; print ''; @@ -1302,9 +1311,12 @@ else print ''; print ''; print ''; print ''; @@ -1351,12 +1363,10 @@ else $sql = 'SELECT fde.rowid, fde.fk_expensereport, fde.fk_c_type_fees, fde.fk_projet, fde.date,'; $sql.= ' fde.fk_c_tva, fde.comments, fde.qty, fde.value_unit, fde.total_ht, fde.total_tva, fde.total_ttc,'; $sql.= ' ctf.code as type_fees_code, ctf.label as type_fees_libelle,'; - $sql.= ' pjt.rowid as projet_id, pjt.title as projet_title, pjt.ref as projet_ref,'; - $sql.= ' tva.rowid as tva_id, tva.taux as tva_taux'; + $sql.= ' pjt.rowid as projet_id, pjt.title as projet_title, pjt.ref as projet_ref'; $sql.= ' FROM '.MAIN_DB_PREFIX.'expensereport_det fde'; $sql.= ' INNER JOIN '.MAIN_DB_PREFIX.'c_type_fees ctf ON fde.fk_c_type_fees=ctf.id'; $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'projet pjt ON fde.fk_projet=pjt.rowid'; - $sql.= ' INNER JOIN '.MAIN_DB_PREFIX.'c_tva tva ON fde.fk_c_tva=tva.rowid'; $sql.= ' WHERE fde.fk_expensereport = '.$id; $resql = $db->query($sql); @@ -1503,7 +1513,7 @@ else //print ''; // Ajouter une ligne - if (($object->fk_c_expensereport_statuts==1 || $object->fk_c_expensereport_statuts==99) && $action != 'editline') + if (($object->fk_c_expensereport_statuts==0 || $object->fk_c_expensereport_statuts==99) && $action != 'editline') { print_fiche_titre($langs->trans("AddLine"),'',''); @@ -1570,6 +1580,10 @@ else } // Fin si c'est payé/validé } + else + { + dol_print_error($db); + } } // end edit or not edit dol_fiche_end(); @@ -1602,9 +1616,9 @@ if ($action != 'create' && $action != 'edit') * ET fk_user_author == user courant * Afficher : "Enregistrer" / "Modifier" / "Supprimer" */ - if($user->rights->expensereport->creer AND $object->fk_c_expensereport_statuts==1) + if ($user->rights->expensereport->creer AND $object->fk_c_expensereport_statuts==0) { - if($object->fk_user_author==$user->id) + if ($object->fk_user_author == $user->id) { // Modifier print ''.$langs->trans('ModifyInfoGen').''; diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php index 092a642b4b4..f5ff354ffbc 100755 --- a/htdocs/expensereport/class/expensereport.class.php +++ b/htdocs/expensereport/class/expensereport.class.php @@ -139,10 +139,10 @@ class ExpenseReport extends CommonObject $sql.= ", '".$this->db->idate($this->date_fin)."'"; $sql.= ", '".$this->db->idate($now)."'"; $sql.= ", ".($user->id > 0 ? $user->id:"null"); - $sql.= ", ".($this->fk_user_validator > 0 ? $this->fk_user_validator:2); - $sql.= ", ".($this->fk_c_expensereport_statuts > 1 ? $this->fk_c_expensereport_statuts:1); - $sql.= ", ".($this->fk_c_paiement > 0 ? $this->fk_c_paiement:2); - $sql.= ", ".($this->note?"'".$this->note."'":"null"); + $sql.= ", ".($this->fk_user_validator > 0 ? $this->fk_user_validator:"null"); + $sql.= ", ".($this->fk_c_expensereport_statuts > 1 ? $this->fk_c_expensereport_statuts:0); + $sql.= ", ".($this->fk_c_paiement > 0 ? $this->fk_c_paiement:"null"); + $sql.= ", ".($this->note?"'".$this->db->escape($this->note)."'":"null"); $sql.= ")"; dol_syslog(get_class($this)."::create sql=".$sql, LOG_DEBUG); @@ -263,11 +263,10 @@ class ExpenseReport extends CommonObject $sql.= " d.date_refuse, d.date_cancel,"; // ACTIONS $sql.= " d.total_ht, d.total_ttc, d.total_tva,"; // TOTAUX (int) $sql.= " d.date_debut, d.date_fin, d.date_create, d.date_valide, d.date_paiement,"; // DATES (datetime) - $sql.= " d.fk_user_author, d.fk_user_validator, d.fk_c_expensereport_statuts, d.fk_c_paiement,"; // FOREING KEY (int) + $sql.= " d.fk_user_author, d.fk_user_validator, d.fk_c_expensereport_statuts as status, d.fk_c_paiement,"; $sql.= " d.fk_user_valid, d.fk_user_paid,"; // FOREING KEY 2 (int) $sql.= " dp.libelle as libelle_paiement, dp.code as code_paiement"; // INNER JOIN paiement - $sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element." d"; - $sql.= " INNER JOIN ".MAIN_DB_PREFIX."c_paiement dp ON d.fk_c_paiement = dp.id"; + $sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element." d LEFT JOIN ".MAIN_DB_PREFIX."c_paiement dp ON d.fk_c_paiement = dp.id"; $sql.= " WHERE d.rowid = ".$id; $sql.= $restrict; @@ -276,71 +275,78 @@ class ExpenseReport extends CommonObject if ($result) { $obj = $db->fetch_object($result); - - $this->id = $obj->rowid; - $this->ref = $obj->ref_number; - $this->ref_number = $obj->ref_number; - $this->total_ht = $obj->total_ht; - $this->total_tva = $obj->total_tva; - $this->total_ttc = $obj->total_ttc; - $this->note = $obj->note; - $this->detail_refuse = $obj->detail_refuse; - $this->detail_cancel = $obj->detail_cancel; - - $this->date_debut = $obj->date_debut; - $this->date_fin = $obj->date_fin; - $this->date_paiement = $obj->date_paiement; - $this->date_valide = $obj->date_valide; - $this->date_create = $obj->date_create; - $this->date_refuse = $obj->date_refuse; - $this->date_cancel = $obj->date_cancel; - - $this->fk_user_author = $obj->fk_user_author; - $this->fk_user_validator = $obj->fk_user_validator; - $this->fk_user_valid = $obj->fk_user_valid; - $this->fk_user_paid = $obj->fk_user_paid; - $this->fk_user_refuse = $obj->fk_user_refuse; - $this->fk_user_cancel = $obj->fk_user_cancel; - - $user_author = new User($this->db); - $user_author->fetch($this->fk_user_author); - $this->user_author_infos = dolGetFirstLastname($user_author->firstname, $user_author->lastname); - - $user_approver = new User($this->db); - $user_approver->fetch($this->fk_user_validator); - $this->user_validator_infos = dolGetFirstLastname($user_approver->firstname, $user_approver->lastname); - - $this->fk_c_expensereport_statuts = $obj->fk_c_expensereport_statuts; - $this->fk_c_paiement = $obj->fk_c_paiement; - - if ($this->fk_c_expensereport_statuts==5 || $this->fk_c_expensereport_statuts==6) + if ($obj) { - $user_valid = new User($this->db); - $user_valid->fetch($this->fk_user_valid); - $this->user_valid_infos = dolGetFirstLastname($user_valid->firstname, $user_valid->lastname); - } + $this->id = $obj->rowid; + $this->ref = $obj->ref_number; + $this->ref_number = $obj->ref_number; + $this->total_ht = $obj->total_ht; + $this->total_tva = $obj->total_tva; + $this->total_ttc = $obj->total_ttc; + $this->note = $obj->note; + $this->detail_refuse = $obj->detail_refuse; + $this->detail_cancel = $obj->detail_cancel; - if ($this->fk_c_expensereport_statuts==6) + $this->date_debut = $obj->date_debut; + $this->date_fin = $obj->date_fin; + $this->date_paiement = $obj->date_paiement; + $this->date_valide = $obj->date_valide; + $this->date_create = $obj->date_create; + $this->date_refuse = $obj->date_refuse; + $this->date_cancel = $obj->date_cancel; + + $this->fk_user_author = $obj->fk_user_author; + $this->fk_user_validator = $obj->fk_user_validator; + $this->fk_user_valid = $obj->fk_user_valid; + $this->fk_user_paid = $obj->fk_user_paid; + $this->fk_user_refuse = $obj->fk_user_refuse; + $this->fk_user_cancel = $obj->fk_user_cancel; + + $user_author = new User($this->db); + $user_author->fetch($this->fk_user_author); + $this->user_author_infos = dolGetFirstLastname($user_author->firstname, $user_author->lastname); + + $user_approver = new User($this->db); + $user_approver->fetch($this->fk_user_validator); + $this->user_validator_infos = dolGetFirstLastname($user_approver->firstname, $user_approver->lastname); + + $this->fk_c_expensereport_statuts = $obj->status; + $this->status = $obj->status; + $this->fk_c_paiement = $obj->fk_c_paiement; + + if ($this->fk_c_expensereport_statuts==5 || $this->fk_c_expensereport_statuts==6) + { + $user_valid = new User($this->db); + $user_valid->fetch($this->fk_user_valid); + $this->user_valid_infos = dolGetFirstLastname($user_valid->firstname, $user_valid->lastname); + } + + if ($this->fk_c_expensereport_statuts==6) + { + $user_paid = new User($this->db); + $user_paid->fetch($this->fk_user_paid); + $this->user_paid_infos = dolGetFirstLastname($user_paid->firstname, $user_paid->lastname); + } + + $this->libelle_statut = $obj->libelle_statut; + $this->libelle_paiement = $obj->libelle_paiement; + $this->code_statut = $obj->code_statut; + $this->code_paiement = $obj->code_paiement; + + $this->lignes = array(); + + $result=$this->fetch_lines(); + + return 1; + } + else { - $user_paid = new User($this->db); - $user_paid->fetch($this->fk_user_paid); - $this->user_paid_infos = dolGetFirstLastname($user_paid->firstname, $user_paid->lastname); + return 0; } - - $this->libelle_statut = $obj->libelle_statut; - $this->libelle_paiement = $obj->libelle_paiement; - $this->code_statut = $obj->code_statut; - $this->code_paiement = $obj->code_paiement; - - $this->lignes = array(); - - $result=$this->fetch_lines(); - - return 1; } else { - $this->error=$db->error(); + $this->error=$db->lasterror(); return -1; } } @@ -980,7 +986,7 @@ class ExpenseReport extends CommonObject function updateline($rowid, $type_fees_id, $projet_id, $c_tva, $comments, $qty, $value_unit, $date, $expensereport_id) { - if ($this->fk_c_expensereport_statuts==1 || $this->fk_c_expensereport_statuts==99) + if ($this->fk_c_expensereport_statuts==0 || $this->fk_c_expensereport_statuts==99) { $this->db->begin(); diff --git a/htdocs/expensereport/document.php b/htdocs/expensereport/document.php index 65ee2a1bbaa..7c02617c9ad 100644 --- a/htdocs/expensereport/document.php +++ b/htdocs/expensereport/document.php @@ -19,6 +19,7 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * or see http://www.gnu.org/ */ /** diff --git a/htdocs/expensereport/index.php b/htdocs/expensereport/index.php index aae513618db..2ea024fb3b0 100644 --- a/htdocs/expensereport/index.php +++ b/htdocs/expensereport/index.php @@ -16,6 +16,7 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * or see http://www.gnu.org/ */ /** diff --git a/htdocs/expensereport/info.php b/htdocs/expensereport/info.php index 866e67ec04b..0349cfb12e1 100644 --- a/htdocs/expensereport/info.php +++ b/htdocs/expensereport/info.php @@ -14,6 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * or see http://www.gnu.org/ */ /** @@ -46,15 +47,15 @@ if ($id) $object = new ExpenseReport($db); $object->fetch($id); $object->info($id); - + $head = trip_prepare_head($object); - + dol_fiche_head($head, 'info', $langs->trans("TripCard"), 0, 'trip'); print '
'.$langs->trans("Statut").''.$object->libelle_statut.''.$object->getLibStatut(4).'
'.$langs->trans("Note").'
'.$langs->trans("VALIDATOR").''; - $userfee=new User($db); - $userfee->fetch($object->fk_user_validator); - print $userfee->getNomUrl(1); + if ($object->fk_user_validator > 0) + { + $userfee=new User($db); + $userfee->fetch($object->fk_user_validator); + print $userfee->getNomUrl(1); + } print '
'.$langs->trans("CANCEL_USER").''; - $userfee=new User($db); - $userfee->fetch($object->fk_user_cancel); - print $userfee->getNomUrl(1); + if ($object->fk_user_cancel > 0) + { + $userfee=new User($db); + $userfee->fetch($object->fk_user_cancel); + print $userfee->getNomUrl(1); + } print '
'.$langs->trans("MOTIF_CANCEL").'
'.$langs->trans("VALIDOR").''; - $userfee=new User($db); - $userfee->fetch($object->fk_user_valid); - print $userfee->getNomUrl(1); + if ($object->fk_user_valid > 0) + { + $userfee=new User($db); + $userfee->fetch($object->fk_user_valid); + print $userfee->getNomUrl(1); + } print '
'.$langs->trans("DATE_VALIDE").'
'.$langs->trans("AUTHOR").''; - $userfee=new User($db); - $userfee->fetch($object->fk_user_author); - print $userfee->getNomUrl(1); + if ($object->fk_user_author > 0) + { + $userfee=new User($db); + $userfee->fetch($object->fk_user_author); + print $userfee->getNomUrl(1); + } print '
'; dol_print_object_info($object); print '
'; - + print '
'; } diff --git a/htdocs/expensereport/list.php b/htdocs/expensereport/list.php index 0d2be8a7c45..b9ec3c8e400 100755 --- a/htdocs/expensereport/list.php +++ b/htdocs/expensereport/list.php @@ -15,8 +15,8 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * along with this program. If not, see . + * or see http://www.gnu.org/ */ /** @@ -81,7 +81,7 @@ $offset = $limit * $page; $pageprev = $page - 1; $pagenext = $page + 1; -$sql = "SELECT d.rowid, d.ref_number, d.total_ht, d.total_tva, d.total_ttc, d.fk_c_expensereport_statuts,"; +$sql = "SELECT d.rowid, d.ref_number, d.total_ht, d.total_tva, d.total_ttc, d.fk_c_expensereport_statuts as status,"; $sql.= " d.date_debut, d.date_fin,"; $sql.= " u.rowid as id_user, u.firstname, u.lastname"; $sql.= " FROM ".MAIN_DB_PREFIX."expensereport d\n"; @@ -266,8 +266,11 @@ if ($resql) print ''.price($objp->total_tva).''; print ''.price($objp->total_ttc).''; - $expensereporttmp->status=$objp->statut; - print ''.$expensereporttmp->getLibStatut(5).''; + $expensereporttmp->status=$objp->status; + print ''; + //print $objp->status; + print $expensereporttmp->getLibStatut(5); + print ''; print "\n"; $total_total_ht = $total_total_ht + $objp->total_ht; diff --git a/htdocs/expensereport/synchro_compta.php b/htdocs/expensereport/synchro_compta.php index 3f94da6eb1b..7d427c44fa1 100755 --- a/htdocs/expensereport/synchro_compta.php +++ b/htdocs/expensereport/synchro_compta.php @@ -1,4 +1,20 @@ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see http://www.gnu.org/ + */ require '../main.inc.php'; require_once(DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'); From eef1e17c61b845e6cd412b5d11403b0d92db3811 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 15 Feb 2015 19:38:20 +0100 Subject: [PATCH 122/173] Fix: default vat --- htdocs/core/class/html.form.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 7d2851f1b31..8f35a486dbe 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -3755,7 +3755,7 @@ class Form if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) { if (empty($conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS)) $defaulttx = $this->cache_vatrates[$num-1]['txtva']; - else $defaulttx=$conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS; + else $defaulttx=($conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS == 'none' ? '' : $conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS); } // Disabled if seller is not subject to VAT From 2a266b3a7e19a2e9f3f6fc3bf7284bf3524cbf77 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 15 Feb 2015 19:47:55 +0100 Subject: [PATCH 123/173] Clean code --- htdocs/expensereport/card.php | 7 +- .../class/expensereport.class.php | 242 +++++++++++++----- 2 files changed, 182 insertions(+), 67 deletions(-) diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index 5b7045fd628..4eabd0ea765 100755 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -1558,7 +1558,12 @@ else // Sélection TVA print ''; - print $form->load_tva('fk_c_tva', (isset($_POST["fk_c_tva"])?$_POST["fk_c_tva"]:-1), $mysoc, ''); + $defaultvat=-1; + if (! empty($conf->global->DEPLACEMENT_NO_DEFAULT_VAT)) $conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS = 'none'; + print ''; print ''; // Prix unitaire diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php index f5ff354ffbc..ee8555a6e69 100755 --- a/htdocs/expensereport/class/expensereport.class.php +++ b/htdocs/expensereport/class/expensereport.class.php @@ -397,9 +397,11 @@ class ExpenseReport extends CommonObject /** + * fetch_line_by_project * - * @param unknown_type $projectid - * @param unknown_type $user + * @param int $projectid Project id + * @param User $user User + * @return int <0 if KO, >0 if OK */ function fetch_line_by_project($projectid,$user='') { @@ -500,7 +502,14 @@ class ExpenseReport extends CommonObject } - function recalculer($id){ + /** + * recalculer + * + * @param int $id + * @return int <0 if KO, >0 if OK + */ + function recalculer($id) + { $sql = 'SELECT tt.total_ht, tt.total_ttc, tt.total_tva'; $sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element_line.' as tt'; $sql.= ' WHERE tt.'.$this->fk_element.' = '.$id; @@ -510,7 +519,8 @@ class ExpenseReport extends CommonObject dol_syslog('ExpenseReport::recalculer sql='.$sql,LOG_DEBUG); $result = $this->db->query($sql); - if($result): + if($result) + { $num = $this->db->num_rows($result); $i = 0; while ($i < $num): @@ -535,13 +545,20 @@ class ExpenseReport extends CommonObject dol_syslog('ExpenseReport::recalculer: Error '.$this->error,LOG_ERR); return -3; endif; - else: + } + else + { $this->error=$this->db->error(); dol_syslog('ExpenseReport::recalculer: Error '.$this->error,LOG_ERR); return -3; - endif; + } } + /** + * fetch_lines + * + * @return int <0 if OK, >0 if KO + */ function fetch_lines() { $sql = ' SELECT de.rowid, de.comments, de.qty, de.value_unit, de.date,'; @@ -602,11 +619,18 @@ class ExpenseReport extends CommonObject } } + + /** + * delete + * + * @param int $rowid Id to delete (optional) + * @return int <0 if KO, >0 if OK + */ function delete($rowid=0) { global $user,$langs,$conf; - if (!$rowid) $rowid=$this->id; + if (! $rowid) $rowid=$this->id; $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element_line.' WHERE '.$this->fk_element.' = '.$rowid; if ($this->db->query($sql)) @@ -635,7 +659,14 @@ class ExpenseReport extends CommonObject } } - function set_save($user){ + /** + * set_save + * + * @param User $user User + * @return int <0 if KO, >0 if OK + */ + function set_save($user) + { global $conf,$langs; $expld_car = (empty($conf->global->NDF_EXPLODE_CHAR))?"-":$conf->global->NDF_EXPLODE_CHAR; @@ -655,11 +686,13 @@ class ExpenseReport extends CommonObject $this->date_debut = $expld_date_debut[0].$expld_date_debut[1].$expld_date_debut[2]; // Création du ref_number suivant - if($ref_next): + if($ref_next) + { $this->ref_number = strtoupper($user->login).$expld_car."NDF".$this->ref_number.$expld_car.$this->date_debut; - endif; + } - if ($this->fk_c_expensereport_statuts != 2): + if ($this->fk_c_expensereport_statuts != 2) + { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; $sql.= " SET ref_number = '".$this->ref_number."', fk_c_expensereport_statuts = 2"; $sql.= " ,ref_number_int = $ref_number_int"; @@ -667,21 +700,30 @@ class ExpenseReport extends CommonObject dol_syslog(get_class($this)."::set_save sql=".$sql, LOG_DEBUG); - if ($this->db->query($sql)): + if ($this->db->query($sql)) + { return 1; - else: + } + else + { $this->error=$this->db->error(); return -1; - endif; - - else: - + } + } + else + { dol_syslog(get_class($this)."::set_save expensereport already with save status", LOG_WARNING); - - endif; + } } - function set_save_from_refuse($user){ + /** + * set_to_validate + * + * @param User $user User + * @return int <0 if KO, >0 if OK + */ + function set_save_from_refuse($user) + { global $conf,$langs; // Sélection de la date de début de la NDF @@ -697,31 +739,42 @@ class ExpenseReport extends CommonObject $expld_date_debut = explode("-",$this->date_debut); $this->date_debut = $expld_date_debut[0].$expld_date_debut[1].$expld_date_debut[2]; - if ($this->fk_c_expensereport_statuts != 2): + if ($this->fk_c_expensereport_statuts != 2) + { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; $sql.= " SET fk_c_expensereport_statuts = 2"; $sql.= ' WHERE rowid = '.$this->id; dol_syslog(get_class($this)."::set_save_from_refuse sql=".$sql, LOG_DEBUG); - if ($this->db->query($sql)): + if ($this->db->query($sql)) + { return 1; - else: - $this->error=$this->db->error(); + } + else + { + $this->error=$this->db->lasterror(); return -1; - endif; - - else: - + } + } + else + { dol_syslog(get_class($this)."::set_save_from_refuse expensereport already with save status", LOG_WARNING); - - endif; + } } - function set_valide($user){ + /** + * set_valide + * + * @param User $user User + * @return int <0 if KO, >0 if OK + */ + function set_valide($user) + { // date de validation $this->date_valide = $this->db->idate(gmmktime()); - if ($this->fk_c_expensereport_statuts != 5): + if ($this->fk_c_expensereport_statuts != 5) + { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; $sql.= " SET ref_number = '".$this->ref_number."', fk_c_expensereport_statuts = 5, fk_user_valid = ".$user->id; $sql.= ', date_valide='.$this->date_valide; @@ -735,13 +788,15 @@ class ExpenseReport extends CommonObject $this->error=$this->db->error(); return -1; endif; - else: + } + else + { dol_syslog(get_class($this)."::set_valide expensereport already with valide status", LOG_WARNING); - endif; + } } /** - * Refuse + * set_refuse * * @param User $user User * @param Details $details Details @@ -750,7 +805,8 @@ class ExpenseReport extends CommonObject { // date de refus $this->date_refuse = $this->db->idate(gmmktime()); - if ($this->fk_c_expensereport_statuts != 99): + if ($this->fk_c_expensereport_statuts != 99) + { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; $sql.= " SET ref_number = '".$this->ref_number."', fk_c_expensereport_statuts = 99, fk_user_refuse = ".$user->id; $sql.= ', date_refuse='.$this->date_refuse; @@ -765,14 +821,24 @@ class ExpenseReport extends CommonObject $this->error=$this->db->error(); return -1; endif; - else: + } + else + { dol_syslog(get_class($this)."::set_refuse expensereport already with refuse status", LOG_WARNING); - endif; + } } - function set_paid($user){ + /** + * set_paid + * + * @param User $user User + * @return int <0 if KO, >0 if OK + */ + function set_paid($user) + { $this->date_paiement = $this->db->idate(gmmktime()); - if ($this->fk_c_expensereport_statuts != 6): + if ($this->fk_c_expensereport_statuts != 6) + { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; $sql.= " SET fk_c_expensereport_statuts = 6, fk_user_paid = ".$user->id; $sql.= ', date_paiement='.$this->date_paiement; @@ -780,23 +846,34 @@ class ExpenseReport extends CommonObject dol_syslog(get_class($this)."::set_paid sql=".$sql, LOG_DEBUG); - if ($this->db->query($sql)): + if ($this->db->query($sql)) + { return 1; - else: + } + else + { $this->error=$this->db->error(); return -1; - endif; - else: + } + } + else + { dol_syslog(get_class($this)."::set_paid expensereport already with paid status", LOG_WARNING); - endif; + } } + /** + * set_unpaid + * + * @param User $user User + * @return int <0 if KO, >0 if OK + */ function set_unpaid($user) { - if ($this->fk_c_expensereport_statuts != 5) + if ($this->fk_c_deplacement_statuts != 5) { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; - $sql.= " SET fk_c_expensereport_statuts = 5"; + $sql.= " SET fk_c_deplacement_statuts = 5"; $sql.= ' WHERE rowid = '.$this->id; dol_syslog(get_class($this)."::set_unpaid sql=".$sql, LOG_DEBUG); @@ -810,16 +887,22 @@ class ExpenseReport extends CommonObject } else { - dol_syslog(get_class($this)."::set_unpaid expensereport already with unpaid status", LOG_WARNING); + dol_syslog(get_class($this)."::set_unpaid deplacement already with unpaid status", LOG_WARNING); } } + /** + * set_draft + * + * @param User $user User + * @return int <0 if KO, >0 if OK + */ function set_draft($user) { - if ($this->fk_c_expensereport_statuts != 1) + if ($this->fk_c_deplacement_statuts != 1) { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; - $sql.= " SET fk_c_expensereport_statuts = 1,"; + $sql.= " SET fk_c_deplacement_statuts = 1,"; //$sql.= " , ref_number = '(PROV".$this->id.")', ref_number_int = 0"; $sql.= " ref_number_int = 0"; $sql.= ' WHERE rowid = '.$this->id; @@ -835,53 +918,80 @@ class ExpenseReport extends CommonObject } else { - dol_syslog(get_class($this)."::set_draft expensereport already with draft status", LOG_WARNING); + dol_syslog(get_class($this)."::set_draft deplacement already with draft status", LOG_WARNING); } } + /** + * set_to_validate + * + * @param User $user User + * @return int <0 if KO, >0 if OK + */ function set_to_valide($user) { - if ($this->fk_c_expensereport_statuts != 2): + if ($this->fk_c_expensereport_statuts != 2) + { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; $sql.= " SET fk_c_expensereport_statuts = 2, fk_user_validator = ".$this->fk_user_validator; $sql.= ' WHERE rowid = '.$this->id; dol_syslog(get_class($this)."::set_to_valide sql=".$sql, LOG_DEBUG); - if ($this->db->query($sql)): + if ($this->db->query($sql)) + { return 1; - else: + } + else + { $this->error=$this->db->error(); return -1; - endif; - else: + } + } + else + { dol_syslog(get_class($this)."::set_to_valide expensereport already with to-valide status", LOG_WARNING); - endif; + } } - function set_cancel($user,$detail){ + /** + * set_cancel + * + * @param User $user User + * @param string $detail Detail + * @return int <0 if KO, >0 if OK + */ + function set_cancel($user,$detail) + { $this->date_cancel = $this->db->idate(gmmktime()); - if ($this->fk_c_expensereport_statuts != 4): + if ($this->fk_c_expensereport_statuts != 4) + { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; $sql.= " SET fk_c_expensereport_statuts = 4, fk_user_cancel = ".$user->id; $sql.= ', date_cancel='.$this->date_cancel; - $sql.= " ,detail_cancel='".addslashes($detail)."'"; + $sql.= " ,detail_cancel='".$this->db->escape($detail)."'"; $sql.= ' WHERE rowid = '.$this->id; dol_syslog(get_class($this)."::set_cancel sql=".$sql, LOG_DEBUG); - if ($this->db->query($sql)): + if ($this->db->query($sql)) + { return 1; - else: + } + else + { $this->error=$this->db->error(); return -1; - endif; - else: + } + } + else + { dol_syslog(get_class($this)."::set_cancel expensereport already with cancel status", LOG_WARNING); - endif; + } } - function getNextNumRef(){ + function getNextNumRef() + { global $conf; $expld_car = (empty($conf->global->NDF_EXPLODE_CHAR))?"-":$conf->global->NDF_EXPLODE_CHAR; From 2e0b2fb012de46ebf136df6c42876ecabed4ca06 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 15 Feb 2015 22:49:23 +0100 Subject: [PATCH 124/173] Work on expensereport module --- htdocs/core/class/commonobject.class.php | 3 +- htdocs/core/lib/expensereport.lib.php | 61 +++ htdocs/expensereport/card.php | 415 ++++++++---------- .../class/expensereport.class.php | 224 +++++++--- htdocs/expensereport/document.php | 6 +- htdocs/expensereport/export_csv.php | 6 +- htdocs/expensereport/info.php | 6 +- htdocs/expensereport/list.php | 37 +- htdocs/expensereport/synchro_compta.php | 26 +- htdocs/install/mysql/data/llx_c_type_fees.sql | 2 +- .../install/mysql/migration/3.7.0-3.8.0.sql | 9 +- .../mysql/tables/llx_expensereport.sql | 3 +- .../mysql/tables/llx_expensereport_det.sql | 2 +- htdocs/langs/en_US/projects.lang | 2 +- htdocs/projet/class/project.class.php | 4 + htdocs/projet/element.php | 12 +- 16 files changed, 472 insertions(+), 346 deletions(-) create mode 100644 htdocs/core/lib/expensereport.lib.php diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 6d464cceb29..b4aff6002d0 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -1792,7 +1792,8 @@ abstract class CommonObject if (! $resql) { $error++; - $this->error=$this->db->error(); + $this->error=$this->db->lasterror(); + $this->error[]=$this->db->lasterror(); } } diff --git a/htdocs/core/lib/expensereport.lib.php b/htdocs/core/lib/expensereport.lib.php new file mode 100644 index 00000000000..f46e6416ec6 --- /dev/null +++ b/htdocs/core/lib/expensereport.lib.php @@ -0,0 +1,61 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see http://www.gnu.org/ + */ + +/** + * \file htdocs/core/lib/expensereport.lib.php + * \brief Functions for module expensereport + */ + +/** + * Prepare array with list of tabs + * + * @param Object $object Object related to tabs + * @return array Array of tabs to show + */ +function expensereport_prepare_head($object) +{ + global $langs, $conf; + + $h = 0; + $head = array(); + + $head[$h][0] = DOL_URL_ROOT . '/expensereport/card.php?id=' . $object->id; + $head[$h][1] = $langs->trans("Card"); + $head[$h][2] = 'card'; + $h++; + + // Show more tabs from modules + // Entries must be declared in modules descriptor with line + // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab + // $this->tabs = array('entity:-tabname); to remove a tab + complete_head_from_modules($conf,$langs,$object,$head,$h,'expensereport'); + + $head[$h][0] = DOL_URL_ROOT.'/expensereport/document.php?id='.$object->id; + $head[$h][1] = $langs->trans("Documents"); + $head[$h][2] = 'documents'; + $h++; + + $head[$h][0] = DOL_URL_ROOT . '/expensereport/info.php?id=' . $object->id; + $head[$h][1] = $langs->trans("Info"); + $head[$h][2] = 'info'; + $h++; + + complete_head_from_modules($conf,$langs,$object,$head,$h,'expensereport','remove'); + + return $head; +} diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index 4eabd0ea765..b555746c05b 100755 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -29,17 +29,20 @@ require_once(DOL_DOCUMENT_ROOT."/core/class/html.formfile.class.php"); require_once(DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'); require_once(DOL_DOCUMENT_ROOT."/core/class/html.formmail.class.php"); require_once(DOL_DOCUMENT_ROOT."/core/class/html.formprojet.class.php"); +require_once(DOL_DOCUMENT_ROOT."/projet/class/project.class.php"); require_once(DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'); -require_once(DOL_DOCUMENT_ROOT."/core/lib/trip.lib.php"); +require_once(DOL_DOCUMENT_ROOT."/core/lib/expensereport.lib.php"); dol_include_once('/expensereport/core/modules/expensereport/modules_expensereport.php'); dol_include_once("/expensereport/class/expensereport.class.php"); $langs->load("trips"); $action=GETPOST('action'); +$cancel=GETPOST('cancel'); $date_start = dol_mktime(0, 0, 0, GETPOST('date_debutmonth'), GETPOST('date_debutday'), GETPOST('date_debutyear')); $date_end = dol_mktime(0, 0, 0, GETPOST('date_finmonth'), GETPOST('date_finday'), GETPOST('date_finyear')); - +$date = dol_mktime(0, 0, 0, GETPOST('datemonth'), GETPOST('dateday'), GETPOST('dateyear')); +$fk_projet=GETPOST('fk_projet'); // If socid provided by ajax company selector if (! empty($_REQUEST['socid_id'])) @@ -54,8 +57,6 @@ $id=GETPOST("id",'int'); if ($user->societe_id) $socid=$user->societe_id; $result = restrictedArea($user, 'expensereport', 0, 'expensereport'); -$mesg=""; - // Hack to use expensereport dir $rootfordata = DOL_DATA_ROOT; @@ -74,6 +75,8 @@ $conf->expensereport->dir_output = $rootfordata.'/expensereport'; * Actions */ +if ($cancel) $action=''; + if ($action == 'confirm_delete' && $_GET["confirm"] == "yes" && $id > 0 && $user->rights->expensereport->supprimer) { $object = new ExpenseReport($db); @@ -103,10 +106,12 @@ if ($action == 'add' && $user->rights->expensereport->creer) if ($object->periode_existe($user,dol_print_date($object->date_debut, 'dayrfc'),dol_print_date($object->date_fin, 'dayrfc'))) { + $error++; setEventMessage($langs->trans("ErrorDoubleDeclaration"),'errors'); $action='create'; } - else + + if (! $error) { $db->begin(); @@ -130,7 +135,7 @@ if ($action == 'add' && $user->rights->expensereport->creer) if ($action == 'update' && $user->rights->expensereport->creer) { $object = new ExpenseReport($db); - $object->fetch($_POST['id'],$user); + $object->fetch($id); $object->date_debut = $date_start; $object->date_fin = $date_end; @@ -158,7 +163,7 @@ if ($action == 'update' && $user->rights->expensereport->creer) if ($action == "confirm_save" && GETPOST("confirm") == "yes" && $id > 0 && $user->rights->expensereport->creer) { $object = new ExpenseReport($db); - $object->fetch($id,$user); + $object->fetch($id); $result = $object->set_save($user); if ($result > 0) { @@ -195,8 +200,8 @@ if ($action == "confirm_save" && GETPOST("confirm") == "yes" && $id > 0 && $user if($resultPDF): // ATTACHMENT $filename=array(); $filedir=array(); $mimetype=array(); - array_push($filename,dol_sanitizeFileName($object->ref_number).".pdf"); - array_push($filedir,$conf->expensereport->dir_output . "/" . dol_sanitizeFileName($object->ref_number) . "/" . dol_sanitizeFileName($object->ref_number).".pdf"); + array_push($filename,dol_sanitizeFileName($object->ref).".pdf"); + array_push($filedir,$conf->expensereport->dir_output . "/" . dol_sanitizeFileName($object->ref) . "/" . dol_sanitizeFileName($object->ref).".pdf"); array_push($mimetype,"application/pdf"); // PREPARE SEND @@ -232,7 +237,7 @@ if ($action == "confirm_save" && GETPOST("confirm") == "yes" && $id > 0 && $user if ($action == "confirm_save_from_refuse" && $_GET["confirm"] == "yes" && $id > 0 && $user->rights->expensereport->creer) { $object = new ExpenseReport($db); - $object->fetch($id,$user); + $object->fetch($id); $result = $object->set_save_from_refuse($user); if ($result > 0) { @@ -256,7 +261,7 @@ if ($action == "confirm_save_from_refuse" && $_GET["confirm"] == "yes" && $id > $dateRefusEx = explode(" ",$object->date_refuse); $message = "Bonjour {$destinataire->firstname},\n\n"; - $message.= "Le {$dateRefusEx[0]} à {$dateRefusEx[1]} vous avez refusé d'approuver la note de frais \"{$object->ref_number}\". Vous aviez émis le motif suivant : {$object->detail_refuse}\n\n"; + $message.= "Le {$dateRefusEx[0]} à {$dateRefusEx[1]} vous avez refusé d'approuver la note de frais \"{$object->ref}\". Vous aviez émis le motif suivant : {$object->detail_refuse}\n\n"; $message.= "L'auteur vient de modifier la note de frais, veuillez trouver la nouvelle version en pièce jointe.\n"; $message.= "- Déclarant : {$expediteur->firstname} {$expediteur->lastname}\n"; $message.= "- Période : du {$object->date_debut} au {$object->date_fin}\n"; @@ -270,8 +275,8 @@ if ($action == "confirm_save_from_refuse" && $_GET["confirm"] == "yes" && $id > if($resultPDF): // ATTACHMENT $filename=array(); $filedir=array(); $mimetype=array(); - array_push($filename,dol_sanitizeFileName($object->ref_number).".pdf"); - array_push($filedir,$conf->expensereport->dir_output . "/" . dol_sanitizeFileName($object->ref_number) . "/" . dol_sanitizeFileName($object->ref_number).".pdf"); + array_push($filename,dol_sanitizeFileName($object->ref).".pdf"); + array_push($filedir,$conf->expensereport->dir_output . "/" . dol_sanitizeFileName($object->ref) . "/" . dol_sanitizeFileName($object->ref_number).".pdf"); array_push($mimetype,"application/pdf"); // PREPARE SEND @@ -308,16 +313,13 @@ if ($action == "confirm_save_from_refuse" && $_GET["confirm"] == "yes" && $id > if ($action == "confirm_validate" && GETPOST("confirm") == "yes" && $id > 0 && $user->rights->expensereport->to_validate) { $object = new ExpenseReport($db); - $object->fetch($id,$user); + $object->fetch($id); $result = $object->set_valide($user); if ($result > 0) { if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) { - $object = new ExpenseReport($db); - $object->fetch($id,$user); - // Send mail // TO @@ -338,7 +340,7 @@ if ($action == "confirm_validate" && GETPOST("confirm") == "yes" && $id > 0 && $ // CONTENT $message = "Bonjour {$destinataire->firstname},\n\n"; - $message.= "Votre note de frais \"{$object->ref_number}\" vient d'être approuvé!\n"; + $message.= "Votre note de frais \"{$object->ref}\" vient d'être approuvé!\n"; $message.= "- Approbateur : {$expediteur->firstname} {$expediteur->lastname}\n"; $message.= "- Lien : {$dolibarr_main_url_root}/expensereport/card.php?id={$object->id}\n\n"; $message.= "Bien cordialement,\n' SI"; @@ -350,12 +352,12 @@ if ($action == "confirm_validate" && GETPOST("confirm") == "yes" && $id > 0 && $ if($resultPDF): // ATTACHMENT $filename=array(); $filedir=array(); $mimetype=array(); - array_push($filename,dol_sanitizeFileName($object->ref_number).".pdf"); + array_push($filename,dol_sanitizeFileName($object->ref).".pdf"); array_push($filedir, $conf->expensereport->dir_output. "/". - dol_sanitizeFileName($object->ref_number) . + dol_sanitizeFileName($object->ref) . "/". - dol_sanitizeFileName($object->ref_number). + dol_sanitizeFileName($object->ref). ".pdf" ); array_push($mimetype,"application/pdf"); @@ -394,16 +396,13 @@ if ($action == "confirm_validate" && GETPOST("confirm") == "yes" && $id > 0 && $ if ($action == "confirm_refuse" && $_POST['confirm']=="yes" && !empty($_POST['detail_refuse']) && $id > 0 && $user->rights->expensereport->to_validate) { $object = new ExpenseReport($db); - $object->fetch($id,$user); + $object->fetch($id); $result = $object->set_refuse($user,$_POST['detail_refuse']); if ($result > 0) { if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) { - $object = new ExpenseReport($db); - $object->fetch($id,$user); - // Send mail // TO @@ -421,7 +420,7 @@ if ($action == "confirm_refuse" && $_POST['confirm']=="yes" && !empty($_POST['de // CONTENT $message = "Bonjour {$destinataire->firstname},\n\n"; - $message.= "Votre note de frais \"{$object->ref_number}\" vient d'être refusée.\n"; + $message.= "Votre note de frais \"{$object->ref}\" vient d'être refusée.\n"; $message.= "- Refuseur : {$expediteur->firstname} {$expediteur->lastname}\n"; $message.= "- Motif de refus : {$_POST['detail_refuse']}\n"; $message.= "- Lien : {$dolibarr_main_url_root}/expensereport/card.php?id={$object->id}\n\n"; @@ -458,7 +457,8 @@ if ($action == "confirm_refuse" && $_POST['confirm']=="yes" && !empty($_POST['de if ($action == "confirm_cancel" && GETPOST('confirm')=="yes" && !empty($_POST['detail_cancel']) && $id > 0 && $user->rights->expensereport->to_validate) { $object = new ExpenseReport($db); - $object->fetch($id,$user); + $object->fetch($id); + if($user->id == $object->fk_user_validator) { $result = $object->set_cancel($user,$_POST['detail_cancel']); @@ -467,8 +467,6 @@ if ($action == "confirm_cancel" && GETPOST('confirm')=="yes" && !empty($_POST['d { if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) { - $object = new ExpenseReport($db); - $object->fetch($id,$user); // Send mail @@ -487,7 +485,7 @@ if ($action == "confirm_cancel" && GETPOST('confirm')=="yes" && !empty($_POST['d // CONTENT $message = "Bonjour {$destinataire->firstname},\n\n"; - $message.= "Votre note de frais \"{$object->ref_number}\" vient d'être annulée.\n"; + $message.= "Votre note de frais \"{$object->ref}\" vient d'être annulée.\n"; $message.= "- Annuleur : {$expediteur->firstname} {$expediteur->lastname}\n"; $message.= "- Motif d'annulation : {$_POST['detail_cancel']}\n"; $message.= "- Lien : {$dolibarr_main_url_root}/expensereport/card.php?id={$object->id}\n\n"; @@ -532,14 +530,12 @@ if ($action == "confirm_paid" && $_GET['confirm']=="yes" && $id > 0 && $user->ri { $object = new ExpenseReport($db); $object->fetch($id,$user); + $result = $object->set_paid($user); if ($result > 0) { if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) { - $object = new ExpenseReport($db); - $object->fetch($id,$user); - // Send mail // TO @@ -557,7 +553,7 @@ if ($action == "confirm_paid" && $_GET['confirm']=="yes" && $id > 0 && $user->ri // CONTENT $message = "Bonjour {$destinataire->firstname},\n\n"; - $message.= "Votre note de frais \"{$object->ref_number}\" vient d'être payée.\n"; + $message.= "Votre note de frais \"{$object->ref}\" vient d'être payée.\n"; $message.= "- Payeur : {$expediteur->firstname} {$expediteur->lastname}\n"; $message.= "- Lien : {$dolibarr_main_url_root}/expensereport/card.php?id={$object->id}\n\n"; $message.= "Bien cordialement,\n' SI"; @@ -579,13 +575,13 @@ if ($action == "confirm_paid" && $_GET['confirm']=="yes" && $id > 0 && $user->ri $idAccount = 1; $object = new ExpenseReport($db); - $object->fetch($idTrip,$user); + $object->fetch($idTrip); $datePaiement = explode("-",$object->date_paiement); $dateop = dol_mktime(12,0,0,$datePaiement[1],$datePaiement[2],$datePaiement[0]); $operation = $object->code_paiement; - $label = "Règlement ".$object->ref_number; + $label = "Règlement ".$object->ref; $amount = - price2num($object->total_ttc); $num_chq = ''; $cat1 = ''; @@ -629,7 +625,7 @@ if ($action == "confirm_paid" && $_GET['confirm']=="yes" && $id > 0 && $user->ri if ($action == "confirm_brouillonner" && $_GET['confirm']=="yes" && $id > 0 && $user->rights->expensereport->creer) { $object = new ExpenseReport($db); - $object->fetch($id,$user); + $object->fetch($id); if($user->id == $object->fk_user_author OR $user->id == $object->fk_user_validator) { $result = $object->set_draft($user); @@ -651,133 +647,107 @@ if ($action == "confirm_brouillonner" && $_GET['confirm']=="yes" && $id > 0 && $ if ($action == "addline") { + $error = 0; + $db->begin(); - $object_ligne = new ExpenseReportLigne($db); + $object_ligne = new ExpenseReportLine($db); - $object_ligne->comments = empty($_POST['comments'])?"Aucun commentaire.":$_POST['comments']; + $object_ligne->comments = GETPOST('comments'); $object_ligne->qty = empty($_POST['qty'])?1:$_POST['qty']; - // Convertion de "," en "." dans le nombre entré dans le champ - if(preg_match("#,#",$_POST['value_unit'])) - { - $object_ligne->value_unit = preg_replace("#,#",".",$_POST['value_unit']); - } - else - { - $object_ligne->value_unit = $_POST['value_unit']; - } + $object_ligne->value_unit = price2num(GETPOST('value_unit')); + $object_ligne->value_unit = price2num($object_ligne->value_unit,'MU'); - $object_ligne->value_unit = number_format($object_ligne->value_unit,3,'.',''); + $object_ligne->date = $date; - $date = explode("/",$_POST['date']); - $object_ligne->date = $date[2]."-".$date[1]."-".$date[0]; + $object_ligne->fk_c_type_fees = GETPOST('fk_c_type_fees'); - $object_ligne->fk_c_type_fees = empty($_POST['fk_c_type_fees'])?1:$_POST['fk_c_type_fees']; - - // Get tax id from rate - $tva_tx=GETPOST('fk_c_tva'); - $sql = "SELECT t.rowid, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type"; - $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as p"; - $sql .= " WHERE t.fk_pays = p.rowid AND p.code = '".$mysoc->country_code."'"; - $sql .= " AND t.taux = ".$db->escape($tva_tx)." AND t.active = 1"; - - dol_syslog("get_localtax sql=".$sql); - $resql=$db->query($sql); - if ($resql) - { - $obj = $db->fetch_object($resql); - $tva=$obj->rowid; - } - else dol_print_error($db); - - // Force la TVA à 0% lorsque c'est du transport - if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) - { - if ($object_ligne->fk_c_type_fees==10) - { - $tva = 15; // TODO A virer le hardcoding - } - } + $tva=GETPOST('vatrate'); $object_ligne->fk_c_tva = $tva; - $object_ligne->fk_projet = $_POST['fk_projet']; + $object_ligne->fk_projet = $fk_projet; - // Tests des données rentrées - $error = false; + if (! GETPOST('fk_c_type_fees') > 0) + { + $error++; + setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("Type")),'errors'); + $action=''; + } + if (GETPOST('vatrate') < 0 || GETPOST('vatrate') == '') + { + $error++; + setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("Vat")),'errors'); + $action=''; + } // Si aucun projet n'est défini - if (empty($object_ligne->fk_projet) || $object_ligne->fk_projet==-1) + if ($conf->projet->enabled) { - $error = true; - $text_error[] = "NO_PROJECT"; + if (empty($object_ligne->fk_projet) || $object_ligne->fk_projet==-1) + { + $error++; + setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("Project")), 'errors'); + } } // Si aucune date n'est rentrée - if($object_ligne->date=="--"): - $error = true; - $text_error[] = "NO_DATE"; - endif; + if (empty($object_ligne->date) || $object_ligne->date=="--") + { + $error++; + setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("Date")), 'errors'); + } // Si aucun prix n'est rentré - if($object_ligne->value_unit==0): - $error = true; - $text_error[] = "NO_PRICE"; - endif; + if($object_ligne->value_unit==0) + { + $error++; + setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("UP")), 'errors'); + } // S'il y'a eu au moins une erreur - if($error) - { - $mesg = implode(",",$text_error); - Header("Location: ".$_SERVER["PHP_SELF"]."?id=".$_POST['fk_expensereport']."&mesg=$mesg"); - exit; - } - else + if (! $error) { $object_ligne->fk_expensereport = $_POST['fk_expensereport']; - $object_ligne->fetch_taux($object_ligne->fk_c_tva); - // Calculs des totos $object_ligne->total_ttc = $object_ligne->value_unit * $object_ligne->qty; - $object_ligne->total_ttc = number_format($object_ligne->total_ttc,2,'.',''); + $object_ligne->total_ttc = price2num($object_ligne->total_ttc,'MT'); - $tx_tva = $object_ligne->tva_taux/100; + $object_ligne->tva_taux = GETPOST('vatrate'); + + $tx_tva = $object_ligne->tva_taux / 100; $tx_tva = $tx_tva + 1; $object_ligne->total_ht = $object_ligne->total_ttc / $tx_tva; $object_ligne->total_ht = price2num($object_ligne->total_ht,'MT'); $object_ligne->total_tva = $object_ligne->total_ttc - $object_ligne->total_ht; - // Fin calculs des totos $result = $object_ligne->insert(); if ($result > 0) { - $object = new ExpenseReport($db); - $object->fetch($_POST['fk_expensereport'],$user); - $object->update_totaux_add($object_ligne->total_ht,$object_ligne->total_tva); - $db->commit(); - Header("Location: ".$_SERVER["PHP_SELF"]."?id=".$_POST['fk_expensereport']); + header("Location: ".$_SERVER["PHP_SELF"]."?id=".$_GET['id']); exit; } else { dol_print_error($db,$object->error); $db->rollback(); - exit; } } + + $action=''; } if ($action == 'confirm_delete_line' && $_POST["confirm"] == "yes") { $object = new ExpenseReport($db); - $object->fetch($_GET["id"],$user); + $object->fetch($id); - $object_ligne = new ExpenseReportLigne($db); + $object_ligne = new ExpenseReportLine($db); $object_ligne->fetch($_GET["rowid"]); $total_ht = $object_ligne->total_ht; $total_tva = $object_ligne->total_tva; @@ -798,60 +768,43 @@ if ($action == 'confirm_delete_line' && $_POST["confirm"] == "yes") if ($action == "updateligne" ) { $object = new ExpenseReport($db); - - $object_id = GETPOST('id','int'); - $object->fetch($object_id,$user); + $object->fetch($id); $rowid = $_POST['rowid']; - $type_fees_id = empty($_POST['fk_c_type_fees'])?1:$_POST['fk_c_type_fees']; - - // Get tax id from rate - $tva_tx=GETPOST('fk_c_tva'); - $sql = "SELECT t.rowid, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type"; - $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as p"; - $sql .= " WHERE t.fk_pays = p.rowid AND p.code = '".$mysoc->country_code."'"; - $sql .= " AND t.taux = ".$db->escape($tva_tx)." AND t.active = 1"; - - dol_syslog("get_localtax sql=".$sql); - $resql=$db->query($sql); - if ($resql) - { - $obj = $db->fetch_object($resql); - $c_tva=$obj->rowid; - } - else dol_print_error($db); - - // Force la TVA à 0% lorsque c'est du transport - if ($type_fees_id==10) - { - $c_tva = 15; - } - + $type_fees_id = GETPOST('fk_c_type_fees'); + $c_tva=GETPOST('vatrate'); $object_ligne->fk_c_tva = $c_tva; - $projet_id = $_POST['fk_projet']; - $comments = $_POST['comments']; - $qty = $_POST['qty']; + $projet_id = $fk_projet; + $comments = GETPOST('comments'); + $qty = GETPOST('qty'); + $value_unit = GETPOST('value_unit'); - // Convertion de "," en "." dans le nombre entré dans le champ - if(preg_match("#,#",$_POST['value_unit'])): - $value_unit = preg_replace("#,#",".",$_POST['value_unit']); - else: - $value_unit = $_POST['value_unit']; - endif; - - $date = explode("/",$_POST['date']); - $date = $date[2]."-".$date[1]."-".$date[0]; - - $result = $object->updateline($rowid, $type_fees_id, $projet_id, $c_tva, $comments, $qty, $value_unit, $date, $object_id); - if ($result >= 0) + if (! GETPOST('fk_c_type_fees') > 0) { - $object->recalculer($object_id); - header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object_id); - exit; + $error++; + setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("Type")),'errors'); + $action=''; } - else + if (GETPOST('vatrate') < 0 || GETPOST('vatrate') == '') { - setEventMessages($object->error, $object->errors, 'errors'); + $error++; + setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("Vat")),'errors'); + $action=''; + } + + if (! $error) + { + $result = $object->updateline($rowid, $type_fees_id, $projet_id, $c_tva, $comments, $qty, $value_unit, $date, $object_id); + if ($result >= 0) + { + $object->recalculer($object_id); + header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object_id); + exit; + } + else + { + setEventMessages($object->error, $object->errors, 'errors'); + } } } @@ -876,7 +829,7 @@ if ($action == "recalc" && $id > 0) if ($action == 'builddoc') // En get ou en post { $depl = new ExpenseReport($db, 0, $_GET['id']); - $depl->fetch($_GET['id'],$user); + $depl->fetch($id); if ($_REQUEST['model']) { @@ -929,10 +882,10 @@ else if ($action == 'remove_file') llxHeader('', $langs->trans("ExpenseReport")); -$html = new Form($db); -$formfile = new FormFile($db); $form = new Form($db); +$formfile = new FormFile($db); $formproject = new FormProjets($db); +$projecttmp = new Project($db); if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) { @@ -976,13 +929,13 @@ if ($action == 'create') print ''; print ''.$langs->trans("DateStart").''; print ''; - $html->select_date($date_start?$date_start:-1,'date_debut',0,0,0,'',1,1); + $form->select_date($date_start?$date_start:-1,'date_debut',0,0,0,'',1,1); print ''; print ''; print ''; print ''.$langs->trans("DateEnd").''; print ''; - $html->select_date($date_end?$date_end:-1,'date_fin',0,0,0,'',1,1); + $form->select_date($date_end?$date_end:-1,'date_fin',0,0,0,'',1,1); print ''; print ''; print ''; @@ -990,8 +943,8 @@ if ($action == 'create') print ''; $object = new ExpenseReport($db); $include_users = $object->fetch_users_approver_expensereport(); - $s=$html->select_dolusers((GETPOST('fk_user_validator')?GETPOST('fk_user_validator'):$conf->global->EXPENSEREPORT_DEFAULT_VALIDATOR), "fk_user_validator", 1, "", 0, $include_users); - print $html->textwithpicto($s, $langs->trans("AnyOtherInThisListCanValidate")); + $s=$form->select_dolusers((GETPOST('fk_user_validator')?GETPOST('fk_user_validator'):$conf->global->EXPENSEREPORT_DEFAULT_VALIDATOR), "fk_user_validator", 1, "", 0, $include_users); + print $form->textwithpicto($s, $langs->trans("AnyOtherInThisListCanValidate")); print ''; print ''; if (! empty($conf->global->EXPENSEREPORT_ASK_PAYMENTMODE_ON_CREATION)) @@ -999,7 +952,7 @@ if ($action == 'create') print ''; print ''.$langs->trans("ModePaiement").''; print ''; - $html->select_types_paiements(2,'fk_c_paiement'); + $form->select_types_paiements(2,'fk_c_paiement'); print ''; print ''; } @@ -1026,9 +979,9 @@ else if($id > 0) { $object = new ExpenseReport($db); - $result = $object->fetch($id,$user); + $result = $object->fetch($id); - if ($result) + if ($result > 0) { if ($object->fk_user_author != $user->id) { @@ -1048,19 +1001,20 @@ else } } - //$head = trip_prepare_head($object); - + $head = expensereport_prepare_head($object); + /* $head[0][0] = $_SERVER['PHP_SELF'].'?id='.$object->id; $head[0][1] = $langs->trans('Card'); $head[0][2] = 'card'; - $h++; - - dol_fiche_head($head, 'card', $langs->trans("TripCard"), 0, 'trip'); + $h++;*/ if ($action == 'edit' && ($object->fk_c_expensereport_statuts < 3 || $object->fk_c_expensereport_statuts==99)) { print "
\n"; print ''; + print ''; + + dol_fiche_head($head, 'card', $langs->trans("TripCard"), 0, 'trip'); if($object->fk_c_expensereport_statuts==99) { @@ -1071,7 +1025,6 @@ else print ''; } - print ''; print ''; @@ -1086,13 +1039,13 @@ else print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; @@ -1101,7 +1054,7 @@ else print ''; print ''; print ''; print ''; } @@ -1112,8 +1065,8 @@ else print ''; print ''; print ''; } @@ -1149,67 +1102,69 @@ else print ''; print ''; print ''; print ''; print '
'.$langs->trans("DateStart").''; - $html->select_date($object->date_debut,'date_debut'); + $form->select_date($object->date_debut,'date_debut'); print '
'.$langs->trans("DateEnd").''; - $html->select_date($object->date_fin,'date_fin'); + $form->select_date($object->date_fin,'date_fin'); print '
'.$langs->trans("ModePaiement").''; - $html->select_types_paiements($object->fk_c_paiement,'fk_c_paiement'); + $form->select_types_paiements($object->fk_c_paiement,'fk_c_paiement'); print '
'.$langs->trans("VALIDATOR").''; $include_users = $object->fetch_users_approver_expensereport(); - $s=$html->select_dolusers($object->fk_user_validator,"fk_user_validator",0,"",0,$include_users); - print $html->textwithpicto($s, $langs->trans("AnyOtherInThisListCanValidate")); + $s=$form->select_dolusers($object->fk_user_validator,"fk_user_validator",0,"",0,$include_users); + print $form->textwithpicto($s, $langs->trans("AnyOtherInThisListCanValidate")); print '
'.$langs->trans("Note").''; - print ''; + print ''; print '
'; - print '
'; + dol_fiche_end(); + + print '
'; print '     '; - print ''; + print ''; print '
'; print ''; - } else { + dol_fiche_head($head, 'card', $langs->trans("TripCard"), 0, 'trip'); if ($action == 'save'): - $ret=$html->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("SaveTrip"),$langs->trans("ConfirmSaveTrip"),"confirm_save","","",1); + $ret=$form->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("SaveTrip"),$langs->trans("ConfirmSaveTrip"),"confirm_save","","",1); if ($ret == 'html') print '
'; endif; if ($action == 'save_from_refuse'): - $ret=$html->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("SaveTrip"),$langs->trans("ConfirmSaveTrip"),"confirm_save_from_refuse","","",1); + $ret=$form->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("SaveTrip"),$langs->trans("ConfirmSaveTrip"),"confirm_save_from_refuse","","",1); if ($ret == 'html') print '
'; endif; if ($action == 'delete'): - $ret=$html->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("DeleteTrip"),$langs->trans("ConfirmDeleteTrip"),"confirm_delete","","",1); + $ret=$form->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("DeleteTrip"),$langs->trans("ConfirmDeleteTrip"),"confirm_delete","","",1); if ($ret == 'html') print '
'; endif; if ($action == 'validate'): - $ret=$html->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("ValideTrip"),$langs->trans("ConfirmValideTrip"),"confirm_validate","","",1); + $ret=$form->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("ValideTrip"),$langs->trans("ConfirmValideTrip"),"confirm_validate","","",1); if ($ret == 'html') print '
'; endif; if ($action == 'paid'): - $ret=$html->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("PaidTrip"),$langs->trans("ConfirmPaidTrip"),"confirm_paid","","",1); + $ret=$form->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("PaidTrip"),$langs->trans("ConfirmPaidTrip"),"confirm_paid","","",1); if ($ret == 'html') print '
'; endif; if ($action == 'cancel'): $array_input = array(array('type'=>"text",'label'=>"Entrez ci-dessous un motif d'annulation :",'name'=>"detail_cancel",'size'=>"50",'value'=>"")); - $ret=$html->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("ConfirmCancelTrip"),"","confirm_cancel",$array_input,"",0); + $ret=$form->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("ConfirmCancelTrip"),"","confirm_cancel",$array_input,"",0); if ($ret == 'html') print '
'; endif; if ($action == 'brouillonner'): - $ret=$html->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("BrouillonnerTrip"),$langs->trans("ConfirmBrouillonnerTrip"),"confirm_brouillonner","","",1); + $ret=$form->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("BrouillonnerTrip"),$langs->trans("ConfirmBrouillonnerTrip"),"confirm_brouillonner","","",1); if ($ret == 'html') print '
'; endif; if ($action == 'refuse'): $array_input = array(array('type'=>"text",'label'=>"Entrez ci-dessous un motif de refus :",'name'=>"detail_refuse",'size'=>"50",'value'=>"")); - $ret=$html->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("ConfirmRefuseTrip"),"","confirm_refuse",$array_input,"yes",0); + $ret=$form->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("ConfirmRefuseTrip"),"","confirm_refuse",$array_input,"yes",0); if ($ret == 'html') print '
'; endif; if ($action == 'delete_line') { - $ret=$html->form_confirm($_SEVER["PHP_SELF"]."?id=".$_GET['id']."&rowid=".$_GET['rowid'],$langs->trans("DeleteLine"),$langs->trans("ConfirmDeleteLine"),"confirm_delete_line"); + $ret=$form->form_confirm($_SEVER["PHP_SELF"]."?id=".$_GET['id']."&rowid=".$_GET['rowid'],$langs->trans("DeleteLine"),$langs->trans("ConfirmDeleteLine"),"confirm_delete_line"); if ($ret == 'html') print '
'; } @@ -1219,11 +1174,11 @@ else // Ref print ''.$langs->trans("Ref").''; - print $form->showrefnav($object, 'id', $linkback, 1, 'rowid', 'ref', ''); + print $form->showrefnav($object, 'id', $linkback, 1, 'ref', 'ref', ''); print ''; print ''; - print ''.$langs->trans("Periode").''; + print ''.$langs->trans("Period").''; print ''; print get_date_range($object->date_debut,$object->date_fin,'',$langs,0); print ''; @@ -1313,9 +1268,10 @@ else print ''; if ($object->fk_user_author > 0) { - $userfee=new User($db); - $userfee->fetch($object->fk_user_author); - print $userfee->getNomUrl(1); + $userauthor=new User($db); + $result=$userauthor->fetch($object->fk_user_author); + if ($result < 0) dol_print_error('',$userauthor->error); + print $userauthor->getNomUrl(1); } print ''; @@ -1387,7 +1343,7 @@ else print ''; print ''; - if ($action != 'editline') print ''; + if ($action != 'editline') print ''; print ''; print ''; print ''; @@ -1418,17 +1374,21 @@ else { print ''; print ''; print ''; - print ''; + print ''; print ''; print ''; print ''; print ''; print ''; - print ''; - print ''; + print ''; + print ''; // Ajout des boutons de modification/suppression if($object->fk_c_expensereport_statuts<2 OR $object->fk_c_expensereport_statuts==99) @@ -1452,7 +1412,7 @@ else print ''; // Sélection date print ''; // Sélection projet @@ -1512,12 +1472,13 @@ else } //print ''; - // Ajouter une ligne + // Add a line if (($object->fk_c_expensereport_statuts==0 || $object->fk_c_expensereport_statuts==99) && $action != 'editline') { print_fiche_titre($langs->trans("AddLine"),'',''); print ''; + print ''; print ''; print ''; @@ -1528,7 +1489,7 @@ else print ''; print ''; print ''; - print ''; + print ''; print ''; print ''; print ''; @@ -1537,43 +1498,42 @@ else // Sélection date print ''; // Sélection projet print ''; // Sélection type print ''; // Add comments print ''; // Sélection TVA print ''; // Prix unitaire print ''; // Quantité print ''; print ''; @@ -1589,9 +1549,10 @@ else { dol_print_error($db); } - } // end edit or not edit - dol_fiche_end(); + dol_fiche_end(); + + } // end edit or not edit } // end of if result else @@ -1614,22 +1575,26 @@ print '
'; if ($action != 'create' && $action != 'edit') { $object = new ExpenseReport($db); - $object->fetch($id,$user); + $object->fetch($id); + /* Si l'état est "Brouillon" * ET user à droit "creer/supprimer" * ET fk_user_author == user courant * Afficher : "Enregistrer" / "Modifier" / "Supprimer" */ - if ($user->rights->expensereport->creer AND $object->fk_c_expensereport_statuts==0) + if ($user->rights->expensereport->creer && $object->fk_c_expensereport_statuts==0) { if ($object->fk_user_author == $user->id) { // Modifier print ''.$langs->trans('ModifyInfoGen').''; - // Enregistrer - print ''.$langs->trans('Validate').''; + // Validate + if (count($object->lines) > 0 || count($object->lignes) > 0) + { + print ''.$langs->trans('Validate').''; + } if ($user->rights->expensereport->supprimer) { @@ -1694,13 +1659,13 @@ if ($action != 'create' && $action != 'edit') // Valider print ''.$langs->trans('Approve').''; // Refuser - print ''.$langs->trans('REFUSE').''; + print ''.$langs->trans('Refuse').''; //} if ($object->fk_user_author==$user->id) { // Annuler - print ''.$langs->trans('CANCEL').''; + print ''.$langs->trans('Cancel').''; } if($user->rights->expensereport->supprimer) @@ -1777,8 +1742,8 @@ print '
'; */ if($user->rights->expensereport->export && $object->fk_c_expensereport_statuts>0 && $action != 'edit') { - $filename = dol_sanitizeFileName($object->ref_number); - $filedir = $conf->expensereport->dir_output . "/" . dol_sanitizeFileName($object->ref_number); + $filename = dol_sanitizeFileName($object->ref); + $filedir = $conf->expensereport->dir_output . "/" . dol_sanitizeFileName($object->ref); $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id; $genallowed = 1; $delallowed = 1; diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php index ee8555a6e69..c357807f315 100755 --- a/htdocs/expensereport/class/expensereport.class.php +++ b/htdocs/expensereport/class/expensereport.class.php @@ -14,7 +14,7 @@ class ExpenseReport extends CommonObject var $fk_element = 'fk_expensereport'; var $id; - var $ref_number; + var $ref; var $lignes=array(); var $total_ht; var $total_tva; @@ -94,11 +94,11 @@ class ExpenseReport extends CommonObject $this->statuts_short[6]='Paid'; $this->statuts_short[99]='Refused'; $this->statuts_logo[0]='statut0'; - $this->statuts_logo[2]='statut4'; - $this->statuts_logo[4]='statut3'; - $this->statuts_logo[5]='statut5'; + $this->statuts_logo[2]='statut1'; + $this->statuts_logo[4]='statut5'; + $this->statuts_logo[5]='statut3'; $this->statuts_logo[6]='statut6'; - $this->statuts_logo[99]='statutx'; + $this->statuts_logo[99]='statut8'; return 1; } @@ -118,7 +118,7 @@ class ExpenseReport extends CommonObject $this->db->begin(); $sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." ("; - $sql.= "ref_number"; + $sql.= "ref"; $sql.= ",total_ht"; $sql.= ",total_ttc"; $sql.= ",total_tva"; @@ -150,16 +150,16 @@ class ExpenseReport extends CommonObject if ($result) { $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element); - $this->ref_number='(PROV'.$this->id.')'; + $this->ref='(PROV'.$this->id.')'; - $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element." SET ref_number='".$this->ref_number."' WHERE rowid=".$this->id; + $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element." SET ref='".$this->ref."' WHERE rowid=".$this->id; dol_syslog(get_class($this)."::create sql=".$sql); $resql=$this->db->query($sql); if (!$resql) $error++; foreach ($this->lignes as $i => $val) { - $newndfline=new ExpenseReportLigne($this->db); + $newndfline=new ExpenseReportLine($this->db); $newndfline=$this->lignes[$i]; $newndfline->fk_expensereport=$this->id; if ($result >= 0) @@ -217,13 +217,13 @@ class ExpenseReport extends CommonObject $sql.= " total_ht = ".$this->total_ht; $sql.= " , total_ttc = ".$this->total_ttc; $sql.= " , total_tva = ".$this->total_tva; - $sql.= " , date_debut = '".$this->date_debut."'"; - $sql.= " , date_fin = '".$this->date_fin."'"; + $sql.= " , date_debut = '".$this->db->idate($this->date_debut)."'"; + $sql.= " , date_fin = '".$this->db->idate($this->date_fin)."'"; $sql.= " , fk_user_author = ".($user->id > 0 ? "'".$user->id."'":"null"); $sql.= " , fk_user_validator = ".($this->fk_user_validator > 0 ? $this->fk_user_validator:"null"); $sql.= " , fk_user_valid = ".($this->fk_user_valid > 0 ? $this->fk_user_valid:"null"); $sql.= " , fk_user_paid = ".($this->fk_user_paid > 0 ? $this->fk_user_paid:"null"); - $sql.= " , fk_c_expensereport_statuts = ".($this->fk_c_expensereport_statuts > 0 ? $this->fk_c_expensereport_statuts:"null"); + $sql.= " , fk_c_expensereport_statuts = ".($this->fk_c_expensereport_statuts >= 0 ? $this->fk_c_expensereport_statuts:'0'); $sql.= " , fk_c_paiement = ".($this->fk_c_paiement > 0 ? $this->fk_c_paiement:"null"); $sql.= " , note = ".(!empty($this->note)?"'".$this->db->escape($this->note)."'":"''"); $sql.= " , detail_refuse = ".(!empty($this->detail_refuse)?"'".$this->db->escape($this->detail_refuse)."'":"''"); @@ -246,19 +246,14 @@ class ExpenseReport extends CommonObject * Load an object from database * * @param int $id Id - * @param User $user User we want expense report for + * @param string $ref Ref + * @return int <0 if KO, >0 if OK */ - function fetch($id,$user='') + function fetch($id, $ref='') { global $conf,$db; - if (!$user->rights->expensereport->lire): - $restrict = " AND fk_user_author = ".$user->id; - else: - $restrict = ""; - endif; - - $sql = "SELECT d.rowid, d.ref_number, d.note,"; // DEFAULT + $sql = "SELECT d.rowid, d.ref, d.note,"; // DEFAULT $sql.= " d.detail_refuse, d.detail_cancel, d.fk_user_refuse, d.fk_user_cancel,"; // ACTIONS $sql.= " d.date_refuse, d.date_cancel,"; // ACTIONS $sql.= " d.total_ht, d.total_ttc, d.total_tva,"; // TOTAUX (int) @@ -267,7 +262,8 @@ class ExpenseReport extends CommonObject $sql.= " d.fk_user_valid, d.fk_user_paid,"; // FOREING KEY 2 (int) $sql.= " dp.libelle as libelle_paiement, dp.code as code_paiement"; // INNER JOIN paiement $sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element." d LEFT JOIN ".MAIN_DB_PREFIX."c_paiement dp ON d.fk_c_paiement = dp.id"; - $sql.= " WHERE d.rowid = ".$id; + if ($ref) $sql.= " WHERE d.ref = '".$this->db->escape($ref)."'"; + else $sql.= " WHERE d.rowid = ".$id; $sql.= $restrict; dol_syslog(get_class($this)."::fetch sql=".$sql, LOG_DEBUG); @@ -278,8 +274,7 @@ class ExpenseReport extends CommonObject if ($obj) { $this->id = $obj->rowid; - $this->ref = $obj->ref_number; - $this->ref_number = $obj->ref_number; + $this->ref = $obj->ref; $this->total_ht = $obj->total_ht; $this->total_tva = $obj->total_tva; $this->total_ttc = $obj->total_ttc; @@ -303,11 +298,12 @@ class ExpenseReport extends CommonObject $this->fk_user_cancel = $obj->fk_user_cancel; $user_author = new User($this->db); - $user_author->fetch($this->fk_user_author); + if ($this->fk_user_author > 0) $user_author->fetch($this->fk_user_author); + $this->user_author_infos = dolGetFirstLastname($user_author->firstname, $user_author->lastname); $user_approver = new User($this->db); - $user_approver->fetch($this->fk_user_validator); + if ($this->fk_user_validator > 0) $user_approver->fetch($this->fk_user_validator); $this->user_validator_infos = dolGetFirstLastname($user_approver->firstname, $user_approver->lastname); $this->fk_c_expensereport_statuts = $obj->status; @@ -317,14 +313,14 @@ class ExpenseReport extends CommonObject if ($this->fk_c_expensereport_statuts==5 || $this->fk_c_expensereport_statuts==6) { $user_valid = new User($this->db); - $user_valid->fetch($this->fk_user_valid); + if ($this->fk_user_valid > 0) $user_valid->fetch($this->fk_user_valid); $this->user_valid_infos = dolGetFirstLastname($user_valid->firstname, $user_valid->lastname); } if ($this->fk_c_expensereport_statuts==6) { $user_paid = new User($this->db); - $user_paid->fetch($this->fk_user_paid); + if ($this->fk_user_paid > 0) $user_paid->fetch($this->fk_user_paid); $this->user_paid_infos = dolGetFirstLastname($user_paid->firstname, $user_paid->lastname); } @@ -395,6 +391,66 @@ class ExpenseReport extends CommonObject } + /** + * Load information on object + * + * @param int $id Id of object + * @return void + */ + function info($id) + { + global $conf; + + $sql = "SELECT f.rowid,"; + $sql.= " f.date_create as datec,"; + $sql.= " f.tms as date_modification,"; + $sql.= " f.date_valide as datev,"; + $sql.= " f.fk_user_author,"; + $sql.= " f.fk_user_modif as fk_user_modification,"; + $sql.= " f.fk_user_validator"; + $sql.= " FROM ".MAIN_DB_PREFIX."expensereport as f"; + $sql.= " WHERE f.rowid = ".$id; + $sql.= " AND f.entity = ".$conf->entity; + + $resql = $this->db->query($sql); + if ($resql) + { + if ($this->db->num_rows($resql)) + { + $obj = $this->db->fetch_object($resql); + + $this->id = $obj->rowid; + + $this->date_creation = $this->db->jdate($obj->datec); + $this->date_modification = $this->db->jdate($obj->date_modification); + $this->date_validation = $this->db->jdate($obj->datev); + + $cuser = new User($this->db); + $cuser->fetch($obj->fk_user_author); + $this->user_creation = $cuser; + + if ($obj->fk_user_valid) + { + $vuser = new User($this->db); + $vuser->fetch($obj->fk_user_valid); + $this->user_validation = $vuser; + } + if ($obj->fk_user_modification) + { + $muser = new User($this->db); + $muser->fetch($obj->fk_user_modification); + $this->user_modification = $muser; + } + + } + $this->db->free($resql); + } + else + { + dol_print_error($this->db); + } + } + /** * fetch_line_by_project @@ -429,7 +485,7 @@ class ExpenseReport extends CommonObject $objp = $db->fetch_object($result); - $sql2 = "SELECT d.rowid, d.fk_user_author, d.ref_number, d.fk_c_expensereport_statuts"; + $sql2 = "SELECT d.rowid, d.fk_user_author, d.ref, d.fk_c_expensereport_statuts"; $sql2.= " FROM ".MAIN_DB_PREFIX."expensereport as d"; $sql2.= " WHERE d.rowid = '".$objp->fk_expensereport."'"; @@ -437,7 +493,7 @@ class ExpenseReport extends CommonObject $obj = $db->fetch_object($result2); $objp->fk_user_author = $obj->fk_user_author; - $objp->ref_num = $obj->ref_number; + $objp->ref = $obj->ref; $objp->fk_c_expensereport_status = $obj->fk_c_expensereport_statuts; $objp->rowid = $obj->rowid; @@ -561,15 +617,15 @@ class ExpenseReport extends CommonObject */ function fetch_lines() { + $this->lines=array(); + $sql = ' SELECT de.rowid, de.comments, de.qty, de.value_unit, de.date,'; $sql.= ' de.'.$this->fk_element.', de.fk_c_type_fees, de.fk_projet, de.fk_c_tva,'; $sql.= ' de.total_ht, de.total_tva, de.total_ttc,'; $sql.= ' ctf.code as code_type_fees, ctf.label as libelle_type_fees,'; - $sql.= ' ctv.taux as taux_tva,'; $sql.= ' p.ref as ref_projet, p.title as title_projet'; $sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element_line.' as de'; $sql.= ' INNER JOIN '.MAIN_DB_PREFIX.'c_type_fees ctf ON de.fk_c_type_fees = ctf.id'; - $sql.= ' INNER JOIN '.MAIN_DB_PREFIX.'c_tva ctv ON de.fk_c_tva = ctv.rowid'; $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'projet p ON de.fk_projet = p.rowid'; $sql.= ' WHERE de.'.$this->fk_element.' = '.$this->id; @@ -582,7 +638,7 @@ class ExpenseReport extends CommonObject while ($i < $num) { $objp = $this->db->fetch_object($result); - $deplig = new ExpenseReportLigne($this->db); + $deplig = new ExpenseReportLine($this->db); $deplig->rowid = $objp->rowid; $deplig->comments = $objp->comments; @@ -606,6 +662,8 @@ class ExpenseReport extends CommonObject $deplig->projet_title = $objp->title_projet; $this->lignes[$i] = $deplig; + $this->lines[$i] = $deplig; + $i++; } $this->db->free($result); @@ -613,7 +671,7 @@ class ExpenseReport extends CommonObject } else { - $this->error=$this->db->error(); + $this->error=$this->db->lasterror(); dol_syslog('ExpenseReport::fetch_lines: Error '.$this->error,LOG_ERR); return -3; } @@ -673,7 +731,7 @@ class ExpenseReport extends CommonObject // Sélection du numéro de ref suivant $ref_next = $this->getNextNumRef(); - $ref_number_int = ($this->ref_number+1)-1; + $ref_number_int = ($this->ref+1)-1; // Sélection de la date de début de la NDF $sql = 'SELECT date_debut'; @@ -688,13 +746,13 @@ class ExpenseReport extends CommonObject // Création du ref_number suivant if($ref_next) { - $this->ref_number = strtoupper($user->login).$expld_car."NDF".$this->ref_number.$expld_car.$this->date_debut; + $this->ref = strtoupper($user->login).$expld_car."NDF".$this->ref.$expld_car.$this->date_debut; } if ($this->fk_c_expensereport_statuts != 2) { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; - $sql.= " SET ref_number = '".$this->ref_number."', fk_c_expensereport_statuts = 2"; + $sql.= " SET ref = '".$this->ref."', fk_c_expensereport_statuts = 2"; $sql.= " ,ref_number_int = $ref_number_int"; $sql.= ' WHERE rowid = '.$this->id; @@ -776,7 +834,7 @@ class ExpenseReport extends CommonObject if ($this->fk_c_expensereport_statuts != 5) { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; - $sql.= " SET ref_number = '".$this->ref_number."', fk_c_expensereport_statuts = 5, fk_user_valid = ".$user->id; + $sql.= " SET ref = '".$this->ref."', fk_c_expensereport_statuts = 5, fk_user_valid = ".$user->id; $sql.= ', date_valide='.$this->date_valide; $sql.= ' WHERE rowid = '.$this->id; @@ -808,7 +866,7 @@ class ExpenseReport extends CommonObject if ($this->fk_c_expensereport_statuts != 99) { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; - $sql.= " SET ref_number = '".$this->ref_number."', fk_c_expensereport_statuts = 99, fk_user_refuse = ".$user->id; + $sql.= " SET ref = '".$this->ref."', fk_c_expensereport_statuts = 99, fk_user_refuse = ".$user->id; $sql.= ', date_refuse='.$this->date_refuse; $sql.= ", detail_refuse='".addslashes($details)."'"; $sql.= ' WHERE rowid = '.$this->id; @@ -903,7 +961,7 @@ class ExpenseReport extends CommonObject { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; $sql.= " SET fk_c_deplacement_statuts = 1,"; - //$sql.= " , ref_number = '(PROV".$this->id.")', ref_number_int = 0"; + //$sql.= " , ref = '(PROV".$this->id.")', ref_number_int = 0"; $sql.= " ref_number_int = 0"; $sql.= ' WHERE rowid = '.$this->id; @@ -1005,15 +1063,15 @@ class ExpenseReport extends CommonObject if($this->db->num_rows($result) > 0): $objp = $this->db->fetch_object($result); - $this->ref_number = $objp->ref_number_int; - $this->ref_number++; - while(strlen($this->ref_number) < $num_car): - $this->ref_number = "0".$this->ref_number; + $this->ref = $objp->ref_number_int; + $this->ref++; + while(strlen($this->ref) < $num_car): + $this->ref = "0".$this->ref; endwhile; else: - $this->ref_number = 1; - while(strlen($this->ref_number) < $num_car): - $this->ref_number = "0".$this->ref_number; + $this->ref = 1; + while(strlen($this->ref) < $num_car): + $this->ref = "0".$this->ref; endwhile; endif; @@ -1119,7 +1177,7 @@ class ExpenseReport extends CommonObject $total_tva = $total_ttc - $total_ht; // fin calculs - $ligne = new ExpenseReportLigne($this->db); + $ligne = new ExpenseReportLine($this->db); $ligne->comments = $comments; $ligne->qty = $qty; $ligne->value_unit = $value_unit; @@ -1295,7 +1353,7 @@ class ExpenseReport extends CommonObject /** * Class of expense report details lines */ -class ExpenseReportLigne +class ExpenseReportLine { var $db; var $error; @@ -1328,7 +1386,7 @@ class ExpenseReportLigne * * @param DoliDB $db Handlet database */ - function ExpenseReportLigne($db) + function ExpenseReportLine($db) { $this->db= $db; } @@ -1354,7 +1412,8 @@ class ExpenseReportLigne $result = $this->db->query($sql); - if($result) { + if($result) + { $objp = $this->db->fetch_object($result); $this->rowid = $objp->rowid; @@ -1391,7 +1450,9 @@ class ExpenseReportLigne { global $langs,$user,$conf; - dol_syslog("ExpenseReportLigne::Insert rang=".$this->rang, LOG_DEBUG); + $error=0; + + dol_syslog("ExpenseReportLine::Insert rang=".$this->rang, LOG_DEBUG); // Clean parameters $this->comments=trim($this->comments); @@ -1413,23 +1474,39 @@ class ExpenseReportLigne $sql.= " ".$this->total_ht.","; $sql.= " ".$this->total_tva.","; $sql.= " ".$this->total_ttc.","; - $sql.= "'".$this->date."'"; + $sql.= "'".$this->db->idate($this->date)."'"; $sql.= ")"; - dol_syslog("ExpenseReportLigne::insert sql=".$sql); + dol_syslog("ExpenseReportLine::insert sql=".$sql); $resql=$this->db->query($sql); - - if ($resql): + if ($resql) + { $this->rowid=$this->db->last_insert_id(MAIN_DB_PREFIX.'expensereport_det'); + + $tmpparent=new ExpenseReport($this->db); + $tmpparent->fetch($this->fk_expensereport); + $result = $tmpparent->update_price(); + if ($result < 0) + { + $error++; + $this->error = $tmpparent->error; + $this->errors = $tmpparent->errors; + } + } + + if (! $error) + { $this->db->commit(); return $this->rowid; - else: - $this->error=$this->db->error(); - dol_syslog("ExpenseReportLigne::insert Error ".$this->error, LOG_ERR); + } + else + { + $this->error=$this->db->lasterror(); + dol_syslog("ExpenseReportLine::insert Error ".$this->error, LOG_ERR); $this->db->rollback(); return -2; - endif; + } } /** @@ -1442,6 +1519,8 @@ class ExpenseReportLigne { global $user,$langs,$conf; + $error=0; + // Clean parameters $this->comments=trim($this->comments); @@ -1465,18 +1544,31 @@ class ExpenseReportLigne else $sql.= ",fk_c_tva=null"; $sql.= " WHERE rowid = ".$this->rowid; - dol_syslog("ExpenseReportLigne::update sql=".$sql); + dol_syslog("ExpenseReportLine::update sql=".$sql); $resql=$this->db->query($sql); if ($resql) + { + $tmpparent=new ExpenseReport($db); + $tmpparent->fetch($this->fk_expensereport); + $result = $tmpparent->update_price(); + if ($result < 0) + { + $error++; + $this->error = $tmpparent->error; + $this->errors = $tmpparent->errors; + } + } + + if (! $error) { $this->db->commit(); return 1; } else { - $this->error=$this->db->error(); - dol_syslog("ExpenseReportLigne::update Error ".$this->error, LOG_ERR); + $this->error=$this->db->lasterror(); + dol_syslog("ExpenseReportLine::update Error ".$this->error, LOG_ERR); $this->db->rollback(); return -2; } @@ -1503,7 +1595,7 @@ function select_expensereport_statut($selected='',$htmlname='fk_c_expensereport_ if ($useempty) print ''; foreach ($tmpep->statuts as $key => $val) { - if ($selected == $key) + if ($selected != '' && $selected == $key) { print ''; } - $sql = "SELECT c.code, c.label as type,c.id FROM ".MAIN_DB_PREFIX."c_type_fees as c"; + $sql = "SELECT c.id, c.code, c.label as type FROM ".MAIN_DB_PREFIX."c_type_fees as c"; $sql.= " ORDER BY c.label ASC"; $resql=$db->query($sql); if ($resql) @@ -1609,7 +1701,7 @@ function select_type_fees_id($selected='',$htmlname='type',$showempty=0) { $obj = $db->fetch_object($resql); print '
"; - print ''; + print ''; print ''; print ''; print ''; diff --git a/htdocs/expensereport/synchro_compta.php b/htdocs/expensereport/synchro_compta.php index 7d427c44fa1..211f5c4cc0a 100755 --- a/htdocs/expensereport/synchro_compta.php +++ b/htdocs/expensereport/synchro_compta.php @@ -38,7 +38,7 @@ if ($_GET["action"] == 'confirm_ndf_to_account' && $_GET["confirm"] == "yes"): $dateop = dol_mktime(12,0,0,$datePaiement[1],$datePaiement[2],$datePaiement[0]); $operation = $expensereport->code_paiement; - $label = "Règlement ".$expensereport->ref_number; + $label = "Règlement ".$expensereport->ref; $amount = - price2num($expensereport->total_ttc); $num_chq = ''; $cat1 = ''; @@ -73,7 +73,7 @@ if ($_GET["action"] == 'confirm_account_to_ndf' && $_GET["confirm"] == "yes"): $expensereport->fetch($idTrip,$user); $sql = "DELETE FROM ".MAIN_DB_PREFIX."bank"; - $sql.= " WHERE label LIKE '%".$expensereport->ref_number."%'"; + $sql.= " WHERE label LIKE '%".$expensereport->ref."%'"; $resql=$db->query($sql); if ($resql > 0): $sql = " UPDATE ".MAIN_DB_PREFIX."expensereport d"; @@ -137,7 +137,7 @@ else: print ' '; print ""; - $sql = "SELECT d.fk_bank_account, d.ref_number, d.rowid, d.date_valide, d.fk_user_author, d.total_ttc, d.integration_compta, d.fk_c_expensereport_statuts"; + $sql = "SELECT d.fk_bank_account, d.ref, d.rowid, d.date_valide, d.fk_user_author, d.total_ttc, d.integration_compta, d.fk_c_expensereport_statuts"; $sql.= " ,CONCAT(u.firstname,' ',u.lastname) as declarant_NDF"; $sql.= " FROM ".MAIN_DB_PREFIX."expensereport d"; $sql.= " INNER JOIN ".MAIN_DB_PREFIX."user u ON d.fk_user_author = u.rowid"; @@ -169,24 +169,30 @@ else: $objp = $db->fetch_object($resql); $var=!$var; print ""; - print ''; + print ''; print ''; print ''; print ''; - if($objp->integration_compta): + if($objp->integration_compta) + { print ''; - else: + } + else + { print ''; - endif; + } print ''; - if($objp->integration_compta): + if($objp->integration_compta) + { print ''; - else: + } + else + { print ''; - endif; + } print ""; $i++; diff --git a/htdocs/install/mysql/data/llx_c_type_fees.sql b/htdocs/install/mysql/data/llx_c_type_fees.sql index 9e763bf5ba8..19ee7865e9f 100644 --- a/htdocs/install/mysql/data/llx_c_type_fees.sql +++ b/htdocs/install/mysql/data/llx_c_type_fees.sql @@ -31,5 +31,5 @@ -- insert into llx_c_type_fees (code,label,active) values ('TF_OTHER', 'Other', 1); -insert into llx_c_type_fees (code,label,active) values ('TF_TRIP', 'Trip', 1); +insert into llx_c_type_fees (code,label,active) values ('TF_TRIP', 'Transportation', 1); insert into llx_c_type_fees (code,label,active) values ('TF_LUNCH', 'Lunch', 1); diff --git a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql index 0acea91984b..7217a53b890 100755 --- a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql +++ b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql @@ -117,7 +117,7 @@ ALTER TABLE llx_stock_mouvement ADD COLUMN sellby date DEFAULT NULL; CREATE TABLE llx_expensereport ( rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY, - ref_number varchar(50) NOT NULL, + ref varchar(50) NOT NULL, entity integer DEFAULT 1 NOT NULL, -- multi company id ref_number_int integer DEFAULT NULL, ref_ext integer, @@ -131,6 +131,7 @@ CREATE TABLE llx_expensereport ( date_paiement datetime, date_valide datetime, date_create datetime NOT NULL, + tms timestamp, fk_user_author integer NOT NULL, fk_user_modif integer DEFAULT NULL, fk_user_validator integer DEFAULT NULL, @@ -151,12 +152,9 @@ CREATE TABLE llx_expensereport ( model_pdf varchar(50) DEFAULT NULL ) ENGINE=innodb; - - - CREATE TABLE llx_expensereport_det ( - rowid integer PRIMARY KEY NOT NULL, + rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY, fk_expensereport integer NOT NULL, fk_c_type_fees integer NOT NULL, fk_projet integer NOT NULL, @@ -184,4 +182,3 @@ CREATE TABLE llx_expensereport_det ) ENGINE=innodb; - diff --git a/htdocs/install/mysql/tables/llx_expensereport.sql b/htdocs/install/mysql/tables/llx_expensereport.sql index 6fcdfa92291..e998343e6db 100755 --- a/htdocs/install/mysql/tables/llx_expensereport.sql +++ b/htdocs/install/mysql/tables/llx_expensereport.sql @@ -18,7 +18,7 @@ CREATE TABLE llx_expensereport ( rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY, - ref_number varchar(50) NOT NULL, + ref varchar(50) NOT NULL, entity integer DEFAULT 1 NOT NULL, -- multi company id ref_number_int integer DEFAULT NULL, ref_ext integer, @@ -32,6 +32,7 @@ CREATE TABLE llx_expensereport ( date_paiement datetime, date_valide datetime, date_create datetime NOT NULL, + tms timestamp, fk_user_author integer NOT NULL, fk_user_modif integer DEFAULT NULL, fk_user_validator integer DEFAULT NULL, diff --git a/htdocs/install/mysql/tables/llx_expensereport_det.sql b/htdocs/install/mysql/tables/llx_expensereport_det.sql index 644668f5713..98e7c33265e 100644 --- a/htdocs/install/mysql/tables/llx_expensereport_det.sql +++ b/htdocs/install/mysql/tables/llx_expensereport_det.sql @@ -18,7 +18,7 @@ CREATE TABLE llx_expensereport_det ( - rowid integer PRIMARY KEY NOT NULL, + rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY, fk_expensereport integer NOT NULL, fk_c_type_fees integer NOT NULL, fk_projet integer NOT NULL, diff --git a/htdocs/langs/en_US/projects.lang b/htdocs/langs/en_US/projects.lang index b3c150d1687..0587ce39bfe 100644 --- a/htdocs/langs/en_US/projects.lang +++ b/htdocs/langs/en_US/projects.lang @@ -67,7 +67,7 @@ ListSupplierOrdersAssociatedProject=List of supplier's orders associated with th ListSupplierInvoicesAssociatedProject=List of supplier's invoices associated with the project ListContractAssociatedProject=List of contracts associated with the project ListFichinterAssociatedProject=List of interventions associated with the project -ListTripAssociatedProject=List of trips and expenses associated with the project +ListExpenseReportsAssociatedProject=List of expense reports associated with the project ListActionsAssociatedProject=List of events associated with the project ActivityOnProjectThisWeek=Activity on project this week ActivityOnProjectThisMonth=Activity on project this month diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index 90fdae1232b..047f0bff057 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -424,6 +424,10 @@ class Project extends CommonObject if (empty($datefieldname)) return 'Error this object has no date field defined'; $sql.=" AND (".$datefieldname." <= '".$this->db->idate($datee)."' OR ".$datefieldname." IS NULL)"; } + if ($type == 'expensereport') + { + $sql ='eeee'; + } if (! $sql) return -1; //print $sql; diff --git a/htdocs/projet/element.php b/htdocs/projet/element.php index 1abaa37cac1..226f4afb573 100644 --- a/htdocs/projet/element.php +++ b/htdocs/projet/element.php @@ -38,6 +38,7 @@ if (! empty($conf->fournisseur->enabled)) require_once DOL_DOCUMENT_ROOT.'/fourn if (! empty($conf->contrat->enabled)) require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php'; if (! empty($conf->ficheinter->enabled)) require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php'; if (! empty($conf->deplacement->enabled)) require_once DOL_DOCUMENT_ROOT.'/compta/deplacement/class/deplacement.class.php'; +if (! empty($conf->expensereport->enabled)) require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php'; if (! empty($conf->agenda->enabled)) require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; $langs->load("projects"); @@ -225,13 +226,22 @@ $listofreferent=array( 'test'=>$conf->ficheinter->enabled && $user->rights->ficheinter->lire), 'trip'=>array( 'name'=>"TripsAndExpenses", - 'title'=>"ListTripAssociatedProject", + 'title'=>"ListExpenseReportsAssociatedProject", 'class'=>'Deplacement', 'table'=>'deplacement', 'datefieldname'=>'dated', 'margin'=>'minus', 'disableamount'=>1, 'test'=>$conf->deplacement->enabled && $user->rights->deplacement->lire), +'expensereport'=>array( + 'name'=>"ExpenseReports", + 'title'=>"ListExpenseReportsAssociatedProject", + 'class'=>'ExpenseReportLine', + 'table'=>'expensereport', + 'datefieldname'=>'date', + 'margin'=>'minus', + 'disableamount'=>1, + 'test'=>$conf->expensereport->enabled && $user->rights->expensereport->lire), 'agenda'=>array( 'name'=>"Agenda", 'title'=>"ListActionsAssociatedProject", From bb2c33e2c11c563c583abb80237d2f30335dcb80 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 15 Feb 2015 22:49:53 +0100 Subject: [PATCH 125/173] Trad --- htdocs/langs/en_US/main.lang | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index e53f0df5585..5fad3a3fd20 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -291,10 +291,10 @@ DefaultGlobalValue=Global value Price=Price UnitPrice=Unit price UnitPriceHT=Unit price (net) -UnitPriceTTC=Unit price +UnitPriceTTC=Unit price (inc. tac) PriceU=U.P. PriceUHT=U.P. (net) -PriceUTTC=U.P. +PriceUTTC=U.P. (inc. tax) Amount=Amount AmountInvoice=Invoice amount AmountPayment=Payment amount From 9ab48b3d90a8427b2965ae4e60e3e0ce28ba0016 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 15 Feb 2015 22:51:18 +0100 Subject: [PATCH 126/173] Revert "Trad" This reverts commit bb2c33e2c11c563c583abb80237d2f30335dcb80. --- htdocs/langs/en_US/main.lang | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 5fad3a3fd20..e53f0df5585 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -291,10 +291,10 @@ DefaultGlobalValue=Global value Price=Price UnitPrice=Unit price UnitPriceHT=Unit price (net) -UnitPriceTTC=Unit price (inc. tac) +UnitPriceTTC=Unit price PriceU=U.P. PriceUHT=U.P. (net) -PriceUTTC=U.P. (inc. tax) +PriceUTTC=U.P. Amount=Amount AmountInvoice=Invoice amount AmountPayment=Payment amount From 2045fb22e9001c444d685d0eb5242c53ed3b0bbf Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 15 Feb 2015 23:39:30 +0100 Subject: [PATCH 127/173] Lock 5.5.40 --- htdocs/install/upgrade.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/install/upgrade.php b/htdocs/install/upgrade.php index 8f62a755518..89e54ef4443 100644 --- a/htdocs/install/upgrade.php +++ b/htdocs/install/upgrade.php @@ -193,9 +193,9 @@ if (! GETPOST("action") || preg_match('/upgrade/i',GETPOST('action'))) // Test database version is not forbidden for migration $dbversion_disallowed=array( array('type'=>'mysql','version'=>array(5,5,40)), - array('type'=>'mysqli','version'=>array(5,5,40)), - array('type'=>'mysql','version'=>array(5,5,41)), - array('type'=>'mysqli','version'=>array(5,5,41)) + array('type'=>'mysqli','version'=>array(5,5,40)) + //,array('type'=>'mysql','version'=>array(5,5,41)), + //array('type'=>'mysqli','version'=>array(5,5,41)) ); $listofforbiddenversion=''; foreach ($dbversion_disallowed as $dbversion_totest) From 3cf4b80baaf8dd8210bbb1d571bb716b17b7f6eb Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 16 Feb 2015 02:02:11 +0100 Subject: [PATCH 128/173] Fix missing test of action when using canvas --- dev/skeletons/modMyModule.class.php | 6 +++--- htdocs/core/class/canvas.class.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dev/skeletons/modMyModule.class.php b/dev/skeletons/modMyModule.class.php index 4c09e379d9b..bf78c7cc161 100644 --- a/dev/skeletons/modMyModule.class.php +++ b/dev/skeletons/modMyModule.class.php @@ -113,9 +113,9 @@ class modMyModule extends DolibarrModules $this->const = array(); // Array to add new pages in new tabs - // Example: $this->tabs = array('objecttype:+tabname1:Title1:mylangfile@mymodule:$user->rights->mymodule->read:/mymodule/mynewtab1.php?id=__ID__', // To add a new tab identified by code tabname1 - // 'objecttype:+tabname2:Title2:mylangfile@mymodule:$user->rights->othermodule->read:/mymodule/mynewtab2.php?id=__ID__', // To add another new tab identified by code tabname2 - // 'objecttype:-tabname:NU:conditiontoremove'); // To remove an existing tab identified by code tabname + // Example: $this->tabs = array('objecttype:+tabname1:Title1:mylangfile@mymodule:$user->rights->mymodule->read:/mymodule/mynewtab1.php?id=__ID__', // To add a new tab identified by code tabname1 + // 'objecttype:+tabname2:SUBSTITUTION_Title2:mylangfile@mymodule:$user->rights->othermodule->read:/mymodule/mynewtab2.php?id=__ID__', // To add another new tab identified by code tabname2. Label will be result of calling all substitution functions on 'Title2' key. + // 'objecttype:-tabname:NU:conditiontoremove'); // To remove an existing tab identified by code tabname // where objecttype can be // 'categories_x' to add a tab in category view (replace 'x' by type of category (0=product, 1=supplier, 2=customer, 3=member) // 'contact' to add a tab in contact view diff --git a/htdocs/core/class/canvas.class.php b/htdocs/core/class/canvas.class.php index 959decc581c..a8bb07e6ec6 100644 --- a/htdocs/core/class/canvas.class.php +++ b/htdocs/core/class/canvas.class.php @@ -67,7 +67,7 @@ class Canvas $newaction = $action; if ($newaction == 'add') $newaction='create'; if ($newaction == 'update') $newaction='edit'; - if (empty($newaction) || $newaction == 'delete' || $newaction == 'create_user') $newaction='view'; + if (empty($newaction) || $newaction == 'delete' || $newaction == 'create_user' || $newaction == 'presend' || $newaction == 'send') $newaction='view'; return $newaction; } From 05dc308e9156dcbb12e120c9fa573c9990f0a63e Mon Sep 17 00:00:00 2001 From: aspangaro Date: Mon, 16 Feb 2015 06:47:37 +0100 Subject: [PATCH 129/173] [T1728] Deactivate RIB suggest in proposals/invoices/orders --- ChangeLog | 1 + htdocs/core/lib/pdf.lib.php | 2 ++ 2 files changed, 3 insertions(+) diff --git a/ChangeLog b/ChangeLog index d905ba24168..35720ebdabc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -106,6 +106,7 @@ For users: - Fix: [ bug #1535 ] Supplier invoice Extrafields are not shown - Fix: datepicker first day of week can be monday by setting into display setup - Fix: [ bug #575 ] GED doesn't works if there is "/" in a mask +- Fix: [ task #1728 ] Deactivate RIB suggest in proposals / invoices / orders For users, new experimental module (need to set feature level of instance to experimental to see them): - New: Module Accounting Expert to manage accountancy diff --git a/htdocs/core/lib/pdf.lib.php b/htdocs/core/lib/pdf.lib.php index 794ba7ac2af..01ab5eeaf82 100644 --- a/htdocs/core/lib/pdf.lib.php +++ b/htdocs/core/lib/pdf.lib.php @@ -533,6 +533,7 @@ function pdf_bank(&$pdf,$outputlangs,$curx,$cury,$account,$onlynumber=0,$default $cury+=3; } + /* if (empty($onlynumber)) $pdf->line($curx+1, $cury+1, $curx+1, $cury+8); if ($usedetailedbban == 1) @@ -596,6 +597,7 @@ function pdf_bank(&$pdf,$outputlangs,$curx,$cury,$account,$onlynumber=0,$default $curx=$savcurx; $cury+=9; + */ } else { From 82b3f4a1020fc6fd72b22a7b54a8695cbd19d7d4 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 16 Feb 2015 10:40:09 +0100 Subject: [PATCH 130/173] Add field budget_amount on project. --- .../install/mysql/migration/3.7.0-3.8.0.sql | 2 ++ htdocs/install/mysql/tables/llx_projet.sql | 2 ++ htdocs/projet/class/project.class.php | 30 +++++++++---------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql index 7217a53b890..6024996624a 100755 --- a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql +++ b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql @@ -182,3 +182,5 @@ CREATE TABLE llx_expensereport_det ) ENGINE=innodb; +ALTER TABLE ll_projet ADD COLUMN budget_amount double(24,8); + diff --git a/htdocs/install/mysql/tables/llx_projet.sql b/htdocs/install/mysql/tables/llx_projet.sql index acac8c7b687..0bfde5c026b 100644 --- a/htdocs/install/mysql/tables/llx_projet.sql +++ b/htdocs/install/mysql/tables/llx_projet.sql @@ -34,5 +34,7 @@ create table llx_projet fk_statut smallint DEFAULT 0 NOT NULL, note_private text, note_public text, + --budget_days real, -- budget in days is sum of field planned_workload of tasks + budget_amount double(24,8), model_pdf varchar(255) )ENGINE=innodb; diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index 047f0bff057..ce699df0b32 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -55,8 +55,11 @@ class Project extends CommonObject var $public; //!< Tell if this is a public or private project var $note_private; var $note_public; + var $budget_amount; + var $statuts_short; var $statuts; + var $oldcopy; @@ -110,6 +113,7 @@ class Project extends CommonObject $sql.= ", datec"; $sql.= ", dateo"; $sql.= ", datee"; + $sql.= ", budget_amount"; $sql.= ", entity"; $sql.= ") VALUES ("; $sql.= "'" . $this->db->escape($this->ref) . "'"; @@ -208,6 +212,7 @@ class Project extends CommonObject $sql.= ", datec=" . ($this->date_c != '' ? "'".$this->db->idate($this->date_c)."'" : 'null'); $sql.= ", dateo=" . ($this->date_start != '' ? "'".$this->db->idate($this->date_start)."'" : 'null'); $sql.= ", datee=" . ($this->date_end != '' ? "'".$this->db->idate($this->date_end)."'" : 'null'); + $sql.= ", budget_amount = " . ($this->budget_amount > 0 ? $this->budget_amount : "null"); $sql.= " WHERE rowid = " . $this->id; dol_syslog(get_class($this)."::Update", LOG_DEBUG); @@ -293,8 +298,8 @@ class Project extends CommonObject { if (empty($id) && empty($ref)) return -1; - $sql = "SELECT rowid, ref, title, description, public, datec"; - $sql.= ", tms, dateo, datee, fk_soc, fk_user_creat, fk_statut, note_private, note_public,model_pdf"; + $sql = "SELECT rowid, ref, title, description, public, datec, budget_amount,"; + $sql.= " tms, dateo, datee, fk_soc, fk_user_creat, fk_statut, note_private, note_public,model_pdf"; $sql.= " FROM " . MAIN_DB_PREFIX . "projet"; if (! empty($id)) { @@ -331,6 +336,7 @@ class Project extends CommonObject $this->user_author_id = $obj->fk_user_creat; $this->public = $obj->public; $this->statut = $obj->fk_statut; + $this->budget_amount = $obj->budget_amount; $this->modelpdf = $obj->model_pdf; $this->db->free($resql); @@ -412,6 +418,10 @@ class Project extends CommonObject { $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . $tablename." WHERE fk_projet=" . $this->id; } + if ($type == 'expensereport') + { + $sql = "SELECT id as rowid FROM " . MAIN_DB_PREFIX . "expensereport as e, " . MAIN_DB_PREFIX . "expensereport_det as ed WHERE ed.fk_project=" . $this->id; + } if ($dates > 0) { if (empty($datefieldname) && ! empty($this->table_element_date)) $datefieldname=$this->table_element_date; @@ -424,10 +434,6 @@ class Project extends CommonObject if (empty($datefieldname)) return 'Error this object has no date field defined'; $sql.=" AND (".$datefieldname." <= '".$this->db->idate($datee)."' OR ".$datefieldname." IS NULL)"; } - if ($type == 'expensereport') - { - $sql ='eeee'; - } if (! $sql) return -1; //print $sql; @@ -842,6 +848,8 @@ class Project extends CommonObject $this->date_m = $now; $this->date_start = $now; $this->note_public = 'SPECIMEN'; + $this->budget_amount = 10000; + /* $nbp = rand(1, 9); $xnbp = 0; @@ -893,13 +901,6 @@ class Project extends CommonObject if ($mode == 'write' && $user->rights->projet->creer) $userAccess++; if ($mode == 'delete' && $user->rights->projet->supprimer) $userAccess++; } - // Permission are supported on users only. To have an external thirdparty contact to see a project, its user must allowed to contacts of projects. - /*if ($source == 'external' && preg_match('/PROJECT/', $userRole[$nblinks]['code']) && $user->contact_id == $userRole[$nblinks]['id']) - { - if ($mode == 'read' && $user->rights->projet->lire) $userAccess++; - if ($mode == 'write' && $user->rights->projet->creer) $userAccess++; - if ($mode == 'delete' && $user->rights->projet->supprimer) $userAccess++; - }*/ $nblinks++; } } @@ -945,11 +946,9 @@ class Project extends CommonObject { $sql.= " AND ec.element_id = p.rowid"; $sql.= " AND ( p.public = 1"; - //$sql.= " OR p.fk_user_creat = ".$user->id; $sql.= " OR ( ctc.rowid = ec.fk_c_type_contact"; $sql.= " AND ctc.element = '" . $this->element . "'"; $sql.= " AND ( (ctc.source = 'internal' AND ec.fk_socpeople = ".$user->id.")"; - //$sql.= " OR (ctc.source = 'external' AND ec.fk_socpeople = ".($user->contact_id?$user->contact_id:0).")"; // Permission are supported on users only. To have an external thirdparty contact to see a project, its user must allowed to contacts of projects. $sql.= " )"; $sql.= " ))"; } @@ -959,7 +958,6 @@ class Project extends CommonObject $sql.= " AND ctc.rowid = ec.fk_c_type_contact"; $sql.= " AND ctc.element = '" . $this->element . "'"; $sql.= " AND ( (ctc.source = 'internal' AND ec.fk_socpeople = ".$user->id.")"; - //$sql.= " OR (ctc.source = 'external' AND ec.fk_socpeople = ".($user->contact_id?$user->contact_id:0).")"; // Permission are supported on users only. To have an external thirdparty contact to see a project, its user must allowed to contacts of projects. $sql.= " )"; } if ($mode == 2) From 3ca31e34cbd6e767d286628c6f7875158d070bf1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 16 Feb 2015 10:58:05 +0100 Subject: [PATCH 131/173] New: Add field "budget" (amount) on projects. --- .../install/mysql/migration/3.7.0-3.8.0.sql | 2 +- htdocs/projet/card.php | 19 ++++++++++++++++++- htdocs/projet/class/project.class.php | 3 ++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql index 6024996624a..831185a9203 100755 --- a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql +++ b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql @@ -182,5 +182,5 @@ CREATE TABLE llx_expensereport_det ) ENGINE=innodb; -ALTER TABLE ll_projet ADD COLUMN budget_amount double(24,8); +ALTER TABLE llx_projet ADD COLUMN budget_amount double(24,8); diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index 5887bb6f1d8..1103396658f 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -141,6 +141,7 @@ if (empty($reshook)) $object->socid = GETPOST('socid','int'); $object->description = GETPOST('description'); // Do not use 'alpha' here, we want field as it is $object->public = GETPOST('public','alpha'); + $object->budget_amount = GETPOST('budget_amount','int'); $object->datec=dol_now(); $object->date_start=$date_start; $object->date_end=$date_end; @@ -217,6 +218,7 @@ if (empty($reshook)) $object->socid = GETPOST('socid','int'); $object->description = GETPOST('description'); // Do not use 'alpha' here, we want field as it is $object->public = GETPOST('public','alpha'); + $object->budget_amount= GETPOST('budget_amount','int'); $object->date_start = empty($_POST["projectstart"])?'':$date_start; $object->date_end = empty($_POST["projectend"])?'':$date_end; @@ -433,7 +435,7 @@ if ($action == 'create' && $user->rights->projet->creer) print ''; // Label - print ''; + print ''; // Customer print ''; + // Budget + print ''; + print ''; + print ''; + // Description print ''; print ''; + // Budget + print ''; + print ''; + print ''; + // Description print ''; print ''; + // Budget + print ''; + // Description print '
'.$langs->trans('Piece').''.$langs->trans('Piece').''.$langs->trans('Date').''.$langs->trans('Project').''.$langs->trans('Type').'
'; - print img_picto("Document", "generic"); + print img_picto($langs->trans("Document"), "object_generic"); print ' '.$piece_comptable.''.$objp->date.''.$objp->projet_ref.''; + $projecttmp->id=$objp->projet_id; + $projecttmp->ref=$objp->projet_ref; + print $projecttmp->getNomUrl(1); + print ''.$langs->trans("TF_".strtoupper($objp->type_fees_libelle)).''.$objp->comments.''.vatrate($objp->tva_taux,true).''.price($objp->value_unit).''.$objp->qty.''.$objp->total_ht.''.$objp->total_ttc.''.price($objp->total_ht).''.price($objp->total_ttc).'
'; - $html->select_date($objp->date,'date'); + $form->select_date($objp->date,'date'); print '
'.$langs->trans('Type').''.$langs->trans('Description').''.$langs->trans('VAT').''.$langs->trans('UnitPriceTTC').''.$langs->trans('PriceUTTC').''.$langs->trans('Qty').'
'; - $html->select_date(-1,'date'); + $form->select_date($date?$date:-1,'date'); print ''; - print select_projet('','','fk_projet'); - //$formproject->select_projects('','','fk_projet'); + $formproject->select_projects('', GETPOST('fk_projet'), 'fk_projet', 0, 0, 1, 1); print ''; - select_type_fees_id('TF_TRAIN','fk_c_type_fees'); + select_type_fees_id(GETPOST('fk_c_type_fees'),'fk_c_type_fees',1); print ''; - print ''; + print ''; print ''; $defaultvat=-1; - if (! empty($conf->global->DEPLACEMENT_NO_DEFAULT_VAT)) $conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS = 'none'; - print ''; print ''; - print ''; + print ''; print ''; - print ''; + print ''; print '
'.img_object($langs->trans("ShowTrip"),"trip").' '.$objp->ref_number.''.img_object($langs->trans("ShowTrip"),"trip").' '.$objp->ref.''.($objp->date_debut > 0 ? dol_print_date($objp->date_debut, 'day') : '').''.($objp->date_fin > 0 ? dol_print_date($objp->date_fin, 'day') : '').''.img_object($langs->trans("ShowUser"),"user").' '.dolGetFirstLastname($objp->firstname, $objp->lastname).'
'.$objp->ref_number.''.$objp->ref.''.dol_print_date($db->jdate($objp->date_valide),'day').''.img_object($langs->trans("ShowUser"),"user").' '.$objp->declarant_NDF.''.$objp->total_ttc.' '.$langs->trans("EURO").'Compte vers NDFNDF vers Compte'.$account->label.'Intégration OKIntégration Non OK
'.$langs->trans("Ref").'
'.$langs->trans("Label").'
'.$langs->trans("Label").'
'.$langs->trans("ThirdParty").''; @@ -462,6 +464,11 @@ if ($action == 'create' && $user->rights->projet->creer) print $form->select_date(($date_end?$date_end:-1),'projectend'); print '
'.$langs->trans("Budget").'
'.$langs->trans("Description").''; @@ -602,6 +609,11 @@ else print $form->select_date($object->date_end?$object->date_end:-1,'projectend'); print '
'.$langs->trans("Budget").'
'.$langs->trans("Description").''; @@ -663,6 +675,11 @@ else print dol_print_date($object->date_end,'day'); print '
'.$langs->trans("Budget").''; + if ($object->budget_amount != '') print price($object->budget_amount,'',$langs,0,0,0,$conf->currency); + print '
'.$langs->trans("Description").''; print nl2br($object->description); diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index ce699df0b32..e1aa84f1f4c 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -126,6 +126,7 @@ class Project extends CommonObject $sql.= ", '".$this->db->idate($now)."'"; $sql.= ", " . ($this->date_start != '' ? "'".$this->db->idate($this->date_start)."'" : 'null'); $sql.= ", " . ($this->date_end != '' ? "'".$this->db->idate($this->date_end)."'" : 'null'); + $sql.= ", " . $this->budget_amount; $sql.= ", ".$conf->entity; $sql.= ")"; @@ -420,7 +421,7 @@ class Project extends CommonObject } if ($type == 'expensereport') { - $sql = "SELECT id as rowid FROM " . MAIN_DB_PREFIX . "expensereport as e, " . MAIN_DB_PREFIX . "expensereport_det as ed WHERE ed.fk_project=" . $this->id; + $sql = "SELECT e.rowid FROM " . MAIN_DB_PREFIX . "expensereport as e, " . MAIN_DB_PREFIX . "expensereport_det as ed WHERE e.rowid = ed.fk_expensereport AND ed.fk_projet=" . $this->id; } if ($dates > 0) { From 53dc28ddc399810853ca87d59aec8b77c55f45b7 Mon Sep 17 00:00:00 2001 From: damien clochard Date: Mon, 16 Feb 2015 11:01:08 +0100 Subject: [PATCH 132/173] There's only 2 sortable formats --- htdocs/langs/en_US/banks.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/banks.lang b/htdocs/langs/en_US/banks.lang index 10a5f5b3c14..c42503c0ecb 100644 --- a/htdocs/langs/en_US/banks.lang +++ b/htdocs/langs/en_US/banks.lang @@ -148,7 +148,7 @@ BackToAccount=Back to account ShowAllAccounts=Show for all accounts FutureTransaction=Transaction in futur. No way to conciliate. SelectChequeTransactionAndGenerate=Select/filter checks to include into the check deposit receipt and click on "Create". -InputReceiptNumber=Choose the bank statement related with the conciliation. Use a sortable numeric value (such as, YYYYMM) +InputReceiptNumber=Choose the bank statement related with the conciliation. Use a sortable numeric value: YYYYMM or YYYYMMDD EventualyAddCategory=Eventually, specify a category in which to classify the records ToConciliate=To conciliate? ThenCheckLinesAndConciliate=Then, check the lines present in the bank statement and click From 58fc57744a7e3bd4bc7cbc059716bed717c7dbf5 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 16 Feb 2015 17:25:26 +0100 Subject: [PATCH 133/173] Update example --- htdocs/conf/conf.php.example | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/htdocs/conf/conf.php.example b/htdocs/conf/conf.php.example index 67147a6d06b..681cecf1261 100644 --- a/htdocs/conf/conf.php.example +++ b/htdocs/conf/conf.php.example @@ -208,11 +208,13 @@ $dolibarr_main_authentication='dolibarr'; // 0 = No forced redirect // 1 = Force redirect to https, until SCRIPT_URI start with https into response // 2 = Force redirect to https, until SERVER["HTTPS"] is 'on' into response -// Warning: If you enable this parameter, your web server must be configured -// to respond URL with https protocol. Try different values (1,2) if you -// experience problems. +// 'https://my.domain.com' = Force reditect to https using this domain name. +// Warning: If you enable this parameter, your web server must be configured to +// respond URL with https protocol. +// According to your web server setup, some values may works and other not. Try +// different values (1,2 or 'http://my.domain.com') if you experience problems. // Default value: 0 -// Possible values: 0, 1 or 2 +// Possible values: 0, 1, 2 or 'http://my.domain.com' // Examples: // $dolibarr_main_force_https='0'; // From 118ae7e8f812582540aa5fbd68f240c7d398e31a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 16 Feb 2015 17:55:53 +0100 Subject: [PATCH 134/173] Backport fix done into dev. --- htdocs/install/mysql/migration/3.6.0-3.7.0.sql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/install/mysql/migration/3.6.0-3.7.0.sql b/htdocs/install/mysql/migration/3.6.0-3.7.0.sql index 4421ad032eb..22a65167e6f 100755 --- a/htdocs/install/mysql/migration/3.6.0-3.7.0.sql +++ b/htdocs/install/mysql/migration/3.6.0-3.7.0.sql @@ -1155,3 +1155,6 @@ ALTER TABLE llx_resource MODIFY COLUMN entity integer DEFAULT 1 NOT NULL; -- This request make mysql drop (mysql bug, so we add it at end): ALTER TABLE llx_product ADD CONSTRAINT fk_product_barcode_type FOREIGN KEY (fk_barcode_type) REFERENCES llx_c_barcode_type(rowid); +-- this update change the old formated url on llx_bank_url +UPDATE llx_bank_url set url = REPLACE( url, 'fiche.php', 'card.php'); + From 03d19bf77fc335032ee1ee92a8cd4587518f7e0a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 16 Feb 2015 18:02:25 +0100 Subject: [PATCH 135/173] Fix: Sort criteria --- htdocs/opensurvey/list.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/opensurvey/list.php b/htdocs/opensurvey/list.php index d21a08007a4..d13c9884e89 100644 --- a/htdocs/opensurvey/list.php +++ b/htdocs/opensurvey/list.php @@ -43,8 +43,8 @@ if ($page == -1) { $page = 0; } $offset = $conf->liste_limit * $page; $pageprev = $page - 1; $pagenext = $page + 1; -if (! $sortfield) $sortfield="p.titre"; -if (! $sortorder) $sortorder="ASC"; +if (! $sortfield) $sortfield="p.date_fin"; +if (! $sortorder) $sortorder="DESC"; if ($page < 0) { $page = 0; } From 9a9a1f398369d062e6f331b7e8ab943ab77d7e68 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 16 Feb 2015 19:14:34 +0100 Subject: [PATCH 136/173] Fix bad id --- htdocs/expedition/card.php | 5 +- htdocs/expedition/class/expedition.class.php | 12 ++-- .../class/expeditionbatch.class.php | 71 ++++++++++--------- htdocs/expedition/shipment.php | 4 +- htdocs/langs/en_US/productbatch.lang | 2 +- 5 files changed, 50 insertions(+), 44 deletions(-) diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index 562caee3cb0..8ecae0ff2dc 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -98,7 +98,7 @@ if (($action == 'create') || ($action == 'add')) { $langs->load("errors"); setEventMessage($langs->trans("WarehouseMustBeSelectedAtFirstStepWhenProductBatchModuleOn"),'errors'); - header("Location: ".DOL_URL_ROOT.'/expedition/shipment.php?id='.$id); + header("Location: ".DOL_URL_ROOT.'/expedition/shipment.php?id='.$origin_id); exit; } } @@ -457,7 +457,6 @@ if ($action == 'create') $classname = ucfirst($origin); $object = new $classname($db); - if ($object->fetch($origin_id)) // This include the fetch_lines { //var_dump($object); @@ -837,7 +836,7 @@ if ($action == 'create') print '
'; } else - { + { dol_print_error($db); } } diff --git a/htdocs/expedition/class/expedition.class.php b/htdocs/expedition/class/expedition.class.php index 67426510da2..228845d162e 100644 --- a/htdocs/expedition/class/expedition.class.php +++ b/htdocs/expedition/class/expedition.class.php @@ -399,7 +399,7 @@ class Expedition extends CommonObject * @param string $ref Ref of object * @param string $ref_ext External reference of object * @param string $ref_int Internal reference of other object - * @return int >0 if OK, <0 if KO + * @return int >0 if OK, 0 if not found, <0 if KO */ function fetch($id, $ref='', $ref_ext='', $ref_int='') { @@ -496,9 +496,9 @@ class Expedition extends CommonObject } else { - dol_syslog(get_class($this).'::Fetch Error -2', LOG_ERR); + dol_syslog(get_class($this).'::Fetch no expedition found', LOG_ERR); $this->error='Delivery with id '.$id.' not found sql='.$sql; - return -2; + return 0; } } else @@ -613,7 +613,7 @@ class Expedition extends CommonObject if ($result < 0) { $error++; break; } if (! empty($conf->productbatch->enabled)) { - $details=ExpeditionLigneBatch::FetchAll($this->db,$obj->rowid); + $details=ExpeditionLigneBatch::fetchAll($this->db,$obj->rowid); if (! empty($details)) { foreach ($details as $dbatch) { $result=$mouvS->livraison_batch($dbatch->fk_origin_stock,$dbatch->dluo_qty); @@ -1175,9 +1175,9 @@ class Expedition extends CommonObject */ require_once DOL_DOCUMENT_ROOT.'/expedition/class/expeditionbatch.class.php'; if ($originline != $obj->fk_origin_line) { - $line->detail_batch = ExpeditionLigneBatch::FetchAll($this->db,$obj->line_id); + $line->detail_batch = ExpeditionLigneBatch::fetchAll($this->db,$obj->line_id); } else { - $line->detail_batch = array_merge($line->detail_batch,ExpeditionLigneBatch::FetchAll($this->db,$obj->line_id)); + $line->detail_batch = array_merge($line->detail_batch,ExpeditionLigneBatch::fetchAll($this->db,$obj->line_id)); } } if ($originline != $obj->fk_origin_line) { diff --git a/htdocs/expedition/class/expeditionbatch.class.php b/htdocs/expedition/class/expeditionbatch.class.php index 62d23aaa7ff..ea179710271 100644 --- a/htdocs/expedition/class/expeditionbatch.class.php +++ b/htdocs/expedition/class/expeditionbatch.class.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2007-2015 Laurent Destailleur * Copyright (C) 2013-2014 Cedric GROSS * * This program is free software; you can redistribute it and/or modify @@ -20,13 +20,12 @@ * \file expedition/class/productbatch.class.php * \ingroup productbatch * \brief This file implements CRUD method for managing product's shipment - * with batch record + * with batch record */ - /** +/** * CRUD class for batch number management within shipment */ - class ExpeditionLigneBatch extends CommonObject { var $element='expeditionlignebatch'; //!< Id that identify managed objects @@ -53,18 +52,19 @@ class ExpeditionLigneBatch extends CommonObject } /** - * Fill object based on a product-warehouse-batch's record + * Fill object based on a product-warehouse-batch's record * * @param int $id_stockdluo Rowid in product_batch table * @return int -1 if KO, 1 if OK */ - function fetchFromStock($id_stockdluo) { + function fetchFromStock($id_stockdluo) + { $sql = "SELECT"; $sql.= " t.sellby,"; $sql.= " t.eatby,"; $sql.= " t.batch,"; $sql.= " e.fk_entrepot"; - + $sql.= " FROM ".MAIN_DB_PREFIX."product_batch as t inner join "; $sql.= MAIN_DB_PREFIX."product_stock as e on t.fk_product_stock=e.rowid "; $sql.= " WHERE t.rowid = ".(int) $id_stockdluo; @@ -82,7 +82,6 @@ class ExpeditionLigneBatch extends CommonObject $this->batch = $obj->batch; $this->entrepot_id= $obj->fk_entrepot; $this->fk_origin_stock=(int) $id_stockdluo; - } $this->db->free($resql); @@ -98,14 +97,15 @@ class ExpeditionLigneBatch extends CommonObject /** * Create an expeditiondet_batch DB record link to an expedtiondet record * - * @param int $id_line_expdet rowid of expedtiondet record - * @return int <0 if KO, Id of record (>0) if OK + * @param int $id_line_expdet rowid of expedtiondet record + * @return int <0 if KO, Id of record (>0) if OK */ - function create($id_line_expdet) { + function create($id_line_expdet) + { $error = 0; $id_line_expdet = (int) $id_line_expdet; - + $sql = "INSERT INTO ".MAIN_DB_PREFIX.self::$_table_element." ("; $sql.= "fk_expeditiondet"; $sql.= ", sellby"; @@ -115,23 +115,25 @@ class ExpeditionLigneBatch extends CommonObject $sql.= ", fk_origin_stock"; $sql.= ") VALUES ("; $sql.= $id_line_expdet.","; - $sql.= " ".(! isset($this->sellby) || dol_strlen($this->sellby)==0?'NULL':$this->db->idate($this->sellby)).","; - $sql.= " ".(! isset($this->eatby) || dol_strlen($this->eatby)==0?'NULL':$this->db->idate($this->eatby)).","; + $sql.= " ".(! isset($this->sellby) || dol_strlen($this->sellby)==0?'NULL':"'".$this->db->idate($this->sellby))."',"; + $sql.= " ".(! isset($this->eatby) || dol_strlen($this->eatby)==0?'NULL':"'".$this->db->idate($this->eatby))."',"; $sql.= " ".(! isset($this->batch)?'NULL':"'".$this->db->escape($this->batch)."'").","; $sql.= " ".(! isset($this->dluo_qty)?'NULL':$this->dluo_qty).","; $sql.= " ".(! isset($this->fk_origin_stock)?'NULL':$this->fk_origin_stock); $sql.= ")"; - dol_syslog(__METHOD__ ."", LOG_DEBUG); + dol_syslog(__METHOD__, LOG_DEBUG); $resql=$this->db->query($sql); - if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); } - if (! $error){ + if (! $error) + { $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.self::$_table_element); $this->fk_expeditiondet=$id_line_expdet; return $this->id; - } else { + } + else + { foreach($this->errors as $errmsg) { dol_syslog(get_class($this)."::create ".$errmsg, LOG_ERR); @@ -147,20 +149,22 @@ class ExpeditionLigneBatch extends CommonObject * * @param object $db Database object * @param int $id_expedition rowid of shipment - * * @return int -1 if KO, 1 if OK */ - static function deletefromexp($db,$id_expedition) { + static function deletefromexp($db,$id_expedition) + { $id_expedition = (int) $id_expedition; - + $sql="DELETE FROM ".MAIN_DB_PREFIX.self::$_table_element; $sql.=" WHERE fk_expeditiondet in (SELECT rowid FROM ".MAIN_DB_PREFIX."expeditiondet WHERE fk_expedition=".$id_expedition.")"; - - dol_syslog(__METHOD__ ."", LOG_DEBUG); - if ( $db->query($sql) ) + + dol_syslog(__METHOD__, LOG_DEBUG); + if ($db->query($sql)) { return 1; - } else { + } + else + { return -1; } } @@ -168,12 +172,12 @@ class ExpeditionLigneBatch extends CommonObject /** * Retrieve all batch number details link to a shipment line * - * @param object $db Database object - * @param int $id_line_expdet id of shipment line - * - * @return variant -1 if KO, array of ExpeditionLigneBatch if OK + * @param object $db Database object + * @param int $id_line_expdet id of shipment line + * @return variant -1 if KO, array of ExpeditionLigneBatch if OK */ - static function FetchAll($db,$id_line_expdet) { + static function fetchAll($db,$id_line_expdet) + { $sql="SELECT rowid,"; $sql.= "fk_expeditiondet"; $sql.= ", sellby"; @@ -190,7 +194,8 @@ class ExpeditionLigneBatch extends CommonObject { $num=$db->num_rows($resql); $i=0; - while ($i<$num) { + while ($i<$num) + { $tmp=new self($db); $obj = $db->fetch_object($resql); @@ -208,7 +213,9 @@ class ExpeditionLigneBatch extends CommonObject } $db->free($resql); return $ret; - } else { + } + else + { return -1; } } diff --git a/htdocs/expedition/shipment.php b/htdocs/expedition/shipment.php index ead48800de5..d5d82f2baa3 100644 --- a/htdocs/expedition/shipment.php +++ b/htdocs/expedition/shipment.php @@ -42,7 +42,7 @@ $langs->load('propal'); $langs->load('deliveries'); $langs->load('stocks'); -$id=GETPOST('id','int'); +$id=GETPOST('id','int'); // id of order $ref= GETPOST('ref','alpha'); $action=GETPOST('action','alpha'); @@ -634,7 +634,7 @@ if ($id > 0 || ! empty($ref)) print '
'; print ''; - print ''; + //print ''; print ''; print ''; print ''; diff --git a/htdocs/langs/en_US/productbatch.lang b/htdocs/langs/en_US/productbatch.lang index 8dd31df3412..c81b1af5374 100644 --- a/htdocs/langs/en_US/productbatch.lang +++ b/htdocs/langs/en_US/productbatch.lang @@ -10,7 +10,7 @@ batch_number=Batch/Serial number l_eatby=Eat-by date l_sellby=Sell-by date DetailBatchNumber=Batch/Serial details -DetailBatchFormat=Batch/Serial: %s - E:%s - S: %s (Qty : %d) +DetailBatchFormat=Batch/Serial: %s - Eat by: %s - Sell by: %s (Qty : %d) printBatch=Batch: %s printEatby=Eat-by: %s printSellby=Sell-by: %s From 213c818204451bfc53503e9c375126bcdffcec0e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 16 Feb 2015 20:14:16 +0100 Subject: [PATCH 137/173] Debug serial/lot management --- htdocs/commande/card.php | 8 +- htdocs/core/class/commonobject.class.php | 3 +- htdocs/core/lib/order.lib.php | 2 +- htdocs/expedition/card.php | 45 +++++++--- htdocs/expedition/class/expedition.class.php | 85 ++++++++++++------- .../class/expeditionbatch.class.php | 14 +-- htdocs/install/mysql/migration/repair.sql | 12 +++ 7 files changed, 113 insertions(+), 56 deletions(-) diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index cbc6141ac1b..6978de14e40 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1232,14 +1232,16 @@ $formorder = new FormOrder($db); * * ******************************************************************* */ -if ($action == 'create' && $user->rights->commande->creer) { +if ($action == 'create' && $user->rights->commande->creer) +{ print_fiche_titre($langs->trans('CreateOrder')); $soc = new Societe($db); if ($socid > 0) $res = $soc->fetch($socid); - if (! empty($origin) && ! empty($originid)) { + if (! empty($origin) && ! empty($originid)) + { // Parse element/subelement (ex: project_task) $element = $subelement = $origin; if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) { @@ -1353,7 +1355,7 @@ if ($action == 'create' && $user->rights->commande->creer) { /* * Contact de la commande - */ + */ if ($socid > 0) { print "
" . $langs->trans("DefaultContact") . ''; $form->select_contacts($soc->id, $setcontact, 'contactid', 1, $srccontactslist); diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index b4aff6002d0..aed2aa3b224 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -2480,12 +2480,13 @@ abstract class CommonObject $tplpath = 'comm/'.$element; if (empty($conf->propal->enabled)) continue; // Do not show if module disabled } - else if ($objecttype == 'shipping') { + else if ($objecttype == 'shipping' || $objecttype == 'shipment') { $tplpath = 'expedition'; if (empty($conf->expedition->enabled)) continue; // Do not show if module disabled } else if ($objecttype == 'delivery') { $tplpath = 'livraison'; + if (empty($conf->expedition->enabled)) continue; // Do not show if module disabled } else if ($objecttype == 'invoice_supplier') { $tplpath = 'fourn/facture'; diff --git a/htdocs/core/lib/order.lib.php b/htdocs/core/lib/order.lib.php index abdf1b648a5..1e0f2f50139 100644 --- a/htdocs/core/lib/order.lib.php +++ b/htdocs/core/lib/order.lib.php @@ -52,7 +52,7 @@ function commande_prepare_head($object) || ($conf->livraison_bon->enabled && $user->rights->expedition->livraison->lire)) { $head[$h][0] = DOL_URL_ROOT.'/expedition/shipment.php?id='.$object->id; - if ($conf->expedition_bon->enabled) $text=$langs->trans("Shipment"); + if ($conf->expedition_bon->enabled) $text=$langs->trans("Shipments"); if ($conf->expedition_bon->enabled && $conf->livraison_bon->enabled) $text.='/'; if ($conf->livraison_bon->enabled) $text.=$langs->trans("Receivings"); $head[$h][1] = $text; diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php index 8ecae0ff2dc..846323ba6b6 100644 --- a/htdocs/expedition/card.php +++ b/htdocs/expedition/card.php @@ -144,45 +144,59 @@ if (empty($reshook)) $object->note_private = GETPOST('note_private'); $object->note_public = GETPOST('note_public'); + $batch_line = array(); + $num=count($objectsrc->lines); $totalqty=0; for ($i = 0; $i < $num; $i++) { - $qty = "qtyl".$i; - $j=0; + $idl="idl".$i; + $sub_qty=array(); $subtotalqty=0; - $idl="idl".$i; + + $j=0; $batch="batchl".$i."_0"; - if (isset($_POST[$batch])) { + $qty = "qtyl".$i; + + if (isset($_POST[$batch])) + { //shipment line with batch-enable product $qty .= '_'.$j; - while (isset($_POST[$batch])) { + while (isset($_POST[$batch])) + { + // save line of detail into sub_qty $sub_qty[$j]['q']=GETPOST($qty,'int'); $sub_qty[$j]['id_batch']=GETPOST($batch,'int'); + $subtotalqty+=$sub_qty[$j]['q']; + $j++; $batch="batchl".$i."_".$j; $qty = "qtyl".$i.'_'.$j; - } - $batch_line[$i]['detail']=$sub_qty; + + $batch_line[$i]['detail']=$sub_qty; // array of details $batch_line[$i]['qty']=$subtotalqty; $batch_line[$i]['ix_l']=GETPOST($idl,'int'); + $totalqty+=$subtotalqty; - } else { - //Standard product + } + else + { + //shipment line for product with no batch management if (GETPOST($qty,'int') > 0) $totalqty+=GETPOST($qty,'int'); } } - if ($totalqty > 0) + if ($totalqty > 0) // There is at least one thing to ship { //var_dump($_POST);exit; for ($i = 0; $i < $num; $i++) { $qty = "qtyl".$i; - if (! isset($batch_line[$i])) { + if (! isset($batch_line[$i])) + { // not batch mode if (GETPOST($qty,'int') > 0 || (GETPOST($qty,'int') == 0 && $conf->global->SHIPMENT_GETS_ALL_ORDER_PRODUCTS)) { $ent = "entl".$i; @@ -197,8 +211,11 @@ if (empty($reshook)) $error++; } } - } else { - if ($batch_line[$i]['qty']>0) { + } + else + { // batch mode + if ($batch_line[$i]['qty']>0) + { $ret=$object->addline_batch($batch_line[$i]); if ($ret < 0) { @@ -211,7 +228,7 @@ if (empty($reshook)) if (! $error) { - $ret=$object->create($user); + $ret=$object->create($user); // This create shipment (like Odoo picking) and line of shipments. Stock movement will when validating shipment. if ($ret <= 0) { $mesg='
'.$object->error.'
'; diff --git a/htdocs/expedition/class/expedition.class.php b/htdocs/expedition/class/expedition.class.php index 228845d162e..379d9849b8f 100644 --- a/htdocs/expedition/class/expedition.class.php +++ b/htdocs/expedition/class/expedition.class.php @@ -255,13 +255,16 @@ class Expedition extends CommonObject $num=count($this->lines); for ($i = 0; $i < $num; $i++) { - if (! isset($this->lines[$i]->detail_batch)) { - if (! $this->create_line($this->lines[$i]->entrepot_id, $this->lines[$i]->origin_line_id, $this->lines[$i]->qty) > 0) - { - $error++; + if (! isset($this->lines[$i]->detail_batch)) + { // no batch management + if (! $this->create_line($this->lines[$i]->entrepot_id, $this->lines[$i]->origin_line_id, $this->lines[$i]->qty) > 0) + { + $error++; + } } - } else { - if (! $this->create_line_ext($this->lines[$i]) > 0) + else + { // with batch management + if (! $this->create_line_batch($this->lines[$i]) > 0) { $error++; } @@ -366,28 +369,37 @@ class Expedition extends CommonObject if (! $error) return 1; else return -1; } + + /** * Create a expedition line with eat-by date * * @param object $line_ext full line informations * @return int <0 if KO, >0 if OK */ - function create_line_ext($line_ext) + function create_line_batch($line_ext) { $error = 0; - if ( $this->create_line(($line_ext->entrepot_id?$line_ext->entrepot_id:'null'),$line_ext->origin_line_id,$line_ext->qty)<0) + if ($this->create_line(($line_ext->entrepot_id?$line_ext->entrepot_id:'null'),$line_ext->origin_line_id,$line_ext->qty) < 0) { $error++; - } else { + } + + if (! $error) + { $line_id= $this->db->last_insert_id(MAIN_DB_PREFIX."expeditiondet"); $tab=$line_ext->detail_batch; - foreach ($tab as $detbatch) { - if (! ($detbatch->create($line_id) >0)) { + foreach ($tab as $detbatch) + { + if (! ($detbatch->create($line_id) >0)) // Create an expeditionlinebatch + { $error++; } } } + + if (! $error) return 1; else return -1; } @@ -612,10 +624,13 @@ class Expedition extends CommonObject $result=$mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, $obj->qty, $obj->subprice, $langs->trans("ShipmentValidatedInDolibarr",$numref)); if ($result < 0) { $error++; break; } - if (! empty($conf->productbatch->enabled)) { - $details=ExpeditionLigneBatch::fetchAll($this->db,$obj->rowid); - if (! empty($details)) { - foreach ($details as $dbatch) { + if (! empty($conf->productbatch->enabled)) + { + $details=ExpeditionLineBatch::fetchAll($this->db,$obj->rowid); + if (! empty($details)) + { + foreach ($details as $dbatch) + { $result=$mouvS->livraison_batch($dbatch->fk_origin_stock,$dbatch->dluo_qty); if ($result < 0) { $error++; $this->errors[]=$mouvS->$error; break 2; } } @@ -751,7 +766,8 @@ class Expedition extends CommonObject $line->origin_line_id = $id; $line->qty = $qty; - if($conf->global->STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT) { + if ($conf->global->STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT) + { $orderline = new OrderLine($this->db); $orderline->fetch($id); $fk_product = $orderline->fk_product; @@ -762,7 +778,8 @@ class Expedition extends CommonObject $result=$product->fetch($fk_product); $product_type=$product->type; - if($product_type == 0 && $product->stock_reel < $qty) { + if($product_type == 0 && $product->stock_reel < $qty) + { $this->error=$langs->trans('ErrorStockIsNotEnough'); $this->db->rollback(); return -3; @@ -777,19 +794,23 @@ class Expedition extends CommonObject * Add a shipment line with batch record * * @param array $dbatch Array of value (key 'detail' -> Array, key 'qty' total quantity for line, key ix_l : original line index) - * @return int <0 if KO, >0 if OK + * @return int <0 if KO, >0 if OK */ function addline_batch($dbatch) { $num = count($this->lines); - if ($dbatch['qty']>0) { + if ($dbatch['qty']>0) + { $line = new ExpeditionLigne($this->db); $tab=array(); - foreach ($dbatch['detail'] as $key=>$value) { - if ($value['q']>0) { - $linebatch = new ExpeditionLigneBatch($this->db); - $ret=$linebatch->fetchFromStock($value['id_batch']); - if ($ret<0) { + foreach ($dbatch['detail'] as $key=>$value) + { + if ($value['q']>0) + { + $linebatch = new ExpeditionLineBatch($this->db); + $ret=$linebatch->fetchFromStock($value['id_batch']); // load serial, sellby, eatby + if ($ret<0) + { $this->error=$linebatch->error; return -1; } @@ -932,10 +953,13 @@ class Expedition extends CommonObject $this->db->begin(); - if ($conf->productbatch->enabled) { + if ($conf->productbatch->enabled) + { require_once DOL_DOCUMENT_ROOT.'/expedition/class/expeditionbatch.class.php'; - if ( ExpeditionLigneBatch::deletefromexp($this->db,$this->id)<0) - {$error++;$this->errors[]="Error ".$this->db->lasterror();} + if (ExpeditionLineBatch::deletefromexp($this->db,$this->id) < 0) + { + $error++;$this->errors[]="Error ".$this->db->lasterror(); + } } // Stock control if ($conf->stock->enabled && $conf->global->STOCK_CALCULATE_ON_SHIPMENT && $this->statut > 0) @@ -1174,10 +1198,11 @@ class Expedition extends CommonObject * May be conf is not well initialized for dark reason */ require_once DOL_DOCUMENT_ROOT.'/expedition/class/expeditionbatch.class.php'; - if ($originline != $obj->fk_origin_line) { - $line->detail_batch = ExpeditionLigneBatch::fetchAll($this->db,$obj->line_id); + if ($originline != $obj->fk_origin_line) + { + $line->detail_batch = ExpeditionLineBatch::fetchAll($this->db,$obj->line_id); } else { - $line->detail_batch = array_merge($line->detail_batch,ExpeditionLigneBatch::fetchAll($this->db,$obj->line_id)); + $line->detail_batch = array_merge($line->detail_batch,ExpeditionLineBatch::fetchAll($this->db,$obj->line_id)); } } if ($originline != $obj->fk_origin_line) { diff --git a/htdocs/expedition/class/expeditionbatch.class.php b/htdocs/expedition/class/expeditionbatch.class.php index ea179710271..cc5726ed0c8 100644 --- a/htdocs/expedition/class/expeditionbatch.class.php +++ b/htdocs/expedition/class/expeditionbatch.class.php @@ -17,16 +17,16 @@ */ /** - * \file expedition/class/productbatch.class.php + * \file expedition/class/expeditionbatch.class.php * \ingroup productbatch - * \brief This file implements CRUD method for managing product's shipment + * \brief This file implements CRUD method for managing shipment batch lines * with batch record */ /** * CRUD class for batch number management within shipment */ -class ExpeditionLigneBatch extends CommonObject +class ExpeditionLineBatch extends CommonObject { var $element='expeditionlignebatch'; //!< Id that identify managed objects private static $_table_element='expeditiondet_batch'; //!< Name of table without prefix where object is stored @@ -115,9 +115,9 @@ class ExpeditionLigneBatch extends CommonObject $sql.= ", fk_origin_stock"; $sql.= ") VALUES ("; $sql.= $id_line_expdet.","; - $sql.= " ".(! isset($this->sellby) || dol_strlen($this->sellby)==0?'NULL':"'".$this->db->idate($this->sellby))."',"; - $sql.= " ".(! isset($this->eatby) || dol_strlen($this->eatby)==0?'NULL':"'".$this->db->idate($this->eatby))."',"; - $sql.= " ".(! isset($this->batch)?'NULL':"'".$this->db->escape($this->batch)."'").","; + $sql.= " ".(! isset($this->sellby) || dol_strlen($this->sellby)==0?'NULL':("'".$this->db->idate($this->sellby))."'").","; + $sql.= " ".(! isset($this->eatby) || dol_strlen($this->eatby)==0?'NULL':("'".$this->db->idate($this->eatby))."'").","; + $sql.= " ".(! isset($this->batch)?'NULL':("'".$this->db->escape($this->batch)."'")).","; $sql.= " ".(! isset($this->dluo_qty)?'NULL':$this->dluo_qty).","; $sql.= " ".(! isset($this->fk_origin_stock)?'NULL':$this->fk_origin_stock); $sql.= ")"; @@ -174,7 +174,7 @@ class ExpeditionLigneBatch extends CommonObject * * @param object $db Database object * @param int $id_line_expdet id of shipment line - * @return variant -1 if KO, array of ExpeditionLigneBatch if OK + * @return variant -1 if KO, array of ExpeditionLineBatch if OK */ static function fetchAll($db,$id_line_expdet) { diff --git a/htdocs/install/mysql/migration/repair.sql b/htdocs/install/mysql/migration/repair.sql index 9e1ca7bb6f9..fe0f8fb2a13 100755 --- a/htdocs/install/mysql/migration/repair.sql +++ b/htdocs/install/mysql/migration/repair.sql @@ -73,6 +73,18 @@ delete from llx_livraisondet where fk_livraison not in (select fk_target from ll delete from llx_livraison where rowid not in (select fk_target from llx_element_element where targettype = 'delivery') AND rowid not in (select fk_source from llx_element_element where sourcetype = 'delivery'); +-- Fix delete element_element orphelins (right side) +delete from llx_element_element where targettype='shipping' and fk_target not in (select rowid from llx_expedition); +delete from llx_element_element where targettype='propal' and fk_target not in (select rowid from llx_propal); +delete from llx_element_element where targettype='facture' and fk_target not in (select rowid from llx_facture); +delete from llx_element_element where targettype='commande' and fk_target not in (select rowid from llx_commande); +-- Fix delete element_element orphelins (left side) +delete from llx_element_element where sourcetype='shipping' and fk_source not in (select rowid from llx_expedition); +delete from llx_element_element where sourcetype='propal' and fk_source not in (select rowid from llx_propal); +delete from llx_element_element where sourcetype='facture' and fk_source not in (select rowid from llx_facture); +delete from llx_element_element where sourcetype='commande' and fk_source not in (select rowid from llx_commande); + + UPDATE llx_product SET canvas = NULL where canvas = 'default@product'; UPDATE llx_product SET canvas = NULL where canvas = 'service@product'; From aa380f6ee053302cb80aa1b177c47e3ff2f0aa17 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 16 Feb 2015 20:43:39 +0100 Subject: [PATCH 138/173] fix bad include --- htdocs/commande/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 6978de14e40..918244528cc 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1155,7 +1155,7 @@ if (empty($reshook)) $action = 'edit_extras'; } - include DOL_DOCUMENT_ROOT.'/core/actions_printipp.inc.php'; + include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php'; /* From 1e78d0e8d499e694545c698b3807af9d83f1b294 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 16 Feb 2015 20:46:54 +0100 Subject: [PATCH 139/173] New: Introduce hidden option STOCK_WAREHOUSE_NOT_REQUIRED_FOR_SHIPMENTS to solve, with no risk, a missing control on missing warehouse. --- ChangeLog | 2 ++ htdocs/core/lib/order.lib.php | 2 +- htdocs/expedition/class/expedition.class.php | 26 ++++++++++++++------ htdocs/langs/en_US/productbatch.lang | 2 +- htdocs/langs/en_US/sendings.lang | 2 +- htdocs/langs/en_US/stocks.lang | 2 +- 6 files changed, 24 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8bdae25eac7..0eac6781fc3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -85,6 +85,8 @@ For users: - New : Use of MAIN_USE_FILECACHE_EXPORT_EXCEL_DIR to use disk cache for big excel export. - New : Option on extrafields to have them always editable regardless of the document status. - New : New module PrintIPP to print without opening document is available as stable. +- New : Introduce hidden option STOCK_WAREHOUSE_NOT_REQUIRED_FOR_SHIPMENTS to solve at no risk + a missing control on missing warehouse. - Fix: [ bug #1487 ] PAYMENT_DELETE trigger does not intercept trigger action - Fix: [ bug #1470, #1472, #1473] User trigger problem - Fix: [ bug #1489, #1491 ] Intervention trigger problem diff --git a/htdocs/core/lib/order.lib.php b/htdocs/core/lib/order.lib.php index abdf1b648a5..1e0f2f50139 100644 --- a/htdocs/core/lib/order.lib.php +++ b/htdocs/core/lib/order.lib.php @@ -52,7 +52,7 @@ function commande_prepare_head($object) || ($conf->livraison_bon->enabled && $user->rights->expedition->livraison->lire)) { $head[$h][0] = DOL_URL_ROOT.'/expedition/shipment.php?id='.$object->id; - if ($conf->expedition_bon->enabled) $text=$langs->trans("Shipment"); + if ($conf->expedition_bon->enabled) $text=$langs->trans("Shipments"); if ($conf->expedition_bon->enabled && $conf->livraison_bon->enabled) $text.='/'; if ($conf->livraison_bon->enabled) $text.=$langs->trans("Receivings"); $head[$h][1] = $text; diff --git a/htdocs/expedition/class/expedition.class.php b/htdocs/expedition/class/expedition.class.php index e6cc0e86d09..0113a582dfb 100644 --- a/htdocs/expedition/class/expedition.class.php +++ b/htdocs/expedition/class/expedition.class.php @@ -732,10 +732,12 @@ class Expedition extends CommonObject } /** - * Add a expedition line + * Add a expedition line. + * If STOCK_WAREHOUSE_NOT_REQUIRED_FOR_SHIPMENTS is set, you can add a shipment line, with no stock source defined + * If STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT is not set, you can add a shipment line, even if not enough into stock * * @param int $entrepot_id Id of warehouse - * @param int $id Id of source line + * @param int $id Id of source line (order line) * @param int $qty Quantity * @return int <0 if KO, >0 if OK */ @@ -750,18 +752,26 @@ class Expedition extends CommonObject $line->origin_line_id = $id; $line->qty = $qty; - if($conf->global->STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT) { - $orderline = new OrderLine($this->db); - $orderline->fetch($id); - $fk_product = $orderline->fk_product; + $orderline = new OrderLine($this->db); + $orderline->fetch($id); + $fk_product = $orderline->fk_product; - if (!empty($orderline->fk_product)) + if (! empty($orderline->fk_product)) + { + if (! ($entrepot_id > 0) && empty($conf->global->STOCK_WAREHOUSE_NOT_REQUIRED_FOR_SHIPMENTS)) + { + $this->error=$langs->trans("ErrorWarehouseRequiredIntoShipmentLine"); + return -1; + } + + if ($conf->global->STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT) // FIXME Check is done for stock of product, it must be done for stock of product into warehouse if $entrepot_id defined { $product=new Product($this->db); $result=$product->fetch($fk_product); $product_type=$product->type; - if($product_type == 0 && $product->stock_reel < $qty) { + if ($product_type == 0 && $product->stock_reel < $qty) + { $this->error=$langs->trans('ErrorStockIsNotEnough'); $this->db->rollback(); return -3; diff --git a/htdocs/langs/en_US/productbatch.lang b/htdocs/langs/en_US/productbatch.lang index 0102f688b1b..ded965131de 100644 --- a/htdocs/langs/en_US/productbatch.lang +++ b/htdocs/langs/en_US/productbatch.lang @@ -11,7 +11,7 @@ batch_number=Batch/Serial number l_eatby=Eat-by date l_sellby=Sell-by date DetailBatchNumber=Batch/Serial details -DetailBatchFormat=Batch/Serial: %s - E:%s - S: %s (Qty : %d) +DetailBatchFormat=Batch/Serial: %s - Eat by: %s - Sell by: %s (Qty : %d) printBatch=Batch: %s printEatby=Eat-by: %s printSellby=Sell-by: %s diff --git a/htdocs/langs/en_US/sendings.lang b/htdocs/langs/en_US/sendings.lang index f1489508ec6..faf41d116b9 100644 --- a/htdocs/langs/en_US/sendings.lang +++ b/htdocs/langs/en_US/sendings.lang @@ -22,7 +22,7 @@ QtyOrdered=Qty ordered QtyShipped=Qty shipped QtyToShip=Qty to ship QtyReceived=Qty received -KeepToShip=Keep to ship +KeepToShip=Remain to ship OtherSendingsForSameOrder=Other shipments for this order DateSending=Date sending order DateSendingShort=Date sending order diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang index d77c65a9a13..0e3e7dd6c27 100644 --- a/htdocs/langs/en_US/stocks.lang +++ b/htdocs/langs/en_US/stocks.lang @@ -122,4 +122,4 @@ RuleForStockAvailability=Rules on stock requirements StockMustBeEnoughForInvoice=Stock level must be enough to add product/service into invoice StockMustBeEnoughForOrder=Stock level must be enough to add product/service into order StockMustBeEnoughForShipment= Stock level must be enough to add product/service into shipment - +WarehouseMustBeSelectedAtFirstStepWhenProductBatchModuleOn=Source warehouse must be defined here when batch module is on. It will be used to list wich lot/serial is available for product that required lot/serial data for movement. If you want to send products from different warehouses, just make the shipment into several steps. From 5688e8ecd815c5eb7e3d45b8cf1f3b94ff336dd7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 16 Feb 2015 20:51:05 +0100 Subject: [PATCH 140/173] Add todo to show code is missing here --- htdocs/expedition/class/expedition.class.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/htdocs/expedition/class/expedition.class.php b/htdocs/expedition/class/expedition.class.php index 0113a582dfb..2eb5a61e3fc 100644 --- a/htdocs/expedition/class/expedition.class.php +++ b/htdocs/expedition/class/expedition.class.php @@ -804,6 +804,12 @@ class Expedition extends CommonObject } $linebatch->dluo_qty=$value['q']; $tab[]=$linebatch; + + if ($conf->global->STOCK_MUST_BE_ENOUGH_FOR_SHIPMENT) + { + // TODO + } + } } $line->entrepot_id = $linebatch->entrepot_id; From c01281a538b300caa4d729ec094f8479190d1335 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Mon, 16 Feb 2015 23:45:52 +0100 Subject: [PATCH 141/173] Renamed WorkBoardResponse::$late_url to WorkBoardResponse::$url_late --- htdocs/core/class/WorkBoardResponse.class.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/core/class/WorkBoardResponse.class.php b/htdocs/core/class/WorkBoardResponse.class.php index 4cb0a1be0e7..ae82c7e3a48 100644 --- a/htdocs/core/class/WorkBoardResponse.class.php +++ b/htdocs/core/class/WorkBoardResponse.class.php @@ -42,18 +42,18 @@ class WorkBoardResponse */ public $url; + /** + * (optional) If set, to do late items will link to this url + * @var string + */ + public $url_late; + /** * Delay time to mark an item as late * @var int */ public $warning_delay; - /** - * (optional) If set, to do late items will link to this url - * @var string - */ - public $lateurl; - /** * Number of items to do * @var int From fa55c60c35db0023e9763101445da545e0f7b35a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Garci=CC=81a=20de=20La=20Fuente?= Date: Mon, 16 Feb 2015 23:49:07 +0100 Subject: [PATCH 142/173] Renamed WorkBoardResponse to WorkboardResponse --- htdocs/adherents/class/adherent.class.php | 4 ++-- htdocs/comm/action/class/actioncomm.class.php | 4 ++-- htdocs/comm/propal/class/propal.class.php | 4 ++-- htdocs/commande/class/commande.class.php | 4 ++-- htdocs/compta/bank/class/account.class.php | 4 ++-- htdocs/compta/facture/class/facture.class.php | 4 ++-- .../compta/paiement/cheque/class/remisecheque.class.php | 4 ++-- htdocs/contrat/class/contrat.class.php | 4 ++-- ...oardResponse.class.php => WorkboardResponse.class.php} | 4 ++-- htdocs/fourn/class/fournisseur.commande.class.php | 4 ++-- htdocs/fourn/class/fournisseur.facture.class.php | 4 ++-- htdocs/index.php | 8 ++++---- 12 files changed, 26 insertions(+), 26 deletions(-) rename htdocs/core/class/{WorkBoardResponse.class.php => WorkboardResponse.class.php} (94%) diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index b275369be4e..9a385becff3 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -1726,7 +1726,7 @@ class Adherent extends CommonObject * Load indicators for dashboard (this->nbtodo and this->nbtodolate) * * @param User $user Objet user - * @return WorkBoardResponse|int <0 if KO, WorkBoardResponse if OK + * @return WorkboardResponse|int <0 if KO, WorkboardResponse if OK */ function load_board($user) { @@ -1747,7 +1747,7 @@ class Adherent extends CommonObject { $langs->load("members"); - $response = new WorkBoardResponse(); + $response = new WorkboardResponse(); $response->warning_delay=$conf->adherent->cotisation->warning_delay/60/60/24; $response->label=$langs->trans("MembersWithSubscriptionToReceive"); $response->url=DOL_URL_ROOT.'/adherents/list.php?mainmenu=members&statut=1'; diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index e49b67604d5..5cfe1dc7310 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -716,7 +716,7 @@ class ActionComm extends CommonObject * Load indicators for dashboard (this->nbtodo and this->nbtodolate) * * @param User $user Objet user - * @return WorkBoardResponse|int <0 if KO, WorkBoardResponse if OK + * @return WorkboardResponse|int <0 if KO, WorkboardResponse if OK */ function load_board($user) { @@ -738,7 +738,7 @@ class ActionComm extends CommonObject { $now = dol_now(); - $response = new WorkBoardResponse(); + $response = new WorkboardResponse(); $response->warning_delay = $conf->actions->warning_delay/60/60/24; $response->label = $langs->trans("ActionsToDo"); $response->url = DOL_URL_ROOT.'/comm/action/listactions.php?status=todo&mainmenu=agenda'; diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index 80cfb5b3266..edc6d7bfd94 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -2345,7 +2345,7 @@ class Propal extends CommonObject * * @param User $user Object user * @param int $mode "opened" for proposal to close, "signed" for proposal to invoice - * @return WorkBoardResponse|int <0 if KO, WorkBoardResponse if OK + * @return WorkboardResponse|int <0 if KO, WorkboardResponse if OK */ function load_board($user,$mode) { @@ -2383,7 +2383,7 @@ class Propal extends CommonObject $label = $langs->trans("PropalsToBill"); } - $response = new WorkBoardResponse(); + $response = new WorkboardResponse(); $response->warning_delay = $delay_warning; $response->label = $label; $response->url = DOL_URL_ROOT.'/comm/propal/list.php?viewstatut='.$statut; diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 19fd5c98a2b..d5c6b3f7715 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -2725,7 +2725,7 @@ class Commande extends CommonOrder * Load indicators for dashboard (this->nbtodo and this->nbtodolate) * * @param User $user Object user - * @return WorkBoardResponse|int <0 if KO, WorkBoardResponse if OK + * @return WorkboardResponse|int <0 if KO, WorkboardResponse if OK */ function load_board($user) { @@ -2751,7 +2751,7 @@ class Commande extends CommonOrder { $now=dol_now(); - $response = new WorkBoardResponse(); + $response = new WorkboardResponse(); $response->warning_delay=$conf->commande->client->warning_delay/60/60/24; $response->label=$langs->trans("OrdersToProcess"); $response->url=DOL_URL_ROOT.'/commande/list.php?viewstatut=-3'; diff --git a/htdocs/compta/bank/class/account.class.php b/htdocs/compta/bank/class/account.class.php index 85a6ad24b85..a2d9aec8ad4 100644 --- a/htdocs/compta/bank/class/account.class.php +++ b/htdocs/compta/bank/class/account.class.php @@ -882,7 +882,7 @@ class Account extends CommonObject * * @param User $user Objet user * @param int $filteraccountid To get info for a particular account id - * @return WorkBoardResponse|int <0 if KO, WorkBoardResponse if OK + * @return WorkboardResponse|int <0 if KO, WorkboardResponse if OK */ function load_board($user,$filteraccountid=0) { @@ -905,7 +905,7 @@ class Account extends CommonObject $langs->load("banks"); $now=dol_now(); - $response = new WorkBoardResponse(); + $response = new WorkboardResponse(); $response->warning_delay=$conf->bank->rappro->warning_delay/60/60/24; $response->label=$langs->trans("TransactionsToConciliate"); $response->url=DOL_URL_ROOT.'/compta/bank/index.php?leftmenu=bank&mainmenu=bank'; diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 71328871323..50a68b2c66a 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -3085,7 +3085,7 @@ class Facture extends CommonInvoice * Load indicators for dashboard (this->nbtodo and this->nbtodolate) * * @param User $user Object user - * @return WorkBoardResponse|int <0 if KO, WorkBoardResponse if OK + * @return WorkboardResponse|int <0 if KO, WorkboardResponse if OK */ function load_board($user) { @@ -3112,7 +3112,7 @@ class Facture extends CommonInvoice $langs->load("bills"); $now=dol_now(); - $response = new WorkBoardResponse(); + $response = new WorkboardResponse(); $response->warning_delay=$conf->facture->client->warning_delay/60/60/24; $response->label=$langs->trans("CustomerBillsUnpaid"); $response->url=DOL_URL_ROOT.'/compta/facture/impayees.php'; diff --git a/htdocs/compta/paiement/cheque/class/remisecheque.class.php b/htdocs/compta/paiement/cheque/class/remisecheque.class.php index 88f9d573737..ddda11bb556 100644 --- a/htdocs/compta/paiement/cheque/class/remisecheque.class.php +++ b/htdocs/compta/paiement/cheque/class/remisecheque.class.php @@ -433,7 +433,7 @@ class RemiseCheque extends CommonObject * Load indicators for dashboard (this->nbtodo and this->nbtodolate) * * @param User $user Objet user - * @return WorkBoardResponse|int <0 if KO, WorkBoardResponse if OK + * @return WorkboardResponse|int <0 if KO, WorkboardResponse if OK */ function load_board($user) { @@ -456,7 +456,7 @@ class RemiseCheque extends CommonObject $langs->load("banks"); $now=dol_now(); - $response = new WorkBoardResponse(); + $response = new WorkboardResponse(); $response->warning_delay=$conf->bank->cheque->warning_delay/60/60/24; $response->label=$langs->trans("BankChecksToReceipt"); $response->url=DOL_URL_ROOT.'/compta/paiement/cheque/index.php?leftmenu=checks&mainmenu=accountancy'; diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 9a5afc0aea1..3cd35db15b5 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -1881,7 +1881,7 @@ class Contrat extends CommonObject * * @param User $user Objet user * @param string $mode "inactive" pour services a activer, "expired" pour services expires - * @return WorkBoardResponse|int <0 if KO, WorkBoardResponse if OK + * @return WorkboardResponse|int <0 if KO, WorkboardResponse if OK */ function load_board($user,$mode) { @@ -1929,7 +1929,7 @@ class Contrat extends CommonObject $label = $langs->trans("BoardRunningServices"); } - $response = new WorkBoardResponse(); + $response = new WorkboardResponse(); $response->warning_delay = $warning_delay/60/60/24; $response->label = $label; $response->url = $url; diff --git a/htdocs/core/class/WorkBoardResponse.class.php b/htdocs/core/class/WorkboardResponse.class.php similarity index 94% rename from htdocs/core/class/WorkBoardResponse.class.php rename to htdocs/core/class/WorkboardResponse.class.php index ae82c7e3a48..c36b50b421e 100644 --- a/htdocs/core/class/WorkBoardResponse.class.php +++ b/htdocs/core/class/WorkboardResponse.class.php @@ -17,11 +17,11 @@ */ /** - * \file htdocs/core/class/WorkBoardResponse.class.php + * \file htdocs/core/class/WorkboardResponse.class.php * \brief Class that represents response of load_board functions */ -class WorkBoardResponse +class WorkboardResponse { /** diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 300a1ad1260..4917ebd2779 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -2000,7 +2000,7 @@ class CommandeFournisseur extends CommonOrder * Load indicators for dashboard (this->nbtodo and this->nbtodolate) * * @param User $user Objet user - * @return WorkBoardResponse|int <0 if KO, WorkBoardResponse if OK + * @return WorkboardResponse|int <0 if KO, WorkboardResponse if OK */ function load_board($user) { @@ -2025,7 +2025,7 @@ class CommandeFournisseur extends CommonOrder { $now=dol_now(); - $response = new WorkBoardResponse(); + $response = new WorkboardResponse(); $response->warning_delay=$conf->commande->fournisseur->warning_delay/60/60/24; $response->label=$langs->trans("SuppliersOrdersToProcess"); $response->url=DOL_URL_ROOT.'/fourn/commande/index.php'; diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php index c8735362cca..d7252d188db 100644 --- a/htdocs/fourn/class/fournisseur.facture.class.php +++ b/htdocs/fourn/class/fournisseur.facture.class.php @@ -1421,7 +1421,7 @@ class FactureFournisseur extends CommonInvoice * Load indicators for dashboard (this->nbtodo and this->nbtodolate) * * @param User $user Object user - * @return WorkBoardResponse|int <0 if KO, WorkBoardResponse if OK + * @return WorkboardResponse|int <0 if KO, WorkboardResponse if OK */ function load_board($user) { @@ -1442,7 +1442,7 @@ class FactureFournisseur extends CommonInvoice $langs->load("bills"); $now=dol_now(); - $response = new WorkBoardResponse(); + $response = new WorkboardResponse(); $response->warning_delay=$conf->facture->fournisseur->warning_delay/60/60/24; $response->label=$langs->trans("SupplierBillsToPay"); $response->url=DOL_URL_ROOT.'/fourn/facture/list.php?filtre=paye:0'; diff --git a/htdocs/index.php b/htdocs/index.php index 54cda381489..32b13c7a63f 100644 --- a/htdocs/index.php +++ b/htdocs/index.php @@ -293,7 +293,7 @@ print '
'; */ $showweather=empty($conf->global->MAIN_DISABLE_METEO)?1:0; -//Array that contains all WorkBoardResponse classes to process them +//Array that contains all WorkboardResponse classes to process them $dashboardlines=array(); print ''."\n"; @@ -311,7 +311,7 @@ print ''."\n"; // Do not include sections without management permission // -require DOL_DOCUMENT_ROOT.'/core/class/WorkBoardResponse.class.php'; +require DOL_DOCUMENT_ROOT.'/core/class/WorkboardResponse.class.php'; // Number of actions to do (late) if (! empty($conf->agenda->enabled) && $user->rights->agenda->myactions->read) @@ -405,9 +405,9 @@ $totallate=0; $var=true; //Remove any invalid response -//load_board can return an integer if failed or WorkBoardResponse if OK +//load_board can return an integer if failed or WorkboardResponse if OK $valid_dashboardlines = array_filter($dashboardlines, function ($board) { - return $board instanceof WorkBoardResponse; + return $board instanceof WorkboardResponse; }); $rowspan = count($valid_dashboardlines); From a64cd69639507a7a5ef788325381f42675edb9e9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 17 Feb 2015 09:56:19 +0100 Subject: [PATCH 143/173] phpcs --- .../modules/expensereport/doc/pdf_standard.modules.php | 10 +++++----- htdocs/expensereport/class/expensereport.class.php | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php b/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php index 450007a0dc6..0323d2f383d 100755 --- a/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php +++ b/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php @@ -660,11 +660,11 @@ class pdf_ extends ModeleExpenseReport /** * Affiche la grille des lignes de factures * - * @param $pdf Objet PDF - * @param $tab_top Tab top - * @param $tab_height Tab height - * @param $nexY next y - * @param $outputlangs Output langs + * @param PDF $pdf Object PDF + * @param int $tab_top Tab top + * @param int $tab_height Tab height + * @param int $nexY next y + * @param Translate $outputlangs Output langs * @return void */ function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs) diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php index c357807f315..84db5bd9ece 100755 --- a/htdocs/expensereport/class/expensereport.class.php +++ b/htdocs/expensereport/class/expensereport.class.php @@ -561,7 +561,7 @@ class ExpenseReport extends CommonObject /** * recalculer * - * @param int $id + * @param int $id Id of expense report * @return int <0 if KO, >0 if OK */ function recalculer($id) From bc88917b812e0e69d25e654874c8085cb5259c31 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 17 Feb 2015 10:18:01 +0100 Subject: [PATCH 144/173] phpcs --- htdocs/core/modules/expensereport/doc/pdf_standard.modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php b/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php index 0323d2f383d..8b84ff505ec 100755 --- a/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php +++ b/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php @@ -444,7 +444,7 @@ class pdf_ extends ModeleExpenseReport /** * Show top header of page. * - * @param PDF &$pdf Object PDF + * @param PDF $pdf Object PDF * @param Object $object Object to show * @param int $showaddress 0=no, 1=yes * @param Translate $outputlangs Object lang for output From 9d0ffb7e85d6e06d5ab861869b2a3e611e32784b Mon Sep 17 00:00:00 2001 From: frederic34 Date: Tue, 17 Feb 2015 10:23:31 +0100 Subject: [PATCH 145/173] Add php-iban and check IBAN --- htdocs/core/lib/bank.lib.php | 23 +++++++++++++++++++++++ htdocs/societe/rib.php | 10 +++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/htdocs/core/lib/bank.lib.php b/htdocs/core/lib/bank.lib.php index e3fb787657b..77b92447d3f 100644 --- a/htdocs/core/lib/bank.lib.php +++ b/htdocs/core/lib/bank.lib.php @@ -123,6 +123,29 @@ function bank_admin_prepare_head($object) return $head; } +/** + * Check IBAN number informations for a bank account + * + * @param Account $account A bank account + * @return int True if informations are valid, false otherwise + */ +function checkIbanForAccount($account) +{ + require_once DOL_DOCUMENT_ROOT.'/includes/php-iban/oophp-iban.php'; + $iban = new Iban(); + $check = $iban->Verify($account->iban); + //print '
'.print_r($iban, true).'
'; + if ($check) { + //print '
OK
'; + return true; + } else { + //$suggest = $iban->MistranscriptionSuggestions($account->iban); + //print '
'.print_r($suggest, true).'
'; + return false; + } + +} + /** * Check account number informations for a bank account * diff --git a/htdocs/societe/rib.php b/htdocs/societe/rib.php index f57eb6a5b70..a615577a8c4 100644 --- a/htdocs/societe/rib.php +++ b/htdocs/societe/rib.php @@ -293,7 +293,15 @@ if ($socid && $action != 'edit' && $action != "create") } print '
'; - print ''; + print ''; print ''; print ''; From 07197f3ca08b5dad641ee21887c7fc4327abf573 Mon Sep 17 00:00:00 2001 From: frederic34 Date: Tue, 17 Feb 2015 10:24:37 +0100 Subject: [PATCH 146/173] Add libs --- htdocs/core/lib/bank.lib.php | 4 +- htdocs/includes/php-iban/LICENSE | 165 ++++++ .../includes/php-iban/docs/COMEDY-OF-ERRORS | 55 ++ ...d implementation guidelines SIG203V3.2.pdf | Bin 0 -> 229029 bytes htdocs/includes/php-iban/docs/HACKING | 63 +++ htdocs/includes/php-iban/docs/ISO13616.pdf | Bin 0 -> 141593 bytes htdocs/includes/php-iban/docs/LICENSE | 165 ++++++ htdocs/includes/php-iban/docs/README | 207 ++++++++ htdocs/includes/php-iban/docs/REGISTRY-URL | 17 + htdocs/includes/php-iban/docs/SEPA | 9 + htdocs/includes/php-iban/docs/TODO | 21 + .../includes/php-iban/mistranscriptions.txt | 49 ++ htdocs/includes/php-iban/oophp-iban.php | 157 ++++++ htdocs/includes/php-iban/php-iban.php | 486 ++++++++++++++++++ htdocs/includes/php-iban/registry.txt | 81 +++ 15 files changed, 1477 insertions(+), 2 deletions(-) create mode 100644 htdocs/includes/php-iban/LICENSE create mode 100644 htdocs/includes/php-iban/docs/COMEDY-OF-ERRORS create mode 100644 htdocs/includes/php-iban/docs/ECBS standard implementation guidelines SIG203V3.2.pdf create mode 100644 htdocs/includes/php-iban/docs/HACKING create mode 100644 htdocs/includes/php-iban/docs/ISO13616.pdf create mode 100644 htdocs/includes/php-iban/docs/LICENSE create mode 100644 htdocs/includes/php-iban/docs/README create mode 100644 htdocs/includes/php-iban/docs/REGISTRY-URL create mode 100644 htdocs/includes/php-iban/docs/SEPA create mode 100644 htdocs/includes/php-iban/docs/TODO create mode 100644 htdocs/includes/php-iban/mistranscriptions.txt create mode 100644 htdocs/includes/php-iban/oophp-iban.php create mode 100644 htdocs/includes/php-iban/php-iban.php create mode 100644 htdocs/includes/php-iban/registry.txt diff --git a/htdocs/core/lib/bank.lib.php b/htdocs/core/lib/bank.lib.php index 77b92447d3f..36626ffcc94 100644 --- a/htdocs/core/lib/bank.lib.php +++ b/htdocs/core/lib/bank.lib.php @@ -132,8 +132,8 @@ function bank_admin_prepare_head($object) function checkIbanForAccount($account) { require_once DOL_DOCUMENT_ROOT.'/includes/php-iban/oophp-iban.php'; - $iban = new Iban(); - $check = $iban->Verify($account->iban); + $iban = new Iban($account->iban); + $check = $iban->Verify(); //print '
'.print_r($iban, true).'
'; if ($check) { //print '
OK
'; diff --git a/htdocs/includes/php-iban/LICENSE b/htdocs/includes/php-iban/LICENSE new file mode 100644 index 00000000000..65c5ca88a67 --- /dev/null +++ b/htdocs/includes/php-iban/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/htdocs/includes/php-iban/docs/COMEDY-OF-ERRORS b/htdocs/includes/php-iban/docs/COMEDY-OF-ERRORS new file mode 100644 index 00000000000..0eb3b8860ad --- /dev/null +++ b/htdocs/includes/php-iban/docs/COMEDY-OF-ERRORS @@ -0,0 +1,55 @@ +This file lists specific errors observed in the official IBAN specification. + +In addition to the specific errors, there persist basic outstanding +matters that cause issue for implementers: + - Non 1:1 mapping of records to countries (eg: French territories, etc.) + - Mixing of free text and hard data in specification fields + - Lack of validation of information in fields prior to publishing + - Lack of synchronisation between TXT and PDF versions of the registry + +2011-07-16 +---------- + - No information for Kuwait past sixth column + - Total absence of information regarding Kazakhstan + - '1.00001E+15' instead of a valid BBAN example for Lithuania + - Repeated IBAN example in human format instead of IBAN format- + specification for UAE + - Incorrect domestic example for Bulgaria, Kazakhstan, Latvia, + Lithuania, Luxembourg, Macedonia, Mauritius, Romania, San Marino + (complete, human-format IBAN instead of domestic example) + +Early 2012 +---------- + - Inconsistent record ordering (KW, KZ) + - Inconsistent capitalization (DK) + - Continued presence of incorrect domestic examples + +February 2013 +------------- + - Deployment of unparseable special values such as "Not in use" (FI). + - Still(!) missing a registry entry for 2010's 'new' entry of Khazakstan + +September 2013 +-------------- + - Azerbaijan, Brazil, Costa Rica, Palestine, Virgin Islands 'SEPA + Country' field in PDF (yes/no) is completely blank + +March 2014 +---------- + - In multiple cases, territories of a major country have a SEPA status + that differs from the parent jurisdiction. The IBAN specification as + previously released does not include individual records for these + territories, and thus cannot convey this important information. + - The IBAN registry's old URL is no longer publicly available! Its now + ends in a 404, and the apparent new home, located over at + http://www.swift.com/products_services/by_type/reference_data/iban_registry_iso13616 + does not have any content. The parent portion of this part of the + SWIFT website suggests the information may have been moved to a new + 'SWIFTRef' site, however that site appears to only peddle paid for + directories of BICs and similar. The new location after much + searching was found to be http://www.swift.com/products_services/bic_and_iban_format_registration_iban_format_r + +June 2014 +--------- + - The TXT registry records of QA and JO do not match those within the + PDF and are essentially spurious while looking roughly correct. Dang. diff --git a/htdocs/includes/php-iban/docs/ECBS standard implementation guidelines SIG203V3.2.pdf b/htdocs/includes/php-iban/docs/ECBS standard implementation guidelines SIG203V3.2.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c7c860aee67e0d718e9c87eee383c28d01c0c6f7 GIT binary patch literal 229029 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 literal 0 HcmV?d00001 diff --git a/htdocs/includes/php-iban/docs/HACKING b/htdocs/includes/php-iban/docs/HACKING new file mode 100644 index 00000000000..dfc48f1ae5b --- /dev/null +++ b/htdocs/includes/php-iban/docs/HACKING @@ -0,0 +1,63 @@ +By unix tradition, this file outlines information that may be useful to +people who wish to modify the php-iban project. It outlines some basic +information around design decisions and other considerations. + + Procedural style + ---------------- + The code is written in PHP's original procedural style, and does + not require or assume any OO model. This is unix tradition and + should ease any integration pains due to objectspace mismatches. + In addition, it should make it easy for users both within an OO + or a procedural codebase to make use of the library. An OO wrapper + has been supplied to make things more familiar for those who are + only exposed to OO PHP: please try to keep it in synch with the + procedural (main) library where possible. + + Registry maintenance + -------------------- + The 'convert-registry.php' tool found in the 'utils/' subdirectory + is intended to assist with the automatic conversion of the SWIFT- + provided 'IBAN Registry' text files to the format required to + support php-iban execution. Why is there a new format, and why is it + distributed with php-iban instead of being generated on the fly + from SWIFT-provided data files? There are a few reasons: + + - Error correction + If errors are discovered in the official specification then they + can be resolved by us. There are (or have been) known errors + with the official IBAN Registry. (See COMEDY-OF-ERRORS) + + - Exclusion correction + If exclusions are discovered in the official specification then + they can be resolved by us. There are (or have been) known + exclusions from the official IBAN Registry. (See COMEDY-OF-ERRORS) + + - Efficiency + Because pattern matching is a core part of the functionality of + php-iban, and the pattern algorithms distributed by SWIFT are + (rather strangely) not in regular expression format, using their + files directly would result in a fairly significant startup + penalty as pattern conversion would be required (at each + invocation!) unless a caching strategy were deployed, which would + create additional complexity and sources of bugs (in addition, + due to the previous two points automatic conversion is not + presently possible ... and may never be!) + + - Maintainability + Distribution of a modified registry along with php-iban places + the burden of registry maintenance on with the package + maintainer(s) rather than with the user. This is better for + users who, if they really want, can still hack their local copy. + + Note that due to points one and two, the 'convert-registry.php' tool + is insufficient to produce a correct 'registry.txt' file. (You may + wish to review the differences between your newly generated file + and the original with the 'diff' tool in order to ascertain what + has changed.) + + A closing point on the registry: obviously, if any new fields are + added, then it is best to append them to the end of the registry + (rightmost, new field) in order to preserve backwards compatibility + instead of re-ordering the fields which would break older installs. + (The internal '_iban_load_registry()' function re-orders these fields + at load time in order to simplify runtime debugging, anyway.) diff --git a/htdocs/includes/php-iban/docs/ISO13616.pdf b/htdocs/includes/php-iban/docs/ISO13616.pdf new file mode 100644 index 0000000000000000000000000000000000000000..fa23285c4f773896fee58e41970274af10ec5fd4 GIT binary patch literal 141593 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 P=U`jbxq0*M)1A)Wf3>z5 literal 0 HcmV?d00001 diff --git a/htdocs/includes/php-iban/docs/LICENSE b/htdocs/includes/php-iban/docs/LICENSE new file mode 100644 index 00000000000..fc8a5de7edf --- /dev/null +++ b/htdocs/includes/php-iban/docs/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/htdocs/includes/php-iban/docs/README b/htdocs/includes/php-iban/docs/README new file mode 100644 index 00000000000..e0deacd88f3 --- /dev/null +++ b/htdocs/includes/php-iban/docs/README @@ -0,0 +1,207 @@ +php-iban README +--------------- + +php-iban is a library for parsing and validating International Bank +Account Number (IBAN) information in PHP. + +It also validates Internet International Bank Account Number +(IIBAN) as specified at http://tools.ietf.org/html/draft-iiban-01 +(see also http://www.ifex-project.org/our-proposals/iiban) + +php-iban lives at http://code.google.com/p/php-iban + + What is an IBAN? + ---------------- + An IBAN is basically a standardised way of explaining a bank + account number that works across borders. Its structure is: + + + + + BBAN is the term used to describe the national-level format + for a bank account number, which varies between countries + (and was sometimes created just to get IBAN connectivity!). + Note that a BBAN may have its own checksum algorithm. + + IBAN provides basic protection, using the checksum, against + transcription (ie: human copying) errors. It also provides + a registry of valid destination countries and their BBAN + formats. Thus, when you ask php-iban to 'validate' an IBAN + it ensures that these checks are passed. However, it cannot + ensure that a bank account actually exists - the only party + who can do that is the receiving bank or country. + + IBAN was invented in Europe, however its usage is growing + rapidly to other parts of the world. Thus, the future of + this library looks pretty good. + + For further information, please see 'docs/ISO13616.pdf' or + visit Wikipedia at http://en.wikipedia.org/wiki/IBAN + + What is an IIBAN? + ----------------- + An Internet IBAN (IIBAN) identifies an internet-based financial + endpoint in a manner that is superset-compatible with the existing + European Committee for Banking Standards (ECBS) International Bank + Account Number (IBAN) standard [ISO13616]. + + For more information see http://tools.ietf.org/html/draft-iiban-00 + and http://www.ifex-project.org/our-proposals/iiban + + To disable IIBAN support from your installation, simply remove + the second ('AA|...') line from the top of the registry.txt file. + + Execution environment + --------------------- + At present the library merely requires a PHP engine to be present + and has no external dependencies. It is recommended that your + PHP engine is configured to disable verbose warnings for events + such as access of unknown array indexes, though this should be + standard on almost any PHP deployment today. Any PHP engine + in use today should be compatible, though PHP3 or PHP4 execution + environments may require minor modifications (specifically, + some string functions may have changed). + + Installation + ------------ + Simply copy 'php-iban.php' and 'registry.txt' to an appropriate + location for your project. The location of the files will affect + the 'require_once()' line used to load the library from your + codebase, and may have relevance security (see 'Security' below). + Note that 'php-iban.php' expects to find 'registry.txt' in the + same directory as itself. + + Security + -------- + Following best practice for library files, the location chosen + for the php-iban.php and registry.txt files should ideally be + outside of any web-accessible directories. Thus, if your + web project lives in /var/www/myproject/htdocs/ then it would + be preferably to place php-iban in /var/www/myproject or some + other directory that is not visible to regular web users. + + Secondly, neither file should be writable by the web server + itself in order to prevent compromise of the execution path + (ie: getting hacked). So, for example if your web server runs + as user 'www', group 'www', you can ensure that the web server + has minimal required privileges against the files as follows + (note that you will need to be root to execute these commands): + + # chown php-iban registry.txt # where is a + # non-root user that + # is not 'www'. + # chgrp www php-iban registry.txt # set group to 'www' + # chmod ugo-rwx php-iban registry.txt # remove privileges + # chmod g+r php-iban registry.txt # allow 'www' group + # to read the files + + Obviously the above do not apply if you are using PHP in a + non web-oriented project (eg: a cronjob or daemon), a usage + of the language that is apparently growing - but limited. + + Using the library + ----------------- + Basic invocation is as follows: + + # include the library + require_once('/path/to/php-iban.php'); # /path/to/ is optional + + # use some library function or other... + if(!verify_iban($iban_to_verify)) { + # blame the user... + } + + Note that because the library is designed in a procedural manner + rather than an object-oriented manner it should be easy to + integrate with a wide variety of established codebases and + PHP interpreter versions. + + Using the library's OO wrapper + ------------------------------ + Because many new PHP programmers seems to learn the language via + books that only teach OO based programming and are thus unfamiliar + with procedural PHP (and often relatively inexperienced as + programmers, too) an OO wrapper-library has been provided. + + ======================= READ THIS ================================= + However *you should avoid excessive use of OO*. For some thought + provoking discussions of the negative aspects of overusing OO, + please refer to 'Coders at Work' and 'The Art of UNIX Programming'. + (OO is great for some problems, but simply pointless for most.) + =================================================================== + + Anyway, to use the OO wrapper supplied, invocation is as follows: + + # include the OO wrapper to the library + require_once('/path/to/oophp-iban.php'); # /path/to is optional + + # instantiate an IBAN object + $myIban = new IBAN('AZ12345678901234'); + if(!$myIban->Verify()) { + # blame the user... + } + + Documentation + ------------- + There are three types of functions provided by the library: + + - IBAN-level functions + + These are functions that operate on an IBAN. All of these + functions accept either machine format or human format + IBANs as input. Typically they return facts about an IBAN + as their output (for example whether it is valid or not, + or the BBAN (national-level) portion of the IBAN), though + some of them may perform other functions (eg: fixing a + broken IBAN checksum). These functions are named 'iban_*' + with the exception of the most commonly used function, + 'verify_iban()', and excepting the country-level functions. + + (Regarding the object oriented wrapper - all of these + functions are implemented as methods on IBAN objects) + + - IBAN country-level functions + These functions return information about countries that are + part of the IBAN standard. They each take the two letter + ISO country code at the beginning of an IBAN as their + argument. They are named 'iban_country_*', with the + exception of 'iban_countries()' which returns a list of + the known IBAN countries. (For example, functions that + return an example IBAN or BBAN for the country, or the + name of the country.) + + (Regarding the object oriented wrapper - all of these + functions are implemented as methods on IBANCountry + objects, except for 'iban_countries()' which is + implemented as the Countries() method on the IBAN class) + + - Internal functions + These functions begin with '_iban_*' and can be ignored. + + (Regarding the object oriented wrapper - these functions + are not present) + + Please refer to either http://code.google.com/p/php-iban or the + commented source code of php-iban itself for the complete list of + which functions are available. Of course, in unix style one could + achieve the same in a pinch as follows (instant documentation!): + $ grep function php-iban.php + $ egrep '(Class|function)' oophp-iban.php + + Community + --------- + You are encouraged to contribute bugs, feedback and suggestions + through the project's website. + + Particularly if you deploy php-iban in a commercial setting, you are + STRONGLY encouraged to join the project's mailing list, which can + be found via the website. Joining the mailing list ensures that you + can be made aware of important updates. Important updates include: + - Updates to new registry editions (support new countries that have + been added to the IBAN system) + - Bug fixes + - Security updates + + The email list receives almost no traffic and as a 'Google Group' is + well protected from spam, so don't worry about junk in your inbox. + +Thanks for choosing php-iban! You have excellent taste in software ;) diff --git a/htdocs/includes/php-iban/docs/REGISTRY-URL b/htdocs/includes/php-iban/docs/REGISTRY-URL new file mode 100644 index 00000000000..58fb8c6dadb --- /dev/null +++ b/htdocs/includes/php-iban/docs/REGISTRY-URL @@ -0,0 +1,17 @@ +To get the latest ISO13616 IBAN registry, go to: + http://www.swift.com/products_services/bic_and_iban_format_registration_iban_format_r + +TXT format: + http://www.swift.com/dsp/resources/documents/IBAN_Registry.txt + +PDF format: + http://www.swift.com/dsp/resources/documents/IBAN_Registry.pdf + +Unfortunately, it has been noticed in 2011 that the official .txt file is +not an accurate representation of the PDF format specification, and lacks +some information. It is hoped that in future SWIFT will be more careful to +publish only correct standards information. + +It has been noted in 2014 that this is still the case. + +(For more information on this subject, see the HACKING file) diff --git a/htdocs/includes/php-iban/docs/SEPA b/htdocs/includes/php-iban/docs/SEPA new file mode 100644 index 00000000000..8310ff1cfb0 --- /dev/null +++ b/htdocs/includes/php-iban/docs/SEPA @@ -0,0 +1,9 @@ +Interpreting the SEPA Field +=========================== + +Note that some IIBAN providers may in fact provide SEPA connectivity. + +Thus, implementers are reminded to consider the reported SEPA status +of a country within the registry as confirming rather than negating +the potential SEPA status of a potential financial institution who +may be party to a proposed transaction. diff --git a/htdocs/includes/php-iban/docs/TODO b/htdocs/includes/php-iban/docs/TODO new file mode 100644 index 00000000000..906ab7e3fb6 --- /dev/null +++ b/htdocs/includes/php-iban/docs/TODO @@ -0,0 +1,21 @@ +TODO +---- + + - Finnish record suggests position at which to pad domestic account + numbers in order to reach a BBAN / IBAN, this data could be of + some use for certain applications and would be nice to include + - Addition of information regarding preferred human-level formatting + for each country's BBAN - worthwhile? + - Addition of 'date effective' information for records such as BH + and the UAE that published data in advance of deployment + - Support for calculating or validating any known national (sub- + BBAN-level) checksum algorithms? + - URLs to national-level BBAN format specifications + - Consider adding a library of localised forms and abbreviations + for account number portions, for example Austria and Germany seem + to have 'Kontonummer' (KTO) for account number, and 'Bankleitzah' + (BLZ) for bank identifier. This could assist greatly with + deployments requiring international and/or constrained input. + - Consider building a library of national-level bank or payment + institution identifier codes. This would be rather large and an + optional extension and would be in competition with SWIFTRef. diff --git a/htdocs/includes/php-iban/mistranscriptions.txt b/htdocs/includes/php-iban/mistranscriptions.txt new file mode 100644 index 00000000000..7593475ff6f --- /dev/null +++ b/htdocs/includes/php-iban/mistranscriptions.txt @@ -0,0 +1,49 @@ + ; formalities + input-roman = number / letter + number = c-0 / c-1 / c-2 / c-3 / c-4 / c-5 / c-6 / c-7 / c-8 / c-9 + letter = c-a / c-b / c-c / c-d / c-e / c-f / c-g / c-h / c-i / c-j + / c-k / c-l / c-m / c-n / c-o / c-p / c-q / c-r / c-s + / c-t / c-u / c-v / c-w / c-x / c-y / c-z + + ; possible sources of mistranscribed numbers + c-0 = "O" / "6" / "D" / "G" + c-1 = "I" / "L" / "7" / "2" / "Z" + c-2 = "Z" / "7" / "P" / "E" / "1" + c-3 = "8" / "B" + c-4 = "G" / "U" + c-5 = "S" / "7" + c-6 = "0" / "O" / "8" / "G" / "C" / "B" / "D" + c-7 = "J" / "I" / "1" / "L" + c-8 = "B" / "3" / "6" + c-9 = "G" / "Y" / "O" / "0" / "D" + + ; possible sources of mistranscribed letters + c-a = "G" / "Q" / "O" / "0" + c-b = "6" / "3" / "8" / "P" / "0" / "O" + c-c = "R" / "6" / "I" / "L" / "O" / "0" + c-d = "0" / "O" / "9" / "Q" / "G" / "6" / "A" + c-e = "F" / "G" / "0" / "2" / "K" / "Z" / "S" / "O" + c-f = "E" / "K" / "T" / "P" / "Y" / "4" / "B" / "7" / "1" + c-g = "9" / "Q" / "8" / "6" / "0" / "C" / "4" / "O" + c-h = "B" / "N" / "A" / "4" / "6" / "M" / "W" / "F" / "R" / "T" / "X" + c-i = "1" / "L" / "7" / "J" / "2" / "T" / "Z" + c-j = "I" / "7" / "2" / "9" / "1" / "U" / "T" / "Q" / "P" / "Y" / "Z" + / "L" / "S" + c-k = "F" / "X" / "H" / "R" + c-l = "1" / "2" / "7" / "C" / "I" / "J" / "R" / "T" / "Y" / "Z" + c-m = "H" / "8" / "E" / "3" / "N" / "V" / "W" + c-n = "H" / "R" / "C" / "2" / "4" / "M" / "O" / "P" / "K" / "T" / "Z" + c-o = "0" / "6" / "9" / "A" / "D" / "G" / "C" / "E" / "B" / "N" / "P" + / "Q" / "R" + c-p = "F" / "4" / "8" / "2" / "B" / "J" / "R" / "N" / "O" / "T" / "Y" + c-q = "O" / "G" / "9" / "Y" / "1" / "7" / "L" + c-r = "K" / "B" / "V" / "C" / "1" / "L" / "2" + c-s = "5" / "6" / "9" / "B" / "G" / "Q" / "A" / "Y" + c-t = "1" / "4" / "7" / "F" / "I" / "J" / "L" / "P" / "X" / "Y" + c-u = "V" / "N" / "A" / "4" / "9" / "W" / "Y" + c-v = "U" / "R" / "N" + c-w = "M" / "N" / "U" / "V" + c-x = "K" / "F" / "4" / "T" / "V" / "Y" + c-y = "G" / "V" / "J" / "I" / "4" / "9" / "T" / "F" / "Q" / "1" + c-z = "2" / "1" / "L" / "R" / "I" / "7" / "V" / "3" / "4" + diff --git a/htdocs/includes/php-iban/oophp-iban.php b/htdocs/includes/php-iban/oophp-iban.php new file mode 100644 index 00000000000..76e3cd0d06b --- /dev/null +++ b/htdocs/includes/php-iban/oophp-iban.php @@ -0,0 +1,157 @@ +iban = $iban; + } + + public function Verify($iban='') { + if($iban!='') { return verify_iban($iban); } + return verify_iban($this->iban); + # we could throw exceptions of various types, but why - does it really + # add anything? possibly some slightly better user feedback potential. + # however, this can be written by hand by performing individual checks + # ala the code in verify_iban() itself where required, which is likely + # almost never. for the increased complexity and + # maintenance/documentation cost, i say, therefore: no. no exceptions. + } + + public function MistranscriptionSuggestions() { + return iban_mistranscription_suggestions($this->iban); + } + + public function MachineFormat() { + return iban_to_machine_format($this->iban); + } + + public function HumanFormat() { + return iban_to_human_format($this->iban); + } + + public function Country($iban='') { + return iban_get_country_part($this->iban); + } + + public function Checksum($iban='') { + return iban_get_checksum_part($this->iban); + } + + public function BBAN() { + return iban_get_bban_part($this->iban); + } + + public function VerifyChecksum() { + return iban_verify_checksum($this->iban); + } + + public function FindChecksum() { + return iban_find_checksum($this->iban); + } + + public function SetChecksum() { + $this->iban = iban_set_checksum($this->iban); + } + + public function ChecksumStringReplace() { + return iban_checksum_string_replace($this->iban); + } + + public function Parts() { + return iban_get_parts($this->iban); + } + + public function Bank() { + return iban_get_bank_part($this->iban); + } + + public function Branch() { + return iban_get_branch_part($this->iban); + } + + public function Account() { + return iban_get_account_part($this->iban); + } + + public function Countries() { + return iban_countries(); + } +} + +# IBANCountry +Class IBANCountry { + + # constructor with code + function __construct($code = '') { + $this->code = $code; + } + + public function Name() { + return iban_country_get_country_name($this->code); + } + + public function DomesticExample() { + return iban_country_get_domestic_example($this->code); + } + + public function BBANExample() { + return iban_country_get_bban_example($this->code); + } + + public function BBANFormatSWIFT() { + return iban_country_get_bban_format_swift($this->code); + } + + public function BBANFormatRegex() { + return iban_country_get_bban_format_regex($this->code); + } + + public function BBANLength() { + return iban_country_get_bban_length($this->code); + } + + public function IBANExample() { + return iban_country_get_iban_example($this->code); + } + + public function IBANFormatSWIFT() { + return iban_country_get_iban_format_swift($this->code); + } + + public function IBANFormatRegex() { + return iban_country_get_iban_format_regex($this->code); + } + + public function IBANLength() { + return iban_country_get_iban_length($this->code); + } + + public function BankIDStartOffset() { + return iban_country_get_bankid_start_offset($this->code); + } + + public function BankIDStopOffset() { + return iban_country_get_bankid_stop_offset($this->code); + } + + public function BranchIDStartOffset() { + return iban_country_get_branchid_start_offset($this->code); + } + + public function BranchIDStopOffset() { + return iban_country_get_branchid_stop_offset($this->code); + } + + public function RegistryEdition() { + return iban_country_get_registry_edition($this->code); + } + + public function IsSEPA() { + return iban_country_is_sepa($this->code); + } + +} + +?> diff --git a/htdocs/includes/php-iban/php-iban.php b/htdocs/includes/php-iban/php-iban.php new file mode 100644 index 00000000000..e4ef4d8dd1d --- /dev/null +++ b/htdocs/includes/php-iban/php-iban.php @@ -0,0 +1,486 @@ +0) && (($i+1)%4==0)) { $human_iban .= ' '; } + } + return $human_iban; +} + +# Get the country part from an IBAN +function iban_get_country_part($iban) { + $iban = iban_to_machine_format($iban); + return substr($iban,0,2); +} + +# Get the checksum part from an IBAN +function iban_get_checksum_part($iban) { + $iban = iban_to_machine_format($iban); + return substr($iban,2,2); +} + +# Get the BBAN part from an IBAN +function iban_get_bban_part($iban) { + $iban = iban_to_machine_format($iban); + return substr($iban,4); +} + +# Check the checksum of an IBAN - code modified from Validate_Finance PEAR class +function iban_verify_checksum($iban) { + # convert to machine format + $iban = iban_to_machine_format($iban); + # move first 4 chars (countrycode and checksum) to the end of the string + $tempiban = substr($iban, 4).substr($iban, 0, 4); + # subsitutute chars + $tempiban = iban_checksum_string_replace($tempiban); + # mod97-10 + $result = iban_mod97_10($tempiban); + # checkvalue of 1 indicates correct IBAN checksum + if ($result != 1) { + return false; + } + return true; +} + +# Find the correct checksum for an IBAN +# $iban The IBAN whose checksum should be calculated +function iban_find_checksum($iban) { + $iban = iban_to_machine_format($iban); + # move first 4 chars to right + $left = substr($iban,0,2) . '00'; # but set right-most 2 (checksum) to '00' + $right = substr($iban,4); + # glue back together + $tmp = $right . $left; + # convert letters using conversion table + $tmp = iban_checksum_string_replace($tmp); + # get mod97-10 output + $checksum = iban_mod97_10_checksum($tmp); + # return 98 minus the mod97-10 output, left zero padded to two digits + return str_pad((98-$checksum),2,'0',STR_PAD_LEFT); +} + +# Set the correct checksum for an IBAN +# $iban IBAN whose checksum should be set +function iban_set_checksum($iban) { + $iban = iban_to_machine_format($iban); + return substr($iban,0,2) . iban_find_checksum($iban) . substr($iban,4); +} + +# Character substitution required for IBAN MOD97-10 checksum validation/generation +# $s Input string (IBAN) +function iban_checksum_string_replace($s) { + $iban_replace_chars = range('A','Z'); + foreach (range(10,35) as $tempvalue) { $iban_replace_values[]=strval($tempvalue); } + return str_replace($iban_replace_chars,$iban_replace_values,$s); +} + +# Same as below but actually returns resulting checksum +function iban_mod97_10_checksum($numeric_representation) { + $checksum = intval(substr($numeric_representation, 0, 1)); + for ($position = 1; $position < strlen($numeric_representation); $position++) { + $checksum *= 10; + $checksum += intval(substr($numeric_representation,$position,1)); + $checksum %= 97; + } + return $checksum; +} + +# Perform MOD97-10 checksum calculation ('Germanic-level effiency' version - thanks Chris!) +function iban_mod97_10($numeric_representation) { + global $__disable_iiban_gmp_extension; + # prefer php5 gmp extension if available + if(!($__disable_iiban_gmp_extension) && function_exists('gmp_intval')) { return gmp_intval(gmp_mod(gmp_init($numeric_representation, 10),'97')) === 1; } + +/* + # old manual processing (~16x slower) + $checksum = intval(substr($numeric_representation, 0, 1)); + for ($position = 1; $position < strlen($numeric_representation); $position++) { + $checksum *= 10; + $checksum += intval(substr($numeric_representation,$position,1)); + $checksum %= 97; + } + return $checksum; + */ + + # new manual processing (~3x slower) + $length = strlen($numeric_representation); + $rest = ""; + $position = 0; + while ($position < $length) { + $value = 9-strlen($rest); + $n = $rest . substr($numeric_representation,$position,$value); + $rest = $n % 97; + $position = $position + $value; + } + return ($rest === 1); +} + +# Get an array of all the parts from an IBAN +function iban_get_parts($iban) { + return array( + 'country' => iban_get_country_part($iban), + 'checksum' => iban_get_checksum_part($iban), + 'bban' => iban_get_bban_part($iban), + 'bank' => iban_get_bank_part($iban), + 'country' => iban_get_country_part($iban), + 'branch' => iban_get_branch_part($iban), + 'account' => iban_get_account_part($iban) + ); +} + +# Get the Bank ID (institution code) from an IBAN +function iban_get_bank_part($iban) { + $iban = iban_to_machine_format($iban); + $country = iban_get_country_part($iban); + $start = iban_country_get_bankid_start_offset($country); + $stop = iban_country_get_bankid_stop_offset($country); + if($start!=''&&$stop!='') { + $bban = iban_get_bban_part($iban); + return substr($bban,$start,($stop-$start+1)); + } + return ''; +} + +# Get the Branch ID (sort code) from an IBAN +function iban_get_branch_part($iban) { + $iban = iban_to_machine_format($iban); + $country = iban_get_country_part($iban); + $start = iban_country_get_branchid_start_offset($country); + $stop = iban_country_get_branchid_stop_offset($country); + if($start!=''&&$stop!='') { + $bban = iban_get_bban_part($iban); + return substr($bban,$start,($stop-$start+1)); + } + return ''; +} + +# Get the (branch-local) account ID from an IBAN +function iban_get_account_part($iban) { + $iban = iban_to_machine_format($iban); + $country = iban_get_country_part($iban); + $start = iban_country_get_branchid_stop_offset($country); + if($start=='') { + $start = iban_country_get_bankid_stop_offset($country); + } + if($start!='') { + $bban = iban_get_bban_part($iban); + return substr($bban,$start+1); + } + return ''; +} + +# Get the name of an IBAN country +function iban_country_get_country_name($iban_country) { + return _iban_country_get_info($iban_country,'country_name'); +} + +# Get the domestic example for an IBAN country +function iban_country_get_domestic_example($iban_country) { + return _iban_country_get_info($iban_country,'domestic_example'); +} + +# Get the BBAN example for an IBAN country +function iban_country_get_bban_example($iban_country) { + return _iban_country_get_info($iban_country,'bban_example'); +} + +# Get the BBAN format (in SWIFT format) for an IBAN country +function iban_country_get_bban_format_swift($iban_country) { + return _iban_country_get_info($iban_country,'bban_format_swift'); +} + +# Get the BBAN format (as a regular expression) for an IBAN country +function iban_country_get_bban_format_regex($iban_country) { + return _iban_country_get_info($iban_country,'bban_format_regex'); +} + +# Get the BBAN length for an IBAN country +function iban_country_get_bban_length($iban_country) { + return _iban_country_get_info($iban_country,'bban_length'); +} + +# Get the IBAN example for an IBAN country +function iban_country_get_iban_example($iban_country) { + return _iban_country_get_info($iban_country,'iban_example'); +} + +# Get the IBAN format (in SWIFT format) for an IBAN country +function iban_country_get_iban_format_swift($iban_country) { + return _iban_country_get_info($iban_country,'iban_format_swift'); +} + +# Get the IBAN format (as a regular expression) for an IBAN country +function iban_country_get_iban_format_regex($iban_country) { + return _iban_country_get_info($iban_country,'iban_format_regex'); +} + +# Get the IBAN length for an IBAN country +function iban_country_get_iban_length($iban_country) { + return _iban_country_get_info($iban_country,'iban_length'); +} + +# Get the BBAN Bank ID start offset for an IBAN country +function iban_country_get_bankid_start_offset($iban_country) { + return _iban_country_get_info($iban_country,'bban_bankid_start_offset'); +} + +# Get the BBAN Bank ID stop offset for an IBAN country +function iban_country_get_bankid_stop_offset($iban_country) { + return _iban_country_get_info($iban_country,'bban_bankid_stop_offset'); +} + +# Get the BBAN Branch ID start offset for an IBAN country +function iban_country_get_branchid_start_offset($iban_country) { + return _iban_country_get_info($iban_country,'bban_branchid_start_offset'); +} + +# Get the BBAN Branch ID stop offset for an IBAN country +function iban_country_get_branchid_stop_offset($iban_country) { + return _iban_country_get_info($iban_country,'bban_branchid_stop_offset'); +} + +# Get the registry edition for an IBAN country +function iban_country_get_registry_edition($iban_country) { + return _iban_country_get_info($iban_country,'registry_edition'); +} + +# Is the IBAN country a SEPA member? +function iban_country_is_sepa($iban_country) { + return _iban_country_get_info($iban_country,'country_sepa'); +} + +# Get the list of all IBAN countries +function iban_countries() { + global $_iban_registry; + return array_keys($_iban_registry); +} + +# Given an incorrect IBAN, return an array of zero or more checksum-valid +# suggestions for what the user might have meant, based upon common +# mistranscriptions. +function iban_mistranscription_suggestions($incorrect_iban) { + + # abort on ridiculous length input (but be liberal) + $length = strlen($incorrect_iban); + if($length<5 || $length>34) { return array('(length bad)'); } + + # abort if mistranscriptions data is unable to load + if(!_iban_load_mistranscriptions()) { return array('(failed to load)'); } + + # init + global $_iban_mistranscriptions; + $suggestions = array(); + + # we have a string of approximately IBAN-like length. + # ... now let's make suggestions. + $numbers = array('0','1','2','3','4','5','6','7','8','9'); + for($i=0;$i<$length;$i++) { + # get the character at this position + $character = substr($incorrect_iban,$i,1); + # for each known transcription error resulting in this character + foreach($_iban_mistranscriptions[$character] as $possible_origin) { + # if we're: + # - in the first 2 characters (country) and the possible replacement + # is a letter + # - in the 3rd or 4th characters (checksum) and the possible + # replacement is a number + # - later in the string + if(($i<2 && !in_array($possible_origin,$numbers)) || + ($i>=2 && $i<=3 && in_array($possible_origin,$numbers)) || + $i>3) { + # construct a possible IBAN using this possible origin for the + # mistranscribed character, replaced at this position only + $possible_iban = substr($incorrect_iban,0,$i) . $possible_origin . substr($incorrect_iban,$i+1); + # if the checksum passes, return it as a possibility + if(verify_iban($possible_iban)) { + array_push($suggestions,$possible_iban); + } + } + } + } + + # now we check for the type of mistransposition case where all of + # the characters of a certain type within a string were mistransposed. + # - first generate a character frequency table + $char_freqs = array(); + for($i=0;$i$freq) { + # if the character occurs more than once + if($freq>1) { + # check the 'all occurrences of were mistranscribed' case + foreach($_iban_mistranscriptions[$char] as $possible_origin) { + $possible_iban = str_replace($char,$possible_origin,$incorrect_iban); + if(verify_iban($possible_iban)) { + array_push($suggestions,$possible_iban); + } + } + } + } + + return $suggestions; +} + + +##### internal use functions - safe to ignore ###### + +# Load the IBAN registry from disk. +global $_iban_registry; +$_iban_registry = array(); +_iban_load_registry(); +function _iban_load_registry() { + global $_iban_registry; + # if the registry is not yet loaded, or has been corrupted, reload + if(!is_array($_iban_registry) || count($_iban_registry)<1) { + $data = file_get_contents(dirname(__FILE__) . '/registry.txt'); + $lines = explode("\n",$data); + array_shift($lines); # drop leading description line + # loop through lines + foreach($lines as $line) { + if($line!='') { + # split to fields + $old_display_errors_value = ini_get('display_errors'); + ini_set('display_errors',false); + $old_error_reporting_value = ini_get('error_reporting'); + ini_set('error_reporting',false); + list($country,$country_name,$domestic_example,$bban_example,$bban_format_swift,$bban_format_regex,$bban_length,$iban_example,$iban_format_swift,$iban_format_regex,$iban_length,$bban_bankid_start_offset,$bban_bankid_stop_offset,$bban_branchid_start_offset,$bban_branchid_stop_offset,$registry_edition,$country_sepa) = explode('|',$line); + ini_set('display_errors',$old_display_errors_value); + ini_set('error_reporting',$old_error_reporting_value); + # assign to registry + $_iban_registry[$country] = array( + 'country' => $country, + 'country_name' => $country_name, + 'country_sepa' => $country_sepa, + 'domestic_example' => $domestic_example, + 'bban_example' => $bban_example, + 'bban_format_swift' => $bban_format_swift, + 'bban_format_regex' => $bban_format_regex, + 'bban_length' => $bban_length, + 'iban_example' => $iban_example, + 'iban_format_swift' => $iban_format_swift, + 'iban_format_regex' => $iban_format_regex, + 'iban_length' => $iban_length, + 'bban_bankid_start_offset' => $bban_bankid_start_offset, + 'bban_bankid_stop_offset' => $bban_bankid_stop_offset, + 'bban_branchid_start_offset' => $bban_branchid_start_offset, + 'bban_branchid_stop_offset' => $bban_branchid_stop_offset, + 'registry_edition' => $registry_edition + ); + } + } + } +} + +# Get information from the IBAN registry by example IBAN / code combination +function _iban_get_info($iban,$code) { + $country = iban_get_country_part($iban); + return _iban_country_get_info($country,$code); +} + +# Get information from the IBAN registry by country / code combination +function _iban_country_get_info($country,$code) { + global $_iban_registry; + $country = strtoupper($country); + $code = strtolower($code); + if(array_key_exists($country,$_iban_registry)) { + if(array_key_exists($code,$_iban_registry[$country])) { + return $_iban_registry[$country][$code]; + } + } + return false; +} + +# Load common mistranscriptions from disk. +function _iban_load_mistranscriptions() { + global $_iban_mistranscriptions; + # do not reload if already present + if(is_array($_iban_mistranscriptions) && count($_iban_mistranscriptions) == 36) { return true; } + $_iban_mistranscriptions = array(); + $file = dirname(__FILE__) . '/mistranscriptions.txt'; + if(!file_exists($file) || !is_readable($file)) { return false; } + $data = file_get_contents($file); + $lines = explode("\n",$data); + foreach($lines as $line) { + # match lines with ' c- = ' where x is a word-like character + if(preg_match('/^ *c-(\w) = (.*?)$/',$line,$matches)) { + # normalize the character to upper case + $character = strtoupper($matches[1]); + # break the possible origins list at '/', strip quotes & spaces + $chars = explode(' ',str_replace('"','',preg_replace('/ *?\/ *?/','',$matches[2]))); + # assign as possible mistranscriptions for that character + $_iban_mistranscriptions[$character] = $chars; + } + } + return true; +} + +?> diff --git a/htdocs/includes/php-iban/registry.txt b/htdocs/includes/php-iban/registry.txt new file mode 100644 index 00000000000..ffe714139dd --- /dev/null +++ b/htdocs/includes/php-iban/registry.txt @@ -0,0 +1,81 @@ +country_code|country_name|domestic_example|bban_example|bban_format_swift|bban_format_regex|bban_length|iban_example|iban_format_swift|iban_format_regex|iban_length|bban_bankid_start_offset|bban_bankid_stop_offset|bban_branchid_start_offset|bban_branchid_stop_offset|registry_edition|country_sepa +AA|IIBAN (Internet)|0011123Z5678|0011123Z5678|12!a|^[A-Z0-9]{12}$|12|AA120011123Z5678|AA2!n12!a|^AA(\d{2})([A-Z0-9]{12})$|16|0|3|||N/A|0 +AL|Albania|0000000235698741|212110090000000235698741|8!n16!c|^(\d{8})([A-Za-z0-9]{16})$|24|AL47212110090000000235698741|AL2!n8!n16!c|^AL(\d{2})(\d{8})([A-Za-z0-9]{16})$|28|0|2|3|6|2011-06-20|0 +AD|Andorra|2030200359100100|00012030200359100100|4!n4!n12!c|^(\d{4})(\d{4})([A-Za-z0-9]{12})$|20|AD1200012030200359100100|AD2!n4!n4!n12!c|^AD(\d{2})(\d{4})(\d{4})([A-Za-z0-9]{12})$|24|0|3|4|7|2011-06-20|0 +AT|Austria|19043-234573201|1904300234573201|5!n11!n|^(\d{5})(\d{11})$|16|AT611904300234573201|AT2!n5!n11!n|^AT(\d{2})(\d{5})(\d{11})$|20|0|4|||2011-06-20|1 +AX|Aland Islands|123456-785|12345600000785|6!n7!n1!n|^(\d{6})(\d{7})(\d{1})$|14|AX2112345600000785|AX2!n6!n7!n1!n|^AX(\d{2})(\d{6})(\d{7})(\d{1})$|18|0|2|||2013-09-05|1 +AZ|Azerbaijan|NABZ00000000137010001944|NABZ00000000137010001944|4!a20!c|^([A-Z]{4})([A-Za-z0-9]{20})$|24|AZ21NABZ00000000137010001944|AZ2!n4!a20!c|^AZ(\d{2})([A-Z]{4})([A-Za-z0-9]{20})$|28|0|3|||2012-05-29|0 +BH|Bahrain|00001299123456|BMAG00001299123456|4!a14!c|^([A-Z]{4})([A-Za-z0-9]{14})$|22|BH67BMAG00001299123456|BH2!n4!a14!c|^BH(\d{2})([A-Z]{4})([A-Za-z0-9]{14})$|22|0|3|||2012-05-29|0 +BE|Belgium|539-0075470-34|539007547034|3!n7!n2!n|^(\d{3})(\d{7})(\d{2})$|12|BE68539007547034|BE2!n3!n7!n2!n|^BE(\d{2})(\d{3})(\d{7})(\d{2})$|16|0|2|||2011-06-20|1 +BA|Bosnia and Herzegovina|199-044-00012002-79|1990440001200279|3!n3!n8!n2!n|^(\d{3})(\d{3})(\d{8})(\d{2})$|16|BA391290079401028494|BA2!n3!n3!n8!n2!n|^BA(\d{2})(\d{3})(\d{3})(\d{8})(\d{2})$|20|0|2|3|5|2011-06-20|0 +BR|Brazil|0009795493C1|00360305000010009795493P1|8!n5!n10!n1!a1!c|^(\d{8})(\d{5})(\d{10})([A-Z]{1})([A-Za-z0-9]{1})$|25|BR2300360305000010009795493P1BR1800000000141455123924100C2|BR2!n8!n5!n10!n1!a1!c|^BR(\d{2})(\d{8})(\d{5})(\d{10})([A-Z]{1})([A-Za-z0-9]{1})$|29|0|7|8|12|2013-06-20|0 +BG|Bulgaria|BNBG 9661 1020 3456 78|BNBG96611020345678|4!a4!n2!n8!c|^([A-Z]{4})(\d{4})(\d{2})([A-Za-z0-9]{8})$|18|BG80BNBG96611020345678|BG2!n4!a4!n2!n8!c|^BG(\d{2})([A-Z]{4})(\d{4})(\d{2})([A-Za-z0-9]{8})$|22|0|3|4|7|2011-06-20|1 +CR|Costa Rica|1026284066|15202001026284066|3!n14!n|^(\d{3})(\d{14})$|7|CR91202001026284066|CR2!n3!n14!n|^CR(\d{2})(\d{3})(\d{14})$|21|0|2|||2012-05-29|0 +HR|Croatia|1001005-1863000160|10010051863000160|7!n10!n|^(\d{7})(\d{10})$|17|HR1210010051863000160|HR2!n7!n10!n|^HR(\d{2})(\d{7})(\d{10})$|21|0|6|||2011-06-20|1 +CY|Cyprus|1200527600|002001280000001200527600|3!n5!n16!c|^(\d{3})(\d{5})([A-Za-z0-9]{16})$|24|CY17002001280000001200527600|CY2!n3!n5!n16!c|^CY(\d{2})(\d{3})(\d{5})([A-Za-z0-9]{16})$|28|0|2|3|7|2011-06-20|1 +CZ|Czech Republic|19-2000145399/0800|08000000192000145399|4!n6!n10!n|^(\d{4})(\d{6})(\d{10})$|20|CZ6508000000192000145399|CZ2!n4!n6!n10!n|^CZ(\d{2})(\d{4})(\d{6})(\d{10})$|24|0|3|4|9|2011-06-20|1 +DK|Denmark|0040 0440116243, 6460 0001631634, 6471 0001000206|00400440116243, 64600001631634, 64710001000206|4!n9!n1!n|^(\d{4})(\d{9})(\d{1})$|14|DK5000400440116243|DK2!n4!n9!n1!n|^DK(\d{2})(\d{4})(\d{9})(\d{1})$|18|0|3|||2011-06-20|1 +FO|Faroe Islands|0040 0440116243, 6460 0001631634, 6471 0001000206|00400440116243, 64600001631634, 64710001000206|4!n9!n1!n|^(\d{4})(\d{9})(\d{1})$|14|FO2000400440116243|FO2!n4!n9!n1!n|^FO(\d{2})(\d{4})(\d{9})(\d{1})$|18|0|3|||2011-06-20|0 +GL|Greenland|0040 0440116243, 6460 0001631634, 6471 0001000206|00400440116243, 64600001631634, 64710001000206|4!n9!n1!n|^(\d{4})(\d{9})(\d{1})$|14|GL2000400440116243|GL2!n4!n9!n1!n|^GL(\d{2})(\d{4})(\d{9})(\d{1})$|18|0|3|||2011-06-20|0 +DO|Dominican Republic|1212453611324|AGR00000001212453611324|4!c20!n|^([A-Za-z0-9]{4})(\d{20})$|24|DO28BAGR00000001212453611324|DO2!n4!c20!n|^DO(\d{2})([A-Za-z0-9]{4})(\d{20})$|28|0|3|||2011-06-20|0 +EE|Estonia|221020145685|2200221020145685|2!n2!n11!n1!n|^(\d{2})(\d{2})(\d{11})(\d{1})$|16|EE382200221020145685|EE2!n2!n2!n11!n1!n|^EE(\d{2})(\d{2})(\d{2})(\d{11})(\d{1})$|20|0|1|||2011-06-20|1 +FI|Finland|123456-785|12345600000785|6!n7!n1!n|^(\d{6})(\d{7})(\d{1})$|14|FI2112345600000785|FI2!n6!n7!n1!n|^FI(\d{2})(\d{6})(\d{7})(\d{1})$|18|0|2|||2013-08-05|1 +FR|France|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|FR1420041010050500013M02606|FR2!n5!n5!n11!c2!n|^FR(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-08-28|1 +BL|Saint Barthelemy|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|BL9820041010050500013M02606|BL2!n5!n5!n11!c2!n|^BL(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-02-08|0 +GF|French Guyana|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|GF4120041010050500013M02606|GF2!n5!n5!n11!c2!n|^GF(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-08-28|1 +GP|Guadelope|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|GP1120041010050500013M02606|GP2!n5!n5!n11!c2!n|^GP(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-08-28|1 +MF|Saint Martin (French Part)|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|MF9820041010050500013M02606|MF2!n5!n5!n11!c2!n|^MF(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-02-08|0 +MQ|Martinique|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|MQ5120041010050500013M02606|MQ2!n5!n5!n11!c2!n|^MQ(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-08-28|1 +RE|Reunion|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|RE4220041010050500013M02606|RE2!n5!n5!n11!c2!n|^RE(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-08-28|1 +PF|French Polynesia|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|PF5720041010050500013M02606|PF2!n5!n5!n11!c2!n|^PF(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2011-06-20|0 +TF|French Southern Territories|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|TF2120041010050500013M02606|TF2!n5!n5!n11!c2!n|^TF(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2011-06-20|0 +YT|Mayotte|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|YT3120041010050500013M02606|YT2!n5!n5!n11!c2!n|^YT(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-08-28|1 +NC|New Caledonia|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|NC8420041010050500013M02606|NC2!n5!n5!n11!c2!n|^NC(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2011-06-20|0 +PM|Saint Pierre et Miquelon|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|PM3620041010050500013M02606|PM2!n5!n5!n11!c2!n|^PM(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-08-28|1 +WF|Wallis and Futuna Islands|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|WF9120041010050500013M02606|WF2!n5!n5!n11!c2!n|^WF(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2011-06-20|0 +GE|Georgia|0000000101904917|NB0000000101904917|2!a16!n|^([A-Z]{2})(\d{16})$|18|GE29NB0000000101904917|GE2!n2!a16!n|^GE(\d{2})([A-Z]{2})(\d{16})$|22|0|1|||2011-06-20|0 +DE|Germany|37040044-532013000|370400440532013000|8!n10!n|^(\d{8})(\d{10})$|18|DE89370400440532013000|DE2!n8!n10!n|^DE(\d{2})(\d{8})(\d{10})$|22|0|7|||2011-06-20|1 +GI|Gibraltar|0000 00007099 453|NWBK000000007099453|4!a15!c|^([A-Z]{4})([A-Za-z0-9]{15})$|19|GI75NWBK000000007099453|GI2!n4!a15!c|^GI(\d{2})([A-Z]{4})([A-Za-z0-9]{15})$|23|0|3|||2011-06-20|1 +GR|Greece|01250000000012300695|01101250000000012300695|3!n4!n16!c|^(\d{3})(\d{4})([A-Za-z0-9]{16})$|23|GR1601101250000000012300695|GR2!n3!n4!n16!c|^GR(\d{2})(\d{3})(\d{4})([A-Za-z0-9]{16})$|27|0|2|3|6|2011-06-20|1 +GT|Guatemala|01020000001210029690|TRAJ01020000001210029690|4!c20!c|^([A-Za-z0-9]{4})([A-Za-z0-9]{20})$|24|GT82TRAJ01020000001210029690|GT2!n4!c20!c|^GT(\d{2})([A-Za-z0-9]{4})([A-Za-z0-9]{20})$|28|0|3|||2012-05-29|0 +HU|Hungary|11773016-11111018-00000000|117730161111101800000000|3!n4!n1!n15!n1!n|^(\d{3})(\d{4})(\d{1})(\d{15})(\d{1})$|24|HU42117730161111101800000000|HU2!n3!n4!n1!n15!n1!n|^HU(\d{2})(\d{3})(\d{4})(\d{1})(\d{15})(\d{1})$|28|0|2|3|6|2011-06-20|1 +IS|Iceland|0159-26-007654-551073-0339|0159260076545510730339|4!n2!n6!n10!n|^(\d{4})(\d{2})(\d{6})(\d{10})$|22|IS140159260076545510730339|IS2!n4!n2!n6!n10!n|^IS(\d{2})(\d{4})(\d{2})(\d{6})(\d{10})$|26|0|3|6|11|2011-06-20|1 +IE|Ireland|93-11-52 12345678|AIBK93115212345678|4!a6!n8!n|^([A-Z]{4})(\d{6})(\d{8})$|18|IE29AIBK93115212345678|IE2!n4!a6!n8!n|^IE(\d{2})([A-Z]{4})(\d{6})(\d{8})$|22|0|3|4|9|2011-06-20|1 +IL|Israel|10-800-99999999|100800000099999000|3!n3!n13!n|^(\d{3})(\d{3})(\d{13})$|19|IL620108000000099999999|IL2!n3!n3!n13!n|^IL(\d{2})(\d{3})(\d{3})(\d{13})$|23|0|2|3|5|2011-06-20|0 +IT|Italy|X 05428 11101 000000123456|X0542811101000000123456|1!a5!n5!n12!c|^([A-Z]{1})(\d{5})(\d{5})([A-Za-z0-9]{12})$|23|IT60X0542811101000000123456|IT2!n1!a5!n5!n12!c|^IT(\d{2})([A-Z]{1})(\d{5})(\d{5})([A-Za-z0-9]{12})$|27|0|5|6|10|2011-06-20|1 +JO|Jordan|1310000302|CBJO0010000000000131000302|4!a4!n18!c|^([A-Z]{4})(\d{4})([A-Za-z0-9]{18})$|26|JO94CBJO0010000000000131000302|JO2!n4!a4!n18!c|^JO(\d{2})([A-Z]{4})(\d{4})([A-Za-z0-9]{18})$|30|0|3|4|7|2014-06-05|0 +KZ|Kazakhstan|KZ86 125K ZT50 0410 0100|125KZT5004100100|3!n13!c|^(\d{3})([A-Za-z0-9]{13})$|16|KZ07|KZ2!n3!n13!c|^KZ(\d{2})(\d{3})([A-Za-z0-9]{13})$||0|2|||2014-06-05|0 +KW|Kuwait|CBKU0000000000001234560101|CBKU0000000000001234560101|4!a22!c|^([A-Z]{4})([A-Za-z0-9]{22})$|26|KW81CBKU0000000000001234560101|KW2!n4!a22!n|^KW(\d{2})([A-Z]{4})(\d{22})$|30|0|3|||2011-06-20|0 +LV|Latvia|BANK 0000 4351 9500 1|BANK0000435195001|4!a13!c|^([A-Z]{4})([A-Za-z0-9]{13})$|17|LV80BANK0000435195001|LV2!n4!a13!c|^LV(\d{2})([A-Z]{4})([A-Za-z0-9]{13})$|21|0|3|||2011-06-20|1 +LB|Lebanon|01 001 901229114|0999 0000 0001 0019 0122 9114|4!n20!c|^(\d{4})([A-Za-z0-9]{20})$|24|LB62099900000001001901229114|LB2!n4!n20!c|^LB(\d{2})(\d{4})([A-Za-z0-9]{20})$|28|0|3|||2011-06-20|0 +LI|Liechtenstein|8810 2324013AA|088100002324013AA|5!n12!c|^(\d{5})([A-Za-z0-9]{12})$|19|LI21088100002324013AA|LI2!n5!n12!c|^LI(\d{2})(\d{5})([A-Za-z0-9]{12})$|21|0|4|||2012-05-29|1 +LT|Lithuania|1000 0111 0100 1000|10000011101001000|5!n11!n|^(\d{5})(\d{11})$|16|LT121000011101001000|LT2!n5!n11!n|^LT(\d{2})(\d{5})(\d{11})$|20|0|4|||2011-06-20|1 +LU|Luxembourg|0019 4006 4475 0000|0019400644750000|3!n13!c|^(\d{3})([A-Za-z0-9]{13})$|16|LU280019400644750000|LU2!n3!n13!c|^LU(\d{2})(\d{3})([A-Za-z0-9]{13})$|20|0|2|||2011-06-20|1 +MK|Macedonia|300 0000000424 25|250120000058984|3!n10!c2!n|^(\d{3})([A-Za-z0-9]{10})(\d{2})$|15|MK07250120000058984|MK2!n3!n10!c2!n|^MK(\d{2})(\d{3})([A-Za-z0-9]{10})(\d{2})$|19|0|2|||2012-05-29|0 +MT|Malta|12345MTLCAST001S|MALT011000012345MTLCAST001S|4!a5!n18!c|^([A-Z]{4})(\d{5})([A-Za-z0-9]{18})$|27|MT84MALT011000012345MTLCAST001S|MT2!n4!a5!n18!c|^MT(\d{2})([A-Z]{4})(\d{5})([A-Za-z0-9]{18})$|31|0|3|4|8|2011-06-20|1 +MR|Mauritania|00020 00101 00001234567 53|00020001010000123456753|5!n5!n11!n2!n|^(\d{5})(\d{5})(\d{11})(\d{2})$|23|MR1300020001010000123456753|MR135!n5!n11!n2!n|^MR13(\d{5})(\d{5})(\d{11})(\d{2})$|27|0|4|5|9|2011-06-20|0 +MU|Mauritius|BOMM 0101 1010 3030 0200 000M UR|BOMM0101101030300200000MUR|4!a2!n2!n12!n3!n3!a|^([A-Z]{4})(\d{2})(\d{2})(\d{12})(\d{3})([A-Z]{3})$|26|MU17BOMM0101101030300200000MUR|MU2!n4!a2!n2!n12!n3!n3!a|^MU(\d{2})([A-Z]{4})(\d{2})(\d{2})(\d{12})(\d{3})([A-Z]{3})$|30|0|5|6|7|2011-06-20|0 +MD|Moldova|00225100013104168|AG000225100013104168|2!c18!c|^([A-Za-z0-9]{2})([A-Za-z0-9]{18})$|20|MD24AG000225100013104168|MD2!n20!c|^MD(\d{2})([A-Za-z0-9]{20})$|24|0|1|||2012-09-09|0 +MC|Monaco|0011111000h|11222 00001 01234567890 30|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|MC5811222000010123456789030|MC2!n5!n5!n11!c2!n|^MC(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2011-06-20|1 +ME|Montenegro|505 0000123456789 51|505000012345678951|3!n13!n2!n|^(\d{3})(\d{13})(\d{2})$|18|ME25505000012345678951|ME2!n3!n13!n2!n|^ME(\d{2})(\d{3})(\d{13})(\d{2})$|22|0|2|||2011-06-20|0 +NL|The Netherlands|041 71 64 300|ABNA0417164300|4!a10!n|^([A-Z]{4})(\d{10})$|14|NL91ABNA0417164300|NL2!n4!a10!n|^NL(\d{2})([A-Z]{4})(\d{10})$|18|0|3|4|3|2013-06-20|1 +NO|Norway|8601 11 17947|86011117947|4!n6!n1!n|^(\d{4})(\d{6})(\d{1})$|11|NO9386011117947|NO2!n4!n6!n1!n|^NO(\d{2})(\d{4})(\d{6})(\d{1})$|15|0|3|||2011-06-20|1 +PK|Pakistan|00260101036360|SCBL0000001123456702|4!a16!c|^([A-Z]{4})([A-Za-z0-9]{16})$|20|PK36SCBL0000001123456702|PK2!n4!a16!c|^PK(\d{2})([A-Z]{4})([A-Za-z0-9]{16})$|24|0|3|||2012-05-29|0 +PL|Poland|61 1090 1014 0000 0712 1981 2874|109010140000071219812874|8!n16!n|^(\d{8})(\d{16})$|24|PL61109010140000071219812874|PL2!n8!n16n|^PL(\d{2})(\d{8})(\d{1,16})$|28|0|7|||2011-06-20|1 +PS|Palestine|400123456702|PALS000000000400123456702|4!a21!c|^([A-Z]{4})([A-Za-z0-9]{21})$|25|PS92PALS000000000400123456702|PS2!n4!a21!c|^PS(\d{2})([A-Z]{4})([A-Za-z0-9]{21})$|29|0|3|||2013-09-05|0 +PT|Portugal|0002.0123.12345678901.54|000201231234567890154|4!n4!n11!n2!n|^(\d{4})(\d{4})(\d{11})(\d{2})$|21|PT50000201231234567890154|PT2!n4!n4!n11!n2!n|^PT(\d{2})(\d{4})(\d{4})(\d{11})(\d{2})$|25|0|3|4|7|2013-09-05|1 +QA|Qatar|QA58DOHB00001234567890ABCDEFG|DOHB00001234567890ABCDEFG|4!a4!n17!c|^([A-Z]{4})(\d{4})([A-Za-z0-9]{17})$|29|QA58DOHB00001234567890ABCDEFG|QA2!n4!a4!n17!c|^QA(\d{2})([A-Z]{4})(\d{4})([A-Za-z0-9]{17})$|29|0|3|4|7|2014-06-05|0 +RO|Romania|AAAA 1B31 0075 9384 0000|AAAA1B31007593840000|4!a16!c|^([A-Z]{4})([A-Za-z0-9]{16})$|20|RO49AAAA1B31007593840000|RO2!n4!a16!c|^RO(\d{2})([A-Z]{4})([A-Za-z0-9]{16})$|24|0|3|||2011-06-20|1 +SM|San Marino|U032 2509 8000 0000 0270 100|U0322509800000000270100|1!a5!n5!n12!c|^([A-Z]{1})(\d{5})(\d{5})([A-Za-z0-9]{12})$|23|SM86U0322509800000000270100|SM2!n1!a5!n5!n12!c|^SM(\d{2})([A-Z]{1})(\d{5})(\d{5})([A-Za-z0-9]{12})$|27|0|5|6|10|2011-06-20|1 +SA|Saudi Arabia|608010167519|80000000608010167519|2!n18!c|^(\d{2})([A-Za-z0-9]{18})$|20|SA0380000000608010167519|SA2!n2!n18!c|^SA(\d{2})(\d{2})([A-Za-z0-9]{18})$|24|0|1|||2012-05-29|0 +RS|Serbia|260-0056010016113-79|260005601001611379|3!n13!n2!n|^(\d{3})(\d{13})(\d{2})$|18|RS35260005601001611379|RS2!n3!n13!n2!n|^RS(\d{2})(\d{3})(\d{13})(\d{2})$|22|0|2|||2011-06-20|0 +SK|Slovak Republic|19-8742637541/1200|12000000198742637541|4!n6!n10!n|^(\d{4})(\d{6})(\d{10})$|20|SK3112000000198742637541|SK2!n4!n6!n10!n|^SK(\d{2})(\d{4})(\d{6})(\d{10})$|24|0|3|4|9|2011-06-20|1 +SI|Slovenia|2633 0001 2039 086|263300012039086|5!n8!n2!n|^(\d{5})(\d{8})(\d{2})$|15|SI56191000000123438|SI2!n5!n8!n2!n|^SI(\d{2})(\d{5})(\d{8})(\d{2})$|19|0|1|2|4|2012-09-09|1 +ES|Spain|2100 0418 45 0200051332|21000418450200051332|4!n4!n1!n1!n10!n|^(\d{4})(\d{4})(\d{1})(\d{1})(\d{10})$|20|ES9121000418450200051332|ES2!n4!n4!n1!n1!n10!n|^ES(\d{2})(\d{4})(\d{4})(\d{1})(\d{1})(\d{10})$|24|0|3|4|7|2013-09-05|1 +SE|Sweden|1234 12 3456 1|5000 0000 0583 9825 7466|3!n16!n1!n|^(\d{3})(\d{16})(\d{1})$|20|SE4550000000058398257466|SE2!n3!n16!n1!n|^SE(\d{2})(\d{3})(\d{16})(\d{1})$|24|0|2|||2011-06-20|1 +CH|Switzerland|762 1162-3852.957|00762011623852957|5!n12!c|^(\d{5})([A-Za-z0-9]{12})$|17|CH9300762011623852957|CH2!n5!n12!c|^CH(\d{2})(\d{5})([A-Za-z0-9]{12})$|21|0|4|||2011-06-20|1 +TN|Tunisia|10 006 0351835984788 31|10006035183598478831|2!n3!n13!n2!n|^(\d{2})(\d{3})(\d{13})(\d{2})$|20|TN5910006035183598478831|TN592!n3!n13!n2!n|^TN59(\d{2})(\d{3})(\d{13})(\d{2})$|24|0|1|2|4|2011-06-20|0 +TR|Turkey|0061 01299 1234567890123456789|0006100519786457841326|5!n1!c16!c|^(\d{5})([A-Za-z0-9]{1})([A-Za-z0-9]{16})$|22|TR330006100519786457841326|TR2!n5!n1!c16!c|^TR(\d{2})(\d{5})([A-Za-z0-9]{1})([A-Za-z0-9]{16})$|26|0|4|||2011-06-20|0 +AE|United Arab Emirates|1234567890123456|0331234567890123456|3!n16!n|^(\d{3})(\d{16})$|19|AE070331234567890123456|AE2!n3!n16!n|^AE(\d{2})(\d{3})(\d{16})$|23|0|2|||2011-06-20|0 +GB|United Kingdom|60-16-13 31926819|NWBK60161331926819|4!a6!n8!n|^([A-Z]{4})(\d{6})(\d{8})$|18|GB29NWBK60161331926819|GB2!n4!a6!n8!n|^GB(\d{2})([A-Z]{4})(\d{6})(\d{8})$|22|0|3|4|9|2011-06-20|1 +VG|British Virgin Islands|00000 12 345 678 901|VPVG0000012345678901|4!a16!n|^([A-Z]{4})(\d{16})$|20|VG96VPVG0000012345678901|VG2!n4!a16!n|^VG(\d{2})([A-Z]{4})(\d{16})$|24|0|3|||2012-05-29|0 From 685b8d722da219fff1e4f913acf2c3fac6d21dd8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 17 Feb 2015 16:46:37 +0100 Subject: [PATCH 147/173] Fix: Bad hook name --- htdocs/core/modules/supplier_order/pdf/pdf_muscadet.modules.php | 2 +- htdocs/langs/en_US/admin.lang | 2 +- htdocs/langs/fr_FR/admin.lang | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/modules/supplier_order/pdf/pdf_muscadet.modules.php b/htdocs/core/modules/supplier_order/pdf/pdf_muscadet.modules.php index 29bd483b39b..ddd10e56457 100644 --- a/htdocs/core/modules/supplier_order/pdf/pdf_muscadet.modules.php +++ b/htdocs/core/modules/supplier_order/pdf/pdf_muscadet.modules.php @@ -200,7 +200,7 @@ class pdf_muscadet extends ModelePDFSuppliersOrders $hookmanager->initHooks(array('pdfgeneration')); $parameters=array('file'=>$file,'object'=>$object,'outputlangs'=>$outputlangs); global $action; - $reshook=$hookmanager->executeHooks('afterPDFCreation',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks + $reshook=$hookmanager->executeHooks('beforePDFCreation',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks $nblignes = count($object->lines); diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 6f9449f209d..1d2085dcbf7 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -624,7 +624,7 @@ Permission181=Read supplier orders Permission182=Create/modify supplier orders Permission183=Validate supplier orders Permission184=Approve supplier orders -Permission185=Order supplier orders +Permission185=Order or cancel supplier orders Permission186=Receive supplier orders Permission187=Close supplier orders Permission188=Cancel supplier orders diff --git a/htdocs/langs/fr_FR/admin.lang b/htdocs/langs/fr_FR/admin.lang index 355878e9901..4475fe60771 100644 --- a/htdocs/langs/fr_FR/admin.lang +++ b/htdocs/langs/fr_FR/admin.lang @@ -631,7 +631,7 @@ Permission181=Consulter les commandes fournisseurs Permission182=Créer/modifier les commandes fournisseurs Permission183=Valider les commandes fournisseurs Permission184=Approuver les commandes fournisseurs -Permission185=Passer les commandes fournisseurs +Permission185=Passer les commandes fournisseurs et les annuler Permission186=Accuser réception des commandes fournisseurs Permission187=Clôturer les commandes fournisseurs Permission188=Annuler les commandes fournisseurs From f652cf4e97b0aec7c5a9c7b6cd33dcec75783aa4 Mon Sep 17 00:00:00 2001 From: frederic34 Date: Tue, 17 Feb 2015 17:02:38 +0100 Subject: [PATCH 148/173] Add translation for IBAN Valid or not --- htdocs/compta/bank/bankid_fr.php | 10 +++++++++- htdocs/langs/en_US/banks.lang | 2 ++ htdocs/societe/rib.php | 4 ++-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/htdocs/compta/bank/bankid_fr.php b/htdocs/compta/bank/bankid_fr.php index 03f0babe75d..1b3d5b89d0d 100644 --- a/htdocs/compta/bank/bankid_fr.php +++ b/htdocs/compta/bank/bankid_fr.php @@ -245,7 +245,15 @@ if (($_GET["id"] || $_GET["ref"]) && $action != 'edit') if ($account->getCountryCode() == 'IN') $bickey="SWIFT"; print '

'; - print ''; + print ''; print ''; print ''; diff --git a/htdocs/langs/en_US/banks.lang b/htdocs/langs/en_US/banks.lang index 10a5f5b3c14..7358f25e6f4 100644 --- a/htdocs/langs/en_US/banks.lang +++ b/htdocs/langs/en_US/banks.lang @@ -33,6 +33,8 @@ AllTime=From start Reconciliation=Reconciliation RIB=Bank Account Number IBAN=IBAN number +IbanValid=Valid IBAN +IbanNotValid=Not Valid IBAN BIC=BIC/SWIFT number StandingOrders=Standing orders StandingOrder=Standing order diff --git a/htdocs/societe/rib.php b/htdocs/societe/rib.php index a615577a8c4..ad3eea735fb 100644 --- a/htdocs/societe/rib.php +++ b/htdocs/societe/rib.php @@ -296,9 +296,9 @@ if ($socid && $action != 'edit' && $action != "create") print ''; From ad67fe50a3c7ae642c4d8f17161fe659aafc3b33 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 17 Feb 2015 17:21:41 +0100 Subject: [PATCH 149/173] Correct management when delivery date is universal time format. --- .../supplier_order/pdf/pdf_muscadet.modules.php | 4 +++- htdocs/fourn/class/fournisseur.commande.class.php | 6 +++--- htdocs/fourn/commande/card.php | 10 +++++++--- htdocs/install/mysql/migration/3.6.0-3.7.0.sql | 2 ++ .../install/mysql/tables/llx_commande_fournisseur.sql | 4 ++-- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/htdocs/core/modules/supplier_order/pdf/pdf_muscadet.modules.php b/htdocs/core/modules/supplier_order/pdf/pdf_muscadet.modules.php index ddd10e56457..e628013cb3e 100644 --- a/htdocs/core/modules/supplier_order/pdf/pdf_muscadet.modules.php +++ b/htdocs/core/modules/supplier_order/pdf/pdf_muscadet.modules.php @@ -1011,7 +1011,9 @@ class pdf_muscadet extends ModelePDFSuppliersOrders } $pdf->SetTextColor(0,0,60); - if (! empty($object->date_livraison)) $pdf->MultiCell(190, 3, $outputlangs->transnoentities("DateDeliveryPlanned")." : " . dol_print_date($object->date_livraison,"day",false,$outputlangs,true), '', 'R'); + $usehourmin='day'; + if ( empty($conf->global->SUPPLIER_ORDER_USE_HOUR_FOR_DELIVERY_DATE)) $usehourmin='dayhour'; + if (! empty($object->date_livraison)) $pdf->MultiCell(190, 3, $outputlangs->transnoentities("DateDeliveryPlanned")." : " . dol_print_date($object->date_livraison,$usehourmin,false,$outputlangs,true), '', 'R'); $posy+=5; $pdf->SetTextColor(0,0,60); diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index d95816a1511..6ba464b0a18 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -1609,9 +1609,9 @@ class CommandeFournisseur extends CommonOrder /** * Set the planned delivery date * - * @param User $user Objet utilisateur qui modifie - * @param timestamp $date_livraison Date de livraison - * @return int <0 si ko, >0 si ok + * @param User $user Objet user making change + * @param timestamp $date_livraison Planned delivery date + * @return int <0 if KO, >0 if OK */ function set_date_livraison($user, $date_livraison) { diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index 022b46f6a9b..ef78a9981c1 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -144,7 +144,7 @@ if ($action == 'setbankaccount' && $user->rights->fournisseur->commande->creer) // date de livraison if ($action == 'setdate_livraison' && $user->rights->fournisseur->commande->creer) { - $datelivraison=dol_mktime(0, 0, 0, GETPOST('liv_month','int'), GETPOST('liv_day','int'),GETPOST('liv_year','int')); + $datelivraison=dol_mktime(GETPOST('liv_hour','int'), GETPOST('liv_min','int'), GETPOST('liv_sec','int'), GETPOST('liv_month','int'), GETPOST('liv_day','int'),GETPOST('liv_year','int')); $result=$object->set_date_livraison($user,$datelivraison); if ($result < 0) @@ -1588,13 +1588,17 @@ elseif (! empty($object->id)) print ''; print ''; print ''; - $form->select_date($object->date_livraison?$object->date_livraison:-1,'liv_','','','',"setdate_livraison"); + $usehourmin=0; + if (! empty($conf->global->SUPPLIER_ORDER_USE_HOUR_FOR_DELIVERY_DATE)) $usehourmin=1; + $form->select_date($object->date_livraison?$object->date_livraison:-1,'liv_',$usehourmin,$usehourmin,'',"setdate_livraison"); print ''; print ''; } else { - print $object->date_livraison ? dol_print_date($object->date_livraison,'daytext') : ' '; + $usehourmin='day'; + if (! empty($conf->global->SUPPLIER_ORDER_USE_HOUR_FOR_DELIVERY_DATE)) $usehourmin='dayhour'; + print $object->date_livraison ? dol_print_date($object->date_livraison, $usehourmin) : ' '; } print ''; diff --git a/htdocs/install/mysql/migration/3.6.0-3.7.0.sql b/htdocs/install/mysql/migration/3.6.0-3.7.0.sql index 22a65167e6f..0a9213a3d73 100755 --- a/htdocs/install/mysql/migration/3.6.0-3.7.0.sql +++ b/htdocs/install/mysql/migration/3.6.0-3.7.0.sql @@ -210,6 +210,8 @@ ALTER TABLE llx_product_price ADD INDEX idx_product_price_fk_product (fk_produc DELETE from llx_product_price where fk_product NOT IN (SELECT rowid from llx_product); ALTER TABLE llx_product_price ADD CONSTRAINT fk_product_price_product FOREIGN KEY (fk_product) REFERENCES llx_product (rowid); +ALTER TABLE llx_commande_fournisseur MODIFY COLUMN date_livraison datetime; + ALTER TABLE llx_commande_fournisseur ADD COLUMN fk_account integer AFTER date_livraison; ALTER TABLE llx_facture_fourn ADD COLUMN fk_account integer AFTER fk_projet; diff --git a/htdocs/install/mysql/tables/llx_commande_fournisseur.sql b/htdocs/install/mysql/tables/llx_commande_fournisseur.sql index ff87110c72a..f9f440d0db4 100644 --- a/htdocs/install/mysql/tables/llx_commande_fournisseur.sql +++ b/htdocs/install/mysql/tables/llx_commande_fournisseur.sql @@ -55,11 +55,11 @@ create table llx_commande_fournisseur note_public text, model_pdf varchar(255), - date_livraison date default NULL, + date_livraison datetime default NULL, fk_account integer, -- bank account fk_cond_reglement integer, -- condition de reglement fk_mode_reglement integer, -- mode de reglement - fk_input_method integer default 0, + fk_input_method integer default 0, import_key varchar(14), extraparams varchar(255) -- for stock other parameters with json format From 1e1543403b7277da9bb4ee7d89d6cac366da6678 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 17 Feb 2015 19:49:17 +0100 Subject: [PATCH 150/173] New: Add option SUPPLIER_ORDER_AUTOADD_USER_CONTACT to automatically set user approving as contact following supplier order. --- htdocs/commande/card.php | 83 +++++++++++-------- htdocs/core/class/commonobject.class.php | 4 +- .../class/fournisseur.commande.class.php | 15 +++- htdocs/fourn/commande/card.php | 14 ++-- 4 files changed, 72 insertions(+), 44 deletions(-) diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 918244528cc..bda67f809fa 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -137,8 +137,10 @@ if (empty($reshook)) } // Reopen a closed order - else if ($action == 'reopen' && $user->rights->commande->creer) { - if ($object->statut == 3) { + else if ($action == 'reopen' && $user->rights->commande->creer) + { + if ($object->statut == 3) + { $result = $object->set_reopen($user); if ($result > 0) { @@ -153,21 +155,26 @@ if (empty($reshook)) } // Suppression de la commande - else if ($action == 'confirm_delete' && $confirm == 'yes' && $user->rights->commande->supprimer) { + else if ($action == 'confirm_delete' && $confirm == 'yes' && $user->rights->commande->supprimer) + { $result = $object->delete($user); - if ($result > 0) { + if ($result > 0) + { header('Location: index.php'); exit; } - else { + else + { setEventMessage($object->error, 'errors'); } } // Remove a product line - else if ($action == 'confirm_deleteline' && $confirm == 'yes' && $user->rights->commande->creer) { + else if ($action == 'confirm_deleteline' && $confirm == 'yes' && $user->rights->commande->creer) + { $result = $object->deleteline($lineid); - if ($result > 0) { + if ($result > 0) + { // Define output language $outputlangs = $langs; $newlang = ''; @@ -194,12 +201,14 @@ if (empty($reshook)) } // Categorisation dans projet - else if ($action == 'classin' && $user->rights->commande->creer) { + else if ($action == 'classin' && $user->rights->commande->creer) + { $object->setProject(GETPOST('projectid')); } // Add order - else if ($action == 'add' && $user->rights->commande->creer) { + else if ($action == 'add' && $user->rights->commande->creer) + { $datecommande = dol_mktime(12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear')); $datelivraison = dol_mktime(12, 0, 0, GETPOST('liv_month'), GETPOST('liv_day'), GETPOST('liv_year')); @@ -239,7 +248,8 @@ if (empty($reshook)) $object->contactid = GETPOST('contactid'); // If creation from another object of another module (Example: origin=propal, originid=1) - if (! empty($origin) && ! empty($originid)) { + if (! empty($origin) && ! empty($originid)) + { // Parse element/subelement (ex: project_task) $element = $subelement = $origin; if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) { @@ -301,37 +311,37 @@ if (empty($reshook)) for($i = 0; $i < $num; $i ++) { - $label = (! empty($lines [$i]->label) ? $lines [$i]->label : ''); - $desc = (! empty($lines [$i]->desc) ? $lines [$i]->desc : $lines [$i]->libelle); - $product_type = (! empty($lines [$i]->product_type) ? $lines [$i]->product_type : 0); + $label = (! empty($lines[$i]->label) ? $lines[$i]->label : ''); + $desc = (! empty($lines[$i]->desc) ? $lines[$i]->desc : $lines[$i]->libelle); + $product_type = (! empty($lines[$i]->product_type) ? $lines[$i]->product_type : 0); // Dates // TODO mutualiser - $date_start = $lines [$i]->date_debut_prevue; - if ($lines [$i]->date_debut_reel) - $date_start = $lines [$i]->date_debut_reel; - if ($lines [$i]->date_start) - $date_start = $lines [$i]->date_start; - $date_end = $lines [$i]->date_fin_prevue; - if ($lines [$i]->date_fin_reel) - $date_end = $lines [$i]->date_fin_reel; - if ($lines [$i]->date_end) - $date_end = $lines [$i]->date_end; + $date_start = $lines[$i]->date_debut_prevue; + if ($lines[$i]->date_debut_reel) + $date_start = $lines[$i]->date_debut_reel; + if ($lines[$i]->date_start) + $date_start = $lines[$i]->date_start; + $date_end = $lines[$i]->date_fin_prevue; + if ($lines[$i]->date_fin_reel) + $date_end = $lines[$i]->date_fin_reel; + if ($lines[$i]->date_end) + $date_end = $lines[$i]->date_end; // Reset fk_parent_line for no child products and special product - if (($lines [$i]->product_type != 9 && empty($lines [$i]->fk_parent_line)) || $lines [$i]->product_type == 9) { + if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9) { $fk_parent_line = 0; } // Extrafields - if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && method_exists($lines [$i], 'fetch_optionals')) // For avoid conflicts if + if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && method_exists($lines[$i], 'fetch_optionals')) // For avoid conflicts if // trigger used { - $lines [$i]->fetch_optionals($lines [$i]->rowid); - $array_option = $lines [$i]->array_options; + $lines[$i]->fetch_optionals($lines[$i]->rowid); + $array_option = $lines[$i]->array_options; } - $result = $object->addline($desc, $lines [$i]->subprice, $lines [$i]->qty, $lines [$i]->tva_tx, $lines [$i]->localtax1_tx, $lines [$i]->localtax2_tx, $lines [$i]->fk_product, $lines [$i]->remise_percent, $lines [$i]->info_bits, $lines [$i]->fk_remise_except, 'HT', 0, $date_start, $date_end, $product_type, $lines [$i]->rang, $lines [$i]->special_code, $fk_parent_line, $lines [$i]->fk_fournprice, $lines [$i]->pa_ht, $label, $array_option); + $result = $object->addline($desc, $lines[$i]->subprice, $lines[$i]->qty, $lines[$i]->tva_tx, $lines[$i]->localtax1_tx, $lines[$i]->localtax2_tx, $lines[$i]->fk_product, $lines[$i]->remise_percent, $lines[$i]->info_bits, $lines[$i]->fk_remise_except, 'HT', 0, $date_start, $date_end, $product_type, $lines[$i]->rang, $lines[$i]->special_code, $fk_parent_line, $lines[$i]->fk_fournprice, $lines[$i]->pa_ht, $label, $array_option); if ($result < 0) { $error ++; @@ -339,7 +349,7 @@ if (empty($reshook)) } // Defined the new fk_parent_line - if ($result > 0 && $lines [$i]->product_type == 9) { + if ($result > 0 && $lines[$i]->product_type == 9) { $fk_parent_line = $result; } } @@ -385,8 +395,10 @@ if (empty($reshook)) } // Insert default contacts if defined - if ($object_id > 0) { - if (GETPOST('contactid')) { + if ($object_id > 0) + { + if (GETPOST('contactid')) + { $result = $object->add_contact(GETPOST('contactid'), 'CUSTOMER', 'external'); if ($result < 0) { setEventMessage($langs->trans("ErrorFailedToAddContact"), 'errors'); @@ -399,7 +411,8 @@ if (empty($reshook)) } // End of object creation, we show it - if ($object_id > 0 && ! $error) { + if ($object_id > 0 && ! $error) + { $db->commit(); header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object_id); exit(); @@ -1594,7 +1607,8 @@ if ($action == 'create' && $user->rights->commande->creer) /* * Confirmation de la validation */ - if ($action == 'validate') { + if ($action == 'validate') + { // on verifie si l'objet est en numerotation provisoire $ref = substr($object->ref, 1, 4); if ($ref == 'PROV') { @@ -1604,7 +1618,8 @@ if ($action == 'create' && $user->rights->commande->creer) } $text = $langs->trans('ConfirmValidateOrder', $numref); - if (! empty($conf->notification->enabled)) { + if (! empty($conf->notification->enabled)) + { require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php'; $notify = new Notify($db); $text .= '
'; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index aed2aa3b224..b886a382b1e 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -175,8 +175,8 @@ abstract class CommonObject /** * Add a link between element $this->element and a contact * - * @param int $fk_socpeople Id of contact to link - * @param int $type_contact Type of contact (code or id). For example: SALESREPFOLL + * @param int $fk_socpeople Id of thirdparty contact (if source = 'external') or id of user (if souce = 'internal') to link + * @param int $type_contact Type of contact (code or id). Must be if or code found into table llx_c_type_contact. For example: SALESREPFOLL * @param int $source external=Contact extern (llx_socpeople), internal=Contact intern (llx_user) * @param int $notrigger Disable all triggers * @return int <0 if KO, >0 if OK diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 64131be840b..2914ca95620 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -613,7 +613,7 @@ class CommandeFournisseur extends CommonOrder } /** - * Accept an order + * Approve a supplier order * * @param User $user Object user * @param int $idwarehouse Id of warhouse for stock change @@ -659,6 +659,15 @@ class CommandeFournisseur extends CommonOrder { $this->log($user, 2, time()); // Statut 2 + if (! empty($conf->global->SUPPLIER_ORDER_AUTOADD_USER_CONTACT)) + { + $result=$this->add_contact($user->id, 'SALESREPFOLL', 'internal', 1); + if ($result < 0) + { + $error++; + } + } + // If stock is incremented on validate order, we must increment it if (! $error && ! empty($conf->stock->enabled) && ! empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER)) { @@ -967,8 +976,8 @@ class CommandeFournisseur extends CommonOrder dol_syslog(get_class($this)."::create", LOG_DEBUG); if ($this->db->query($sql)) { - // On logue creation pour historique - $this->log($user, 0, time()); + // Add entry into log + $this->log($user, 0, $now); if (! $error) { diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index ed276d7b328..f449c7f1098 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -1,6 +1,6 @@ - * Copyright (C) 2004-2013 Laurent Destailleur + * Copyright (C) 2004-2015 Laurent Destailleur * Copyright (C) 2005 Eric Seigne * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2010-2014 Juanjo Menent @@ -1601,13 +1601,13 @@ elseif (! empty($object->id)) } print ''; - + // Delai livraison jours print '
'; print ''; print ''; print ''; - + // Project if (! empty($conf->projet->enabled)) { @@ -2232,8 +2232,12 @@ elseif (! empty($object->id)) if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->fournisseur->commande->creer)) || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->fournisseur->supplier_order_advance->validate))) { - print ''.$langs->trans('Validate').''; + $tmpbuttonlabel=$langs->trans('Validate'); + if ($user->rights->fournisseur->commande->approuver) $tmpbuttonlabel = $langs->trans("ValidateAndApprove"); + + print ''; + print $tmpbuttonlabel; + print ''; } } From 4bbbff8d69cdab251c1e1770d0ee59c76c1aa76d Mon Sep 17 00:00:00 2001 From: frederic34 Date: Tue, 17 Feb 2015 17:37:32 +0100 Subject: [PATCH 151/173] Add BIC/SWIFT Validation --- htdocs/compta/bank/bankid_fr.php | 10 +++++++++- htdocs/core/lib/bank.lib.php | 23 ++++++++++++++++++----- htdocs/langs/en_US/banks.lang | 6 ++++-- htdocs/societe/rib.php | 10 +++++++++- 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/htdocs/compta/bank/bankid_fr.php b/htdocs/compta/bank/bankid_fr.php index 1b3d5b89d0d..f20d70ef14f 100644 --- a/htdocs/compta/bank/bankid_fr.php +++ b/htdocs/compta/bank/bankid_fr.php @@ -256,7 +256,15 @@ if (($_GET["id"] || $_GET["ref"]) && $action != 'edit') print ''; print ''; - print ''; + print ''; print ''; print ''; - print ''; + print ''; print ''; } // Ajout des boutons de modification/suppression - if ($object->fk_c_expensereport_statuts<2 OR $object->fk_c_expensereport_statuts==99) + if ($object->fk_c_expensereport_statuts < 2 || $object->fk_c_expensereport_statuts==99) { print ''; } @@ -1370,25 +1355,34 @@ else $piece_comptable = $i + 1; $objp = $db->fetch_object($resql); $var=!$var; - if ($action != 'editline') + if ($action != 'editline' || $objp->rowid != GETPOST('rowid')) { print ''; - print ''; + if ($action != 'editline') + { + print ''; + } print ''; print ''; print ''; print ''; - print ''; + print ''; print ''; print ''; - print ''; - print ''; + if ($action != 'editline') + { + print ''; + print ''; + } // Ajout des boutons de modification/suppression if($object->fk_c_expensereport_statuts<2 OR $object->fk_c_expensereport_statuts==99) @@ -1404,45 +1398,44 @@ else } print ''; } - else + + if ($action == 'editline' && $objp->rowid == GETPOST('rowid')) { - if($objp->rowid==$_GET['rowid']) - { //modif ligne!!!!! print ''; // Sélection date - print ''; - // Sélection projet - print ''; - // Sélection type - print ''; // Add comments - print ''; // Sélection TVA - print ''; // Prix unitaire - print ''; // Quantité - print ''; print ''; - } } $i++; @@ -1503,7 +1495,7 @@ else // Sélection projet print ''; // Sélection type @@ -1528,7 +1520,7 @@ else // Prix unitaire print ''; // Quantité @@ -1593,7 +1585,7 @@ if ($action != 'create' && $action != 'edit') // Validate if (count($object->lines) > 0 || count($object->lignes) > 0) { - print ''.$langs->trans('Validate').''; + print ''.$langs->trans('ValidateAndSubmit').''; } if ($user->rights->expensereport->supprimer) @@ -1611,7 +1603,7 @@ if ($action != 'create' && $action != 'edit') */ if($user->rights->expensereport->creer && $object->fk_c_expensereport_statuts==99) { - if ($object->fk_user_author == $user->id) + if ($user->id == $object->fk_user_author || $user->id == $object->fk_user_valid) { // Modifier print ''.$langs->trans('ModifyInfoGen').''; @@ -1619,7 +1611,7 @@ if ($action != 'create' && $action != 'edit') // Brouillonner (le statut refusée est identique à brouillon) //print ''.$langs->trans('BROUILLONNER').''; // Enregistrer depuis le statut "Refusée" - print ''.$langs->trans('Validate').''; + print ''.$langs->trans('ValidateAndSubmit').''; if ($user->rights->expensereport->supprimer) { @@ -1631,10 +1623,10 @@ if ($action != 'create' && $action != 'edit') if ($user->rights->expensereport->to_paid && $object->fk_c_expensereport_statuts==5) { - if ($object->fk_user_author == $user->id || $object->fk_user_valid == $user->id) + if ($user->id == $object->fk_user_author || $user->id == $object->fk_user_valid) { // Brouillonner - print ''.$langs->trans('BROUILLONNER').''; + print ''.$langs->trans('SetToDraft').''; } } @@ -1648,7 +1640,7 @@ if ($action != 'create' && $action != 'edit') if ($object->fk_user_author == $user->id) { // Brouillonner - print ''.$langs->trans('BROUILLONNER').''; + print ''.$langs->trans('SetToDraft').''; } } @@ -1659,12 +1651,12 @@ if ($action != 'create' && $action != 'edit') // Valider print ''.$langs->trans('Approve').''; // Refuser - print ''.$langs->trans('Refuse').''; + print ''.$langs->trans('Deny').''; //} - if ($object->fk_user_author==$user->id) + if ($user->id == $object->fk_user_author || $user->id == $object->fk_user_valid) { - // Annuler + // Cancel print ''.$langs->trans('Cancel').''; } @@ -1679,14 +1671,17 @@ if ($action != 'create' && $action != 'edit') * ET user à droit de "to_paid" * Afficher : "Annuler" / "Payer" / "Supprimer" */ - if ($user->rights->expensereport->to_paid && $object->fk_c_expensereport_statuts==5) + if ($user->rights->expensereport->to_paid && $object->fk_c_expensereport_statuts == 5) { // Payer print ''.$langs->trans('TO_PAID').''; - // Annuler - print ''.$langs->trans('CANCEL').''; - + // Cancel + if ($user->id == $object->fk_user_author || $user->id == $object->fk_user_valid) + { + print ''.$langs->trans('Cancel').''; + } + if($user->rights->expensereport->supprimer) { // Supprimer @@ -1717,10 +1712,10 @@ if ($action != 'create' && $action != 'edit') if ($user->rights->expensereport->supprimer && $object->fk_c_expensereport_statuts==4) { - if ($object->fk_user_validator==$user->id) + if ($user->id == $object->fk_user_author || $user->id == $object->fk_user_valid) { // Brouillonner - print ''.$langs->trans('BROUILLONNER').''; + print ''.$langs->trans('ReOpen').''; } // Supprimer @@ -1732,7 +1727,7 @@ if ($action != 'create' && $action != 'edit') print ''; -$conf->global->DOL_URL_ROOT_DOCUMENT_PHP=dol_buildpath('/expensereport/documentwrapper.php',1); +//$conf->global->DOL_URL_ROOT_DOCUMENT_PHP=dol_buildpath('/expensereport/documentwrapper.php',1); print '
'; diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php index 84db5bd9ece..76534e94c2a 100755 --- a/htdocs/expensereport/class/expensereport.class.php +++ b/htdocs/expensereport/class/expensereport.class.php @@ -39,40 +39,40 @@ class ExpenseReport extends CommonObject ACTIONS */ - // Enregistrement - var $date_create; - var $fk_user_author; + // Enregistrement + var $date_create; + var $fk_user_author; - // Refus - var $date_refuse; - var $detail_refuse; - var $fk_user_refuse; + // Refus + var $date_refuse; + var $detail_refuse; + var $fk_user_refuse; - // Annulation - var $date_cancel; - var $detail_cancel; - var $fk_user_cancel; + // Annulation + var $date_cancel; + var $detail_cancel; + var $fk_user_cancel; - // Validation - var $date_valide; - var $fk_user_valid; - var $user_valid_infos; + // Validation + var $date_valide; + var $fk_user_valid; + var $user_valid_infos; - // Paiement - var $date_paiement; - var $fk_user_paid; - var $user_paid_infos; + // Paiement + var $date_paiement; + var $fk_user_paid; + var $user_paid_infos; /* END ACTIONS */ - /** - * Constructor - * - * @param DoliDB $db Handler acces base de donnees - */ + /** + * Constructor + * + * @param DoliDB $db Handler acces base de donnees + */ function __construct($db) { $this->db = $db; @@ -242,13 +242,13 @@ class ExpenseReport extends CommonObject } } - /** - * Load an object from database - * - * @param int $id Id - * @param string $ref Ref - * @return int <0 if KO, >0 if OK - */ + /** + * Load an object from database + * + * @param int $id Id + * @param string $ref Ref + * @return int <0 if KO, >0 if OK + */ function fetch($id, $ref='') { global $conf,$db; @@ -467,94 +467,94 @@ class ExpenseReport extends CommonObject if($user->rights->expensereport->lire) { - $sql = "SELECT de.fk_expensereport, de.date, de.comments, de.total_ht, de.total_ttc"; - $sql.= " FROM ".MAIN_DB_PREFIX."expensereport_det as de"; - $sql.= " WHERE de.fk_projet = ".$projectid; + $sql = "SELECT de.fk_expensereport, de.date, de.comments, de.total_ht, de.total_ttc"; + $sql.= " FROM ".MAIN_DB_PREFIX."expensereport_det as de"; + $sql.= " WHERE de.fk_projet = ".$projectid; - dol_syslog(get_class($this)."::fetch sql=".$sql, LOG_DEBUG); - $result = $db->query($sql) ; - if ($result) - { - $num = $db->num_rows($result); - $i = 0; - $total_HT = 0; - $total_TTC = 0; + dol_syslog(get_class($this)."::fetch sql=".$sql, LOG_DEBUG); + $result = $db->query($sql) ; + if ($result) + { + $num = $db->num_rows($result); + $i = 0; + $total_HT = 0; + $total_TTC = 0; - while ($i < $num) - { + while ($i < $num) + { - $objp = $db->fetch_object($result); + $objp = $db->fetch_object($result); - $sql2 = "SELECT d.rowid, d.fk_user_author, d.ref, d.fk_c_expensereport_statuts"; - $sql2.= " FROM ".MAIN_DB_PREFIX."expensereport as d"; - $sql2.= " WHERE d.rowid = '".$objp->fk_expensereport."'"; + $sql2 = "SELECT d.rowid, d.fk_user_author, d.ref, d.fk_c_expensereport_statuts"; + $sql2.= " FROM ".MAIN_DB_PREFIX."expensereport as d"; + $sql2.= " WHERE d.rowid = '".$objp->fk_expensereport."'"; - $result2 = $db->query($sql2); - $obj = $db->fetch_object($result2); + $result2 = $db->query($sql2); + $obj = $db->fetch_object($result2); - $objp->fk_user_author = $obj->fk_user_author; - $objp->ref = $obj->ref; - $objp->fk_c_expensereport_status = $obj->fk_c_expensereport_statuts; - $objp->rowid = $obj->rowid; + $objp->fk_user_author = $obj->fk_user_author; + $objp->ref = $obj->ref; + $objp->fk_c_expensereport_status = $obj->fk_c_expensereport_statuts; + $objp->rowid = $obj->rowid; - $total_HT = $total_HT + $objp->total_ht; - $total_TTC = $total_TTC + $objp->total_ttc; - $author = new User($db); - $author->fetch($objp->fk_user_author); + $total_HT = $total_HT + $objp->total_ht; + $total_TTC = $total_TTC + $objp->total_ttc; + $author = new User($db); + $author->fetch($objp->fk_user_author); - print '
'; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; - print ''; + switch($objp->fk_c_expensereport_status) { + case 4: + print img_picto($langs->trans('StatusOrderCanceled'),'statut5'); + break; + case 1: + print $langs->trans('Draft').' '.img_picto($langs->trans('Draft'),'statut0'); + break; + case 2: + print $langs->trans('TripForValid').' '.img_picto($langs->trans('TripForValid'),'statut3');; + break; + case 5: + print $langs->trans('TripForPaid').' '.img_picto($langs->trans('TripForPaid'),'statut3'); + break; + case 6: + print $langs->trans('TripPaid').' '.img_picto($langs->trans('TripPaid'),'statut4'); + break; + } + /* + if ($status==4) return img_picto($langs->trans('StatusOrderCanceled'),'statut5'); + if ($status==1) return img_picto($langs->trans('StatusOrderDraft'),'statut0'); + if ($status==2) return img_picto($langs->trans('StatusOrderValidated'),'statut1'); + if ($status==2) return img_picto($langs->trans('StatusOrderOnProcess'),'statut3'); + if ($status==5) return img_picto($langs->trans('StatusOrderToBill'),'statut4'); + if ($status==6) return img_picto($langs->trans('StatusOrderOnProcess'),'statut6'); + */ + print ''; + print ''; - $i++; - } + $i++; + } - print ''; - print ''; - print ''; - print ''; - print ''; + print ''; + print ''; + print ''; + print ''; + print ''; - } - else - { - $this->error=$db->error(); - return -1; - } - } + } + else + { + $this->error=$db->error(); + return -1; + } + } } @@ -580,10 +580,10 @@ class ExpenseReport extends CommonObject $num = $this->db->num_rows($result); $i = 0; while ($i < $num): - $objp = $this->db->fetch_object($result); - $total_ht+=$objp->total_ht; - $total_tva+=$objp->total_tva; - $i++; + $objp = $this->db->fetch_object($result); + $total_ht+=$objp->total_ht; + $total_tva+=$objp->total_tva; + $i++; endwhile; $total_ttc = $total_ht + $total_tva; @@ -594,19 +594,19 @@ class ExpenseReport extends CommonObject $sql.= " WHERE rowid = ".$id; $result = $this->db->query($sql); if($result): - $this->db->free($result); - return 1; + $this->db->free($result); + return 1; else: - $this->error=$this->db->error(); - dol_syslog('ExpenseReport::recalculer: Error '.$this->error,LOG_ERR); - return -3; + $this->error=$this->db->error(); + dol_syslog('ExpenseReport::recalculer: Error '.$this->error,LOG_ERR); + return -3; endif; } else { - $this->error=$this->db->error(); - dol_syslog('ExpenseReport::recalculer: Error '.$this->error,LOG_ERR); - return -3; + $this->error=$this->db->error(); + dol_syslog('ExpenseReport::recalculer: Error '.$this->error,LOG_ERR); + return -3; } } @@ -718,12 +718,12 @@ class ExpenseReport extends CommonObject } /** - * set_save + * Set to status validate * * @param User $user User * @return int <0 if KO, >0 if OK */ - function set_save($user) + function setValidate($user) { global $conf,$langs; @@ -752,8 +752,8 @@ class ExpenseReport extends CommonObject if ($this->fk_c_expensereport_statuts != 2) { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; - $sql.= " SET ref = '".$this->ref."', fk_c_expensereport_statuts = 2"; - $sql.= " ,ref_number_int = $ref_number_int"; + $sql.= " SET ref = '".$this->ref."', fk_c_expensereport_statuts = 2, fk_user_valid = ".$user->id.","; + $sql.= " ref_number_int = ".$ref_number_int; $sql.= ' WHERE rowid = '.$this->id; dol_syslog(get_class($this)."::set_save sql=".$sql, LOG_DEBUG); @@ -822,30 +822,30 @@ class ExpenseReport extends CommonObject } /** - * set_valide + * Set status to approved * * @param User $user User * @return int <0 if KO, >0 if OK */ - function set_valide($user) + function setApproved($user) { // date de validation $this->date_valide = $this->db->idate(gmmktime()); if ($this->fk_c_expensereport_statuts != 5) { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; - $sql.= " SET ref = '".$this->ref."', fk_c_expensereport_statuts = 5, fk_user_valid = ".$user->id; - $sql.= ', date_valide='.$this->date_valide; + $sql.= " SET ref = '".$this->ref."', fk_c_expensereport_statuts = 5, fk_user_approve = ".$user->id.","; + $sql.= " date_valide='".$this->date_valide."'"; $sql.= ' WHERE rowid = '.$this->id; - - dol_syslog(get_class($this)."::set_valide sql=".$sql, LOG_DEBUG); - - if ($this->db->query($sql)): + if ($this->db->query($sql)) + { return 1; - else: - $this->error=$this->db->error(); + } + else + { + $this->error=$this->db->lasterror(); return -1; - endif; + } } else { @@ -861,24 +861,29 @@ class ExpenseReport extends CommonObject */ function set_refuse($user,$details) { + $now = dol_now(); + // date de refus - $this->date_refuse = $this->db->idate(gmmktime()); if ($this->fk_c_expensereport_statuts != 99) { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; - $sql.= " SET ref = '".$this->ref."', fk_c_expensereport_statuts = 99, fk_user_refuse = ".$user->id; - $sql.= ', date_refuse='.$this->date_refuse; - $sql.= ", detail_refuse='".addslashes($details)."'"; + $sql.= " SET ref = '".$this->ref."', fk_c_expensereport_statuts = 99, fk_user_refuse = ".$user->id.","; + $sql.= " date_refuse='".$this->db->idate($now)."',"; + $sql.= " detail_refuse='".$this->db->escape($details)."'"; $sql.= ' WHERE rowid = '.$this->id; - - dol_syslog(get_class($this)."::set_refuse sql=".$sql, LOG_DEBUG); - - if ($this->db->query($sql)): + if ($this->db->query($sql)) + { + $this->fk_c_expensereport_statuts = 99; + $this->fk_user_refuse = $user->id; + $this->detail_refuse = $details; + $this->date_refuse = $now; return 1; - else: - $this->error=$this->db->error(); + } + else + { + $this->error=$this->db->lasterror(); return -1; - endif; + } } else { @@ -887,22 +892,22 @@ class ExpenseReport extends CommonObject } /** - * set_paid + * setPaid * * @param User $user User * @return int <0 if KO, >0 if OK */ - function set_paid($user) + function setPaid($user) { $this->date_paiement = $this->db->idate(gmmktime()); if ($this->fk_c_expensereport_statuts != 6) { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; - $sql.= " SET fk_c_expensereport_statuts = 6, fk_user_paid = ".$user->id; - $sql.= ', date_paiement='.$this->date_paiement; + $sql.= " SET fk_c_expensereport_statuts = 6, fk_user_paid = ".$user->id.","; + $sql.= " date_paiement='".$this->date_paiement."'"; $sql.= ' WHERE rowid = '.$this->id; - dol_syslog(get_class($this)."::set_paid sql=".$sql, LOG_DEBUG); + dol_syslog(get_class($this)."::setPaid sql=".$sql, LOG_DEBUG); if ($this->db->query($sql)) { @@ -931,52 +936,21 @@ class ExpenseReport extends CommonObject if ($this->fk_c_deplacement_statuts != 5) { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; - $sql.= " SET fk_c_deplacement_statuts = 5"; + $sql.= " SET fk_c_expensereport_statuts = 5"; $sql.= ' WHERE rowid = '.$this->id; dol_syslog(get_class($this)."::set_unpaid sql=".$sql, LOG_DEBUG); if ($this->db->query($sql)): - return 1; + return 1; else: - $this->error=$this->db->error(); - return -1; + $this->error=$this->db->error(); + return -1; endif; } else { - dol_syslog(get_class($this)."::set_unpaid deplacement already with unpaid status", LOG_WARNING); - } - } - - /** - * set_draft - * - * @param User $user User - * @return int <0 if KO, >0 if OK - */ - function set_draft($user) - { - if ($this->fk_c_deplacement_statuts != 1) - { - $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; - $sql.= " SET fk_c_deplacement_statuts = 1,"; - //$sql.= " , ref = '(PROV".$this->id.")', ref_number_int = 0"; - $sql.= " ref_number_int = 0"; - $sql.= ' WHERE rowid = '.$this->id; - - dol_syslog(get_class($this)."::set_draft sql=".$sql, LOG_DEBUG); - - if ($this->db->query($sql)) return 1; - else - { - $this->error=$this->db->error(); - return -1; - } - } - else - { - dol_syslog(get_class($this)."::set_draft deplacement already with draft status", LOG_WARNING); + dol_syslog(get_class($this)."::set_unpaid expensereport already with unpaid status", LOG_WARNING); } } @@ -1026,7 +1000,7 @@ class ExpenseReport extends CommonObject { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; $sql.= " SET fk_c_expensereport_statuts = 4, fk_user_cancel = ".$user->id; - $sql.= ', date_cancel='.$this->date_cancel; + $sql.= ", date_cancel='".$this->date_cancel."'"; $sql.= " ,detail_cancel='".$this->db->escape($detail)."'"; $sql.= ' WHERE rowid = '.$this->id; @@ -1062,24 +1036,24 @@ class ExpenseReport extends CommonObject $result = $this->db->query($sql); if($this->db->num_rows($result) > 0): - $objp = $this->db->fetch_object($result); - $this->ref = $objp->ref_number_int; - $this->ref++; - while(strlen($this->ref) < $num_car): - $this->ref = "0".$this->ref; - endwhile; + $objp = $this->db->fetch_object($result); + $this->ref = $objp->ref_number_int; + $this->ref++; + while(strlen($this->ref) < $num_car): + $this->ref = "0".$this->ref; + endwhile; else: - $this->ref = 1; - while(strlen($this->ref) < $num_car): - $this->ref = "0".$this->ref; - endwhile; + $this->ref = 1; + while(strlen($this->ref) < $num_car): + $this->ref = "0".$this->ref; + endwhile; endif; if ($result): - return 1; + return 1; else: - $this->error=$this->db->error(); - return -1; + $this->error=$this->db->error(); + return -1; endif; } @@ -1123,10 +1097,10 @@ class ExpenseReport extends CommonObject $result = $this->db->query($sql); if ($result): - return 1; + return 1; else: - $this->error=$this->db->error(); - return -1; + $this->error=$this->db->error(); + return -1; endif; } @@ -1143,10 +1117,10 @@ class ExpenseReport extends CommonObject $result = $this->db->query($sql); if ($result): - return 1; + return 1; else: - $this->error=$this->db->error(); - return -1; + $this->error=$this->db->error(); + return -1; endif; } @@ -1214,12 +1188,12 @@ class ExpenseReport extends CommonObject $result = $ligne->update(); if ($result > 0): - $this->db->commit(); - return 1; + $this->db->commit(); + return 1; else: - $this->error=$ligne->error; - $this->db->rollback(); - return -2; + $this->error=$ligne->error; + $this->db->rollback(); + return -2; endif; } @@ -1467,7 +1441,7 @@ class ExpenseReportLine $sql.= " VALUES (".$this->fk_expensereport.","; $sql.= " ".$this->fk_c_type_fees.","; $sql.= " ".($this->fk_projet>0?$this->fk_projet:'null').","; - $sql.= " ".$this->fk_c_tva.","; + $sql.= " ".$this->vatrate.","; $sql.= " '".$this->db->escape($this->comments)."',"; $sql.= " ".$this->qty.","; $sql.= " ".$this->value_unit.","; @@ -1531,8 +1505,11 @@ class ExpenseReportLine $sql.= " comments='".$this->db->escape($this->comments)."'"; $sql.= ",value_unit=".$this->value_unit.""; $sql.= ",qty=".$this->qty.""; - if ($this->date) { $sql.= ",date='".$this->date."'"; } - else { $sql.=',date=null'; } + if ($this->date) { + $sql.= ",date='".$this->date."'"; + } + else { $sql.=',date=null'; + } $sql.= ",total_ht=".$this->total_ht.""; $sql.= ",total_tva=".$this->total_tva.""; $sql.= ",total_ttc=".$this->total_ttc.""; @@ -1587,9 +1564,9 @@ class ExpenseReportLine */ function select_expensereport_statut($selected='',$htmlname='fk_c_expensereport_statuts',$useempty=1) { - global $db; + global $db; - $tmpep=new ExpenseReport($db); + $tmpep=new ExpenseReport($db); print ''; } -/** - * select_projet - * TODO Utiliser le select project officiel - * - * @param int $selected Id selected - * @param string $filter Filter - * @param string $htmlname Select name - * @return int <0 if KO, >0 if OK - */ -function select_projet($selected='',$filter='', $htmlname='fk_projet') -{ - global $conf,$user,$langs,$db; - - $out=''; - - $sql = "SELECT p.rowid, p.ref, p.title"; - $sql.= " FROM ".MAIN_DB_PREFIX."projet as p"; - $sql.= " WHERE p.entity = ".$conf->entity; - if (is_numeric($selected)) $sql.= " AND p.rowid = ".$selected; - - dol_syslog("Form::select_projet sql=".$sql); - $resql=$db->query($sql); - if ($resql) - { - if ($conf->use_javascript_ajax && ! $forcecombo) - { - $minLength = (is_numeric($conf->global->COMPANY_USE_SEARCH_TO_SELECT)?$conf->global->COMPANY_USE_SEARCH_TO_SELECT:2); - - $projetid = 0; - - if ($selected) - { - $obj = $db->fetch_object($resql); - $projetid = $obj->rowid?$obj->rowid:''; - } - - $out.= "\n".''."\n"; - $out.= '
'.$langs->trans("IBAN").''.$account->iban.'
'.$account->iban . ' '; + if (! empty($account->iban)) { + if (! checkIbanForAccount($account)) { + print img_picto($langs->trans("NotValid"),'warning'); + } else { + print img_picto($langs->trans("IsValid"),'info'); + } + } + print '
'.$langs->trans("BIC").''.$account->bic.'
'.$langs->trans($ibankey).''.$account->iban.'
'.$account->iban.' '; + if (! empty($account->iban)) { + if (! checkIbanForAccount($account)) { + print img_picto($langs->trans("IbanNotValid"),'warning'); + } else { + print img_picto($langs->trans("IbanValid"),'info'); + } + } + print '
'.$langs->trans($bickey).''.$account->bic.'
'.$account->iban . ' '; if (! empty($account->iban)) { if (! checkIbanForAccount($account)) { - print img_picto($langs->trans("NotValid"),'warning'); + print img_picto($langs->trans("IbanNotValid"),'warning'); } else { - print img_picto($langs->trans("IsValid"),'info'); + print img_picto($langs->trans("IbanValid"),'info'); } } print '
'.$langs->trans('NbDaysToDelivery').' '.img_picto($langs->trans('DescNbDaysToDelivery'), 'info', 'style="cursor:help"').''.$object->getMaxDeliveryTimeDay($langs).'
'.$langs->trans($bickey).''.$account->bic.'
'.$account->bic.' '; + if (! empty($account->bic)) { + if (! checkSwiftForAccount($account)) { + print img_picto($langs->trans("SwiftNotValid"),'warning'); + } else { + print img_picto($langs->trans("SwiftValid"),'info'); + } + } + print '
'.$langs->trans("BankAccountDomiciliation").''; print nl2br($account->domiciliation); diff --git a/htdocs/core/lib/bank.lib.php b/htdocs/core/lib/bank.lib.php index 36626ffcc94..db6b9d5b8aa 100644 --- a/htdocs/core/lib/bank.lib.php +++ b/htdocs/core/lib/bank.lib.php @@ -121,7 +121,24 @@ function bank_admin_prepare_head($object) complete_head_from_modules($conf, $langs, $object, $head, $h, 'bank_admin', 'remove'); return $head; - } +} + +/** + * Check SWIFT informations for a bank account + * + * @param Account $account A bank account + * @return int True if informations are valid, false otherwise + */ +function checkSwiftForAccount($account) +{ + $swift = $account->bic; + if (eregi("^([a-zA-Z]){4}([a-zA-Z]){2}([0-9a-zA-Z]){2}([0-9a-zA-Z]{3})?$", $swift)) { + return true; + } else { + return false; + } + +} /** * Check IBAN number informations for a bank account @@ -134,13 +151,9 @@ function checkIbanForAccount($account) require_once DOL_DOCUMENT_ROOT.'/includes/php-iban/oophp-iban.php'; $iban = new Iban($account->iban); $check = $iban->Verify(); - //print '
'.print_r($iban, true).'
'; if ($check) { - //print '
OK
'; return true; } else { - //$suggest = $iban->MistranscriptionSuggestions($account->iban); - //print '
'.print_r($suggest, true).'
'; return false; } diff --git a/htdocs/langs/en_US/banks.lang b/htdocs/langs/en_US/banks.lang index 7358f25e6f4..dfa0934ce70 100644 --- a/htdocs/langs/en_US/banks.lang +++ b/htdocs/langs/en_US/banks.lang @@ -33,9 +33,11 @@ AllTime=From start Reconciliation=Reconciliation RIB=Bank Account Number IBAN=IBAN number -IbanValid=Valid IBAN -IbanNotValid=Not Valid IBAN +IbanValid=IBAN is Valid +IbanNotValid=IBAN is Not Valid BIC=BIC/SWIFT number +SwiftValid=BIC/SWIFT is Valid +SwiftNotValid=BIC/SWIFT is Not Valid StandingOrders=Standing orders StandingOrder=Standing order Withdrawals=Withdrawals diff --git a/htdocs/societe/rib.php b/htdocs/societe/rib.php index ad3eea735fb..2a21f6cdc87 100644 --- a/htdocs/societe/rib.php +++ b/htdocs/societe/rib.php @@ -304,7 +304,15 @@ if ($socid && $action != 'edit' && $action != "create") print '
'.$langs->trans("BIC").''.$account->bic.'
'.$account->bic.' '; + if (! empty($account->bic)) { + if (! checkSwiftForAccount($account)) { + print img_picto($langs->trans("SwiftNotValid"),'warning'); + } else { + print img_picto($langs->trans("SwiftValid"),'info'); + } + } + print '
'.$langs->trans("BankAccountDomiciliation").''; print $account->domiciliation; From cbe49df090d5e34dcdef9254b36bb6cb38cca9c7 Mon Sep 17 00:00:00 2001 From: frederic34 Date: Wed, 18 Feb 2015 16:07:59 +0100 Subject: [PATCH 152/173] Add copyright --- COPYRIGHT | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/COPYRIGHT b/COPYRIGHT index 1631f85d321..cf31432caf0 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -21,6 +21,7 @@ GeoIP 1.4 LGPL-2.1+ Yes NuSoap 0.9.5 LGPL 2.1+ Yes Library to develop SOAP Web services (not into rpm and deb package) odtPHP 1.0.1 GPL-2+ b Yes Library to build/edit ODT files PHPExcel 1.7.8 LGPL-2.1+ Yes Read/Write XLS files, read ODS files +php-iban 1.4.6 LGPL-3+ Yes Parse and validate IBAN (and IIBAN) bank account information in PHP PHPPrintIPP 1.3 GPL-2+ Yes Library to send print IPP requests TCPDF 6.0.093 LGPL-3+ Yes PDF generation @@ -54,7 +55,10 @@ Copyright --------- Copyright (C) 2015 +- Laurent Destailleur - Marcos García +- Alexandre Spangaro +- Frederic France Copyright (C) 2014 - Laurent Destailleur @@ -67,6 +71,7 @@ Copyright (C) 2014 - Maxime Kohlhaas - Juanjo Menent - Alexandre Spangaro +- Frederic France Copyright (C) 2013 - Christophe Battarel From fe50a585fc75ea801e8a3b9ac09f73c93eca0c07 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 18 Feb 2015 18:47:01 +0100 Subject: [PATCH 153/173] Fix: removed deprecated menu --- htdocs/install/mysql/migration/3.7.0-3.8.0.sql | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql index 831185a9203..a697096874a 100755 --- a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql +++ b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql @@ -19,6 +19,10 @@ -- -- VMYSQL4.1 DELETE FROM llx_usergroup_user WHERE fk_usergroup NOT IN (SELECT rowid from llx_usergroup); +-- Remove menu entries of removed or renamed modules +DELETE FROM llx_menu where module = 'printipp'; + + ALTER TABLE llx_bank ADD INDEX idx_bank_num_releve(num_releve); From cc1d506614ca9e0267f3d6335cd71aa2b65c8719 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 18 Feb 2015 21:01:17 +0100 Subject: [PATCH 154/173] Miscelaneous debug on barcode features. --- htdocs/admin/barcode.php | 5 +- htdocs/barcode/codeinit.php | 7 ++- htdocs/commande/contact.php | 2 +- htdocs/core/menus/standard/eldy.lib.php | 4 +- htdocs/core/modules/DolibarrModules.class.php | 7 ++- htdocs/cron/card.php | 2 +- htdocs/cron/info.php | 2 +- htdocs/install/upgrade2.php | 62 +++++++++++++------ htdocs/langs/en_US/admin.lang | 2 +- htdocs/langs/en_US/cron.lang | 1 + htdocs/langs/en_US/errors.lang | 2 +- 11 files changed, 61 insertions(+), 35 deletions(-) diff --git a/htdocs/admin/barcode.php b/htdocs/admin/barcode.php index 11341f632a2..725d53dd1c3 100644 --- a/htdocs/admin/barcode.php +++ b/htdocs/admin/barcode.php @@ -1,6 +1,6 @@ - * Copyright (C) 2004-2011 Laurent Destailleur + * Copyright (C) 2004-2015 Laurent Destailleur * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2011-2013 Juanjo Menent * @@ -430,6 +430,5 @@ print ''; print "
"; -$db->close(); - llxFooter(); +$db->close(); diff --git a/htdocs/barcode/codeinit.php b/htdocs/barcode/codeinit.php index 19fb5c193bb..a2e24685017 100644 --- a/htdocs/barcode/codeinit.php +++ b/htdocs/barcode/codeinit.php @@ -27,6 +27,7 @@ require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; $langs->load("admin"); $langs->load("members"); $langs->load("errors"); +$langs->load("other"); // Choice of print year or current year. $now = dol_now(); @@ -229,7 +230,7 @@ if ($conf->societe->enabled) } else dol_print_error($db); - print $langs->trans("CurrentlyNWithoutBarCode", $nbno, $nbtotal, $langs->transnoentitiesnoconv("Thirdparties")).'
'."\n"; + print $langs->trans("CurrentlyNWithoutBarCode", $nbno, $nbtotal, $langs->transnoentitiesnoconv("ThirdParties")).'
'."\n"; print '
product->enabled || $conf->product->service) $nbno=$nbtotal=0; print_fiche_titre($langs->trans("BarcodeInitForProductsOrServices"),'','').'
'."\n"; - $sql ="SELECT count(rowid) as nb, fk_product_type"; + $sql ="SELECT count(rowid) as nb, fk_product_type, datec"; $sql.=" FROM ".MAIN_DB_PREFIX."product"; $sql.=" WHERE barcode IS NULL OR barcode = ''"; - $sql.=" GROUP BY fk_product_type"; + $sql.=" GROUP BY fk_product_type, datec"; $sql.=" ORDER BY datec"; $resql=$db->query($sql); if ($resql) diff --git a/htdocs/commande/contact.php b/htdocs/commande/contact.php index c36f19c166b..6a322e8681e 100644 --- a/htdocs/commande/contact.php +++ b/htdocs/commande/contact.php @@ -221,5 +221,5 @@ if ($id > 0 || ! empty($ref)) } -$db->close(); llxFooter(); +$db->close(); diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index 1ae0d46343b..c88c8375a41 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -217,8 +217,8 @@ function print_eldy_menu($db,$atarget,$type_user,&$tabMenu,&$menu,$noout=0) // Tools - $tmpentry=array('enabled'=>(! empty($conf->mailing->enabled) || ! empty($conf->export->enabled) || ! empty($conf->import->enabled) || ! empty($conf->opensurvey->enabled)), - 'perms'=>(! empty($user->rights->mailing->lire) || ! empty($user->rights->export->lire) || ! empty($user->rights->import->run) || ! empty($user->rights->opensurvey->read)), + $tmpentry=array('enabled'=>(! empty($conf->barcode->enabled) || ! empty($conf->mailing->enabled) || ! empty($conf->export->enabled) || ! empty($conf->import->enabled) || ! empty($conf->opensurvey->enabled)), + 'perms'=>(! empty($conf->barcode->enabled) || ! empty($user->rights->mailing->lire) || ! empty($user->rights->export->lire) || ! empty($user->rights->import->run) || ! empty($user->rights->opensurvey->read)), 'module'=>'mailing|export|import|opensurvey'); $showmode=dol_eldy_showmenu($type_user, $tmpentry, $listofmodulesforexternal); if ($showmode) diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index 91b6e57a9b5..045bb1ddbcf 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -193,7 +193,9 @@ abstract class DolibarrModules * Inserts all informations into database * * @param string[] $array_sql SQL requests to be executed when enabling module - * @param string $options String with options when disabling module ('newboxdefonly|noboxes') + * @param string $options String with options when disabling module: + * 'noboxes' = Do not insert boxes + * 'newboxdefonly' = For boxes, insert def of boxes only and not boxes activation * * @return int 1 if OK, 0 if KO */ @@ -279,7 +281,8 @@ abstract class DolibarrModules * Disable function. Deletes the module constant and boxes from the database. * * @param string[] $array_sql SQL requests to be executed when module is disabled - * @param string $options Options when disabling module ('newboxdefonly|noboxes') + * @param string $options Options when disabling module: + * 'newboxdefonly|noboxes' = We don't remove boxes. * * @return int 1 if OK, 0 if KO */ diff --git a/htdocs/cron/card.php b/htdocs/cron/card.php index a826264c94e..f3c7d0363bb 100644 --- a/htdocs/cron/card.php +++ b/htdocs/cron/card.php @@ -227,7 +227,7 @@ llxHeader('',$langs->trans("CronAdd")); if ($action=='edit' || empty($action) || $action=='delete' || $action=='execute') { $head=cron_prepare_head($object); - print dol_get_fiche_head($head, 'card', $langs->trans("CronTask"), 0, 'bill'); + print dol_get_fiche_head($head, 'card', $langs->trans("CronTask"), 0, 'cron'); } elseif ($action=='create') { diff --git a/htdocs/cron/info.php b/htdocs/cron/info.php index 53489d69f5a..ceec1d34adb 100644 --- a/htdocs/cron/info.php +++ b/htdocs/cron/info.php @@ -46,7 +46,7 @@ $object->info($id); $head = cron_prepare_head($object); -dol_fiche_head($head, 'info', $langs->trans("CronTask"), 0, 'bill'); +dol_fiche_head($head, 'info', $langs->trans("CronTask"), 0, 'cron'); print ''; - print '\n"; + $payment_type = $langs->trans("PaymentType".$objp->paiement_type)!=("PaymentType".$objp->paiement_type)?$langs->trans("PaymentType".$objp->paiement_type):$objp->paiement_libelle; + + print '\n"; print ', $tbodyStart = $rowMin; - $tbodyEnd = $rowMax; $theadStart = $theadEnd = 0; // default: no no if ($sheet->getPageSetup()->isRowsToRepeatAtTopSet()) { $rowsToRepeatAtTop = $sheet->getPageSetup()->getRowsToRepeatAtTop(); @@ -429,7 +428,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { while($column++ < $dimension[1][0]) { // Cell exists? if ($sheet->cellExistsByColumnAndRow($column, $row)) { - $rowData[$column] = $sheet->getCellByColumnAndRow($column, $row); + $rowData[$column] = PHPExcel_Cell::stringFromColumnIndex($column) . $row; } else { $rowData[$column] = ''; } @@ -441,12 +440,11 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { if ($row == $theadEnd) { $html .= ' ' . PHP_EOL; } - - // ? - if ($row == $tbodyEnd) { - $html .= ' ' . PHP_EOL; - } } + $html .= $this->_extendRowsForChartsAndImages($sheet, $row); + + // Close table body. + $html .= ' ' . PHP_EOL; // Write table footer $html .= $this->_generateTableFooter(); @@ -470,13 +468,13 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { * Generate sheet tabs * * @return string - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function generateNavigation() { // PHPExcel object known? if (is_null($this->_phpExcel)) { - throw new Exception('Internal PHPExcel object not set to an instance of an object.'); + throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); } // Fetch sheets @@ -508,15 +506,65 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { return $html; } + private function _extendRowsForChartsAndImages(PHPExcel_Worksheet $pSheet, $row) { + $rowMax = $row; + $colMax = 'A'; + if ($this->_includeCharts) { + foreach ($pSheet->getChartCollection() as $chart) { + if ($chart instanceof PHPExcel_Chart) { + $chartCoordinates = $chart->getTopLeftPosition(); + $chartTL = PHPExcel_Cell::coordinateFromString($chartCoordinates['cell']); + $chartCol = PHPExcel_Cell::columnIndexFromString($chartTL[0]); + if ($chartTL[1] > $rowMax) { + $rowMax = $chartTL[1]; + if ($chartCol > PHPExcel_Cell::columnIndexFromString($colMax)) { + $colMax = $chartTL[0]; + } + } + } + } + } + + foreach ($pSheet->getDrawingCollection() as $drawing) { + if ($drawing instanceof PHPExcel_Worksheet_Drawing) { + $imageTL = PHPExcel_Cell::coordinateFromString($drawing->getCoordinates()); + $imageCol = PHPExcel_Cell::columnIndexFromString($imageTL[0]); + if ($imageTL[1] > $rowMax) { + $rowMax = $imageTL[1]; + if ($imageCol > PHPExcel_Cell::columnIndexFromString($colMax)) { + $colMax = $imageTL[0]; + } + } + } + } + $html = ''; + $colMax++; + while ($row < $rowMax) { + $html .= ''; + for ($col = 'A'; $col != $colMax; ++$col) { + $html .= ''; + } + ++$row; + $html .= ''; + } + return $html; + } + + /** * Generate image tag in cell * * @param PHPExcel_Worksheet $pSheet PHPExcel_Worksheet * @param string $coordinates Cell coordinates * @return string - * @throws Exception + * @throws PHPExcel_Writer_Exception */ - private function _writeImageTagInCell(PHPExcel_Worksheet $pSheet, $coordinates) { + private function _writeImageInCell(PHPExcel_Worksheet $pSheet, $coordinates) { // Construct HTML $html = ''; @@ -543,7 +591,74 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { $filename = htmlspecialchars($filename); $html .= PHP_EOL; - $html .= ' ' . PHP_EOL; + if ((!$this->_embedImages) || ($this->_isPdf)) { + $imageData = $filename; + } else { + $imageDetails = getimagesize($filename); + if ($fp = fopen($filename,"rb", 0)) { + $picture = fread($fp,filesize($filename)); + fclose($fp); + // base64 encode the binary data, then break it + // into chunks according to RFC 2045 semantics + $base64 = chunk_split(base64_encode($picture)); + $imageData = 'data:'.$imageDetails['mime'].';base64,' . $base64; + } else { + $imageData = $filename; + } + } + + $html .= '
'; + $html .= ''; + $html .= '
'; + } + } + } + + // Return + return $html; + } + + /** + * Generate chart tag in cell + * + * @param PHPExcel_Worksheet $pSheet PHPExcel_Worksheet + * @param string $coordinates Cell coordinates + * @return string + * @throws PHPExcel_Writer_Exception + */ + private function _writeChartInCell(PHPExcel_Worksheet $pSheet, $coordinates) { + // Construct HTML + $html = ''; + + // Write charts + foreach ($pSheet->getChartCollection() as $chart) { + if ($chart instanceof PHPExcel_Chart) { + $chartCoordinates = $chart->getTopLeftPosition(); + if ($chartCoordinates['cell'] == $coordinates) { + $chartFileName = PHPExcel_Shared_File::sys_get_temp_dir().'/'.uniqid().'.png'; + if (!$chart->render($chartFileName)) { + return; + } + + $html .= PHP_EOL; + $imageDetails = getimagesize($chartFileName); + if ($fp = fopen($chartFileName,"rb", 0)) { + $picture = fread($fp,filesize($chartFileName)); + fclose($fp); + // base64 encode the binary data, then break it + // into chunks according to RFC 2045 semantics + $base64 = chunk_split(base64_encode($picture)); + $imageData = 'data:'.$imageDetails['mime'].';base64,' . $base64; + + $html .= '
'; + $html .= '' . PHP_EOL; + $html .= '
'; + + unlink($chartFileName); + } } } } @@ -557,12 +672,12 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { * * @param boolean $generateSurroundingHTML Generate surrounding HTML tags? () * @return string - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function generateStyles($generateSurroundingHTML = true) { // PHPExcel object known? if (is_null($this->_phpExcel)) { - throw new Exception('Internal PHPExcel object not set to an instance of an object.'); + throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); } // Build CSS @@ -598,12 +713,12 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { * * @param boolean $generateSurroundingHTML Generate surrounding HTML style? (html { }) * @return array - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function buildCSS($generateSurroundingHTML = true) { // PHPExcel object known? if (is_null($this->_phpExcel)) { - throw new Exception('Internal PHPExcel object not set to an instance of an object.'); + throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); } // Cached? @@ -851,7 +966,10 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { */ private function _createCSSStyleBorder(PHPExcel_Style_Border $pStyle) { // Create CSS - $css = $this->_mapBorderStyle($pStyle->getBorderStyle()) . ' #' . $pStyle->getColor()->getRGB(); +// $css = $this->_mapBorderStyle($pStyle->getBorderStyle()) . ' #' . $pStyle->getColor()->getRGB(); + // Create CSS - add !important to non-none border styles for merged cells + $borderStyle = $this->_mapBorderStyle($pStyle->getBorderStyle()); + $css = $borderStyle . ' #' . $pStyle->getColor()->getRGB() . (($borderStyle == 'none') ? '' : ' !important'); // Return return $css; @@ -894,25 +1012,26 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { * * @param PHPExcel_Worksheet $pSheet The worksheet for the table we are writing * @return string - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _generateTableHeader($pSheet) { $sheetIndex = $pSheet->getParent()->getIndex($pSheet); // Construct HTML $html = ''; - + $html .= $this->_setMargins($pSheet); + if (!$this->_useInlineCss) { - $gridlines = $pSheet->getShowGridLines() ? ' gridlines' : ''; + $gridlines = $pSheet->getShowGridlines() ? ' gridlines' : ''; $html .= '
'; dol_print_object_info($object); diff --git a/htdocs/install/upgrade2.php b/htdocs/install/upgrade2.php index 86ab911c71b..a7226c1621d 100644 --- a/htdocs/install/upgrade2.php +++ b/htdocs/install/upgrade2.php @@ -367,19 +367,21 @@ if (! GETPOST("action") || preg_match('/upgrade/i',GETPOST('action'))) // Reload modules (this must be always and only into last targeted version) $listofmodule=array( 'MAIN_MODULE_AGENDA', - 'MAIN_MODULE_SOCIETE', - 'MAIN_MODULE_PRODUIT', - 'MAIN_MODULE_SERVICE', + 'MAIN_MODULE_BARCODE', + 'MAIN_MODULE_CRON', 'MAIN_MODULE_COMMANDE', - 'MAIN_MODULE_FACTURE', - 'MAIN_MODULE_FOURNISSEUR', - 'MAIN_MODULE_USER', 'MAIN_MODULE_DEPLACEMENT', 'MAIN_MODULE_DON', 'MAIN_MODULE_ECM', - 'MAIN_MODULE_PAYBOX', - 'MAIN_MODULE_OPENSURVEY' - ); + 'MAIN_MODULE_FACTURE', + 'MAIN_MODULE_FOURNISSEUR', + 'MAIN_MODULE_OPENSURVEY', + 'MAIN_MODULE_PAYBOX', + 'MAIN_MODULE_PRODUIT', + 'MAIN_MODULE_SOCIETE', + 'MAIN_MODULE_SERVICE', + 'MAIN_MODULE_USER' + ); migrate_reload_modules($db,$langs,$conf,$listofmodule); // Reload menus (this must be always and only into last targeted version) @@ -3773,6 +3775,26 @@ function migrate_reload_modules($db,$langs,$conf,$listofmodule=array()) $mod->init('newboxdefonly'); } } + if ($moduletoreload == 'MAIN_MODULE_BARCODE') + { + dolibarr_install_syslog("upgrade2::migrate_reload_modules Reactivate module Barcode"); + $res=@include_once DOL_DOCUMENT_ROOT.'/core/modules/modBarcode.class.php'; + if ($res) { + $mod=new modBarcode($db); + $mod->remove('noboxes'); + $mod->init('newboxdefonly'); + } + } + if ($moduletoreload == 'MAIN_MODULE_CRON') + { + dolibarr_install_syslog("upgrade2::migrate_reload_modules Reactivate module Cron"); + $res=@include_once DOL_DOCUMENT_ROOT.'/core/modules/modCron.class.php'; + if ($res) { + $mod=new modCron($db); + $mod->remove('noboxes'); + $mod->init('newboxdefonly'); + } + } if ($moduletoreload == 'MAIN_MODULE_SOCIETE') { dolibarr_install_syslog("upgrade2::migrate_reload_modules Reactivate module Societe"); @@ -3833,17 +3855,6 @@ function migrate_reload_modules($db,$langs,$conf,$listofmodule=array()) $mod->init('newboxdefonly'); } } - - if ($moduletoreload == 'MAIN_MODULE_USER') // Permission has changed into 3.0 - { - dolibarr_install_syslog("upgrade2::migrate_reload_modules Reactivate module User"); - $res=@include_once DOL_DOCUMENT_ROOT.'/core/modules/modUser.class.php'; - if ($res) { - $mod=new modUser($db); - //$mod->remove('noboxes'); // We need to remove because id of module has changed - $mod->init('newboxdefonly'); - } - } if ($moduletoreload == 'MAIN_MODULE_DEPLACEMENT') // Permission has changed into 3.0 { dolibarr_install_syslog("upgrade2::migrate_reload_modules Reactivate module Deplacement"); @@ -3894,6 +3905,17 @@ function migrate_reload_modules($db,$langs,$conf,$listofmodule=array()) $mod->init('newboxdefonly'); } } + if ($moduletoreload == 'MAIN_MODULE_USER') // Permission has changed into 3.0 + { + dolibarr_install_syslog("upgrade2::migrate_reload_modules Reactivate module User"); + $res=@include_once DOL_DOCUMENT_ROOT.'/core/modules/modUser.class.php'; + if ($res) { + $mod=new modUser($db); + //$mod->remove('noboxes'); // We need to remove because id of module has changed + $mod->init('newboxdefonly'); + } + } + } } diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 1d2085dcbf7..009c7dd774c 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1374,7 +1374,7 @@ BarcodeDescUPC=Barcode of type UPC BarcodeDescISBN=Barcode of type ISBN BarcodeDescC39=Barcode of type C39 BarcodeDescC128=Barcode of type C128 -GenbarcodeLocation=Bar code generation command line tool (used by internal engine for some bar code types) +GenbarcodeLocation=Bar code generation command line tool (used by internal engine for some bar code types). Must be compatible with "genbarcode".
For example: /usr/local/bin/genbarcode BarcodeInternalEngine=Internal engine BarCodeNumberManager=Manager to auto define barcode numbers ##### Prelevements ##### diff --git a/htdocs/langs/en_US/cron.lang b/htdocs/langs/en_US/cron.lang index 5432c5b5b52..31e701f1e2d 100644 --- a/htdocs/langs/en_US/cron.lang +++ b/htdocs/langs/en_US/cron.lang @@ -84,3 +84,4 @@ CronType_command=Shell command CronMenu=Cron CronCannotLoadClass=Cannot load class %s or object %s UseMenuModuleToolsToAddCronJobs=Go into menu "Home - Modules tools - Job list" to see and edit scheduled jobs. +TaskDisabled=Task disabled diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang index 0187c567eb6..a2d73817bf1 100644 --- a/htdocs/langs/en_US/errors.lang +++ b/htdocs/langs/en_US/errors.lang @@ -25,7 +25,7 @@ ErrorFromToAccountsMustDiffers=Source and targets bank accounts must be differen ErrorBadThirdPartyName=Bad value for third party name ErrorProdIdIsMandatory=The %s is mandatory ErrorBadCustomerCodeSyntax=Bad syntax for customer code -ErrorBadBarCodeSyntax=Bad syntax for bar code +ErrorBadBarCodeSyntax=Bad syntax for bar code. May be you set a bad barcode type or you defined a barcode mask for numbering that does not match value scanned. ErrorCustomerCodeRequired=Customer code required ErrorBarCodeRequired=Bar code required ErrorCustomerCodeAlreadyUsed=Customer code already used From c2f5b24a9d09d76ad2867cc84600bf39441e305a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 18 Feb 2015 22:40:13 +0100 Subject: [PATCH 155/173] Better text --- htdocs/langs/en_US/admin.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 8ba499a7ae1..dcef2941d94 100755 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1512,7 +1512,7 @@ CashDeskThirdPartyForSell=Default generic third party to use for sells CashDeskBankAccountForSell=Default account to use to receive cash payments CashDeskBankAccountForCheque= Default account to use to receive payments by cheque CashDeskBankAccountForCB= Default account to use to receive payments by credit cards -CashDeskDoNotDecreaseStock=Disable stock decrease when a sell is done from Point of Sale +CashDeskDoNotDecreaseStock=Disable stock decrease when a sell is done from Point of Sale (if "no", stock decrease is done for each sell done from POS, whatever is option set into module Stock). CashDeskIdWareHouse=Force and restrict warehouse to use for stock decrease StockDecreaseForPointOfSaleDisabled=Stock decrease from Point Of Sale disabled CashDeskYouDidNotDisableStockDecease=You did not disable stock decrease when making a sell from Point Of Sale. So a warehouse is required. From fc415fc3c918b83c8cdb256506ace18a1dd6cc12 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 18 Feb 2015 22:44:42 +0100 Subject: [PATCH 156/173] Fix: [ bug #1826 ] Supplier payment types are not translated in fourn/facture/paiement.php --- ChangeLog | 1 + htdocs/fourn/facture/paiement.php | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 16073f9658c..51dd2ff268a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -23,6 +23,7 @@ English Dolibarr ChangeLog - Fix: [ bug #1827 ] Tax reports gives incorrect amounts when using external modules that create lines with special codes - Fix: [ bug #1822 ] SQL error in clientfourn.php report with PostgreSQL - Fix: [ bug #1832 ] SQL error when adding a product with no price defined to an object +- Fix: [ bug #1826 ] Supplier payment types are not translated in fourn/facture/paiement.php ***** ChangeLog for 3.6.2 compared to 3.6.1 ***** - Fix: fix ErrorBadValueForParamNotAString error message in price customer multiprice. diff --git a/htdocs/fourn/facture/paiement.php b/htdocs/fourn/facture/paiement.php index b6a4c5a7925..a8576cff01d 100644 --- a/htdocs/fourn/facture/paiement.php +++ b/htdocs/fourn/facture/paiement.php @@ -5,6 +5,7 @@ * Copyright (C) 2004 Christophe Combelles * Copyright (C) 2005 Marc Barilley / Ocebo * Copyright (C) 2005-2012 Regis Houssin + * Copyright (C) 2015 Marcos García * * 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 @@ -447,7 +448,7 @@ if (empty($action)) $sql = 'SELECT p.rowid as pid, p.datep as dp, p.amount as pamount, p.num_paiement,'; $sql.= ' s.rowid as socid, s.nom,'; - $sql.= ' c.libelle as paiement_type,'; + $sql.= ' c.code as paiement_type, c.libelle as paiement_libelle,'; $sql.= ' ba.rowid as bid, ba.label,'; if (!$user->rights->societe->client->voir) $sql .= ' sc.fk_soc, sc.fk_user,'; $sql.= ' SUM(f.amount)'; @@ -486,7 +487,7 @@ if (empty($action)) { $sql .= " AND s.nom LIKE '%".$db->escape($search_company)."%'"; } - $sql.= " GROUP BY p.rowid, p.datep, p.amount, p.num_paiement, s.rowid, s.nom, c.libelle, ba.rowid, ba.label"; + $sql.= " GROUP BY p.rowid, p.datep, p.amount, p.num_paiement, s.rowid, s.nom, c.code, c.libelle, ba.rowid, ba.label"; if (!$user->rights->societe->client->voir) $sql .= ", sc.fk_soc, sc.fk_user"; $sql.= $db->order($sortfield,$sortorder); $sql.= $db->plimit($limit+1, $offset); @@ -558,7 +559,9 @@ if (empty($action)) else print ' '; print '
'.dol_trunc($objp->paiement_type.' '.$objp->num_paiement,32)."'.$payment_type.' '.dol_trunc($objp->num_paiement,32)."'; if ($objp->bid) print ''.img_object($langs->trans("ShowAccount"),'account').' '.dol_trunc($objp->label,24).''; From bd9c168e3cace14d28bb6662a5b6a24d68a22709 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 18 Feb 2015 23:42:39 +0100 Subject: [PATCH 157/173] Doxygen --- htdocs/core/modules/expensereport/doc/pdf_standard.modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php b/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php index 8b84ff505ec..2ce272af9ef 100755 --- a/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php +++ b/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php @@ -739,7 +739,7 @@ class pdf_ extends ModeleExpenseReport /** * Show footer of page. Need this->emetteur object * - * @param PDF &$pdf PDF + * @param PDF $pdf PDF * @param Object $object Object to show * @param Translate $outputlangs Object lang for output * @param int $hidefreetext 1=Hide free text From b73f1eb82786ce30041598e5862f8c273c5ac051 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Thu, 19 Feb 2015 08:40:38 +0100 Subject: [PATCH 158/173] Update account.class.php --- htdocs/compta/bank/class/account.class.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/compta/bank/class/account.class.php b/htdocs/compta/bank/class/account.class.php index 16a9c45cc2a..1db6ec18cc6 100644 --- a/htdocs/compta/bank/class/account.class.php +++ b/htdocs/compta/bank/class/account.class.php @@ -910,6 +910,8 @@ class Account extends CommonObject $langs->load("banks"); $now=dol_now(); + require_once DOL_DOCUMENT_ROOT.'/core/class/WorkboardResponse.class.php'; + $response = new WorkboardResponse(); $response->warning_delay=$conf->bank->rappro->warning_delay/60/60/24; $response->label=$langs->trans("TransactionsToConciliate"); From 9be3e79a72ae381fec7ceb6a68f9a89011f60068 Mon Sep 17 00:00:00 2001 From: aspangaro Date: Fri, 20 Feb 2015 05:01:44 +0100 Subject: [PATCH 159/173] Align the version of AdoDb-Date library --- COPYRIGHT | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/COPYRIGHT b/COPYRIGHT index cf31432caf0..320d4dcd4f4 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.32 Modified BSD License Yes Date convertion (not into rpm package) +AdoDb-Date 0.33 Modified BSD License Yes Date convertion (not into rpm package) ChromePHP 4.3.3 Apache Software License 2.0 Yes Return server log to chrome browser console CKEditor 4.3.3 LGPL-2.1+ Yes Editor WYSIWYG FPDI 1.4.2 Apache Software License 2.0 Yes PDF templates management From 014f255f22ca256a354e526ea85a17b363611bf9 Mon Sep 17 00:00:00 2001 From: aspangaro Date: Fri, 20 Feb 2015 05:09:07 +0100 Subject: [PATCH 160/173] Update FPDF_TPL library to 1.2.3 --- COPYRIGHT | 2 +- htdocs/includes/fpdfi/fpdf_tpl.php | 49 ++++++++++++++++++------------ 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/COPYRIGHT b/COPYRIGHT index 320d4dcd4f4..05651d8b0e4 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -16,7 +16,7 @@ AdoDb-Date 0.33 Modified BSD License Yes ChromePHP 4.3.3 Apache Software License 2.0 Yes Return server log to chrome browser console CKEditor 4.3.3 LGPL-2.1+ Yes Editor WYSIWYG FPDI 1.4.2 Apache Software License 2.0 Yes PDF templates management -FPDF_TPL 1.2 Apache Software License 2.0 Yes PDF templates management +FPDF_TPL 1.2.3 Apache Software License 2.0 Yes PDF templates management GeoIP 1.4 LGPL-2.1+ Yes Sample code to make geoip convert (not into deb package) NuSoap 0.9.5 LGPL 2.1+ Yes Library to develop SOAP Web services (not into rpm and deb package) odtPHP 1.0.1 GPL-2+ b Yes Library to build/edit ODT files diff --git a/htdocs/includes/fpdfi/fpdf_tpl.php b/htdocs/includes/fpdfi/fpdf_tpl.php index 6e234bf9321..8482ba336ed 100644 --- a/htdocs/includes/fpdfi/fpdf_tpl.php +++ b/htdocs/includes/fpdfi/fpdf_tpl.php @@ -1,8 +1,8 @@ $this->rMargin, 'o_h' => $this->h, 'o_w' => $this->w, + 'o_FontFamily' => $this->FontFamily, + 'o_FontStyle' => $this->FontStyle, + 'o_FontSizePt' => $this->FontSizePt, + 'o_FontSize' => $this->FontSize, 'buffer' => '', 'x' => $x, 'y' => $y, @@ -121,6 +125,13 @@ class FPDF_TPL extends FPDF { $this->SetXY($x + $this->lMargin, $y + $this->tMargin); $this->SetRightMargin($this->w - $w + $this->rMargin); + if ($this->CurrentFont) { + $fontkey = $this->FontFamily . $this->FontStyle; + $this->_res['tpl'][$this->tpl]['fonts'][$fontkey] =& $this->fonts[$fontkey]; + + $this->_out(sprintf('BT /F%d %.2f Tf ET', $this->CurrentFont['i'], $this->FontSizePt)); + } + return $this->tpl; } @@ -148,6 +159,15 @@ class FPDF_TPL extends FPDF { $this->w = $tpl['o_w']; $this->SetAutoPageBreak($tpl['o_AutoPageBreak'], $tpl['o_bMargin']); + $this->FontFamily = $tpl['o_FontFamily']; + $this->FontStyle = $tpl['o_FontStyle']; + $this->FontSizePt = $tpl['o_FontSizePt']; + $this->FontSize = $tpl['o_FontSize']; + + $fontkey = $this->FontFamily . $this->FontStyle; + if ($fontkey) + $this->CurrentFont =& $this->fonts[$fontkey]; + return $this->tpl; } else { return false; @@ -213,13 +233,6 @@ class FPDF_TPL extends FPDF { $this->_out(sprintf('q %.4F 0 0 %.4F %.4F %.4F cm', $tData['scaleX'], $tData['scaleY'], $tData['tx'] * $this->k, $tData['ty'] * $this->k)); // Translate $this->_out(sprintf('%s%d Do Q', $this->tplprefix, $tplidx)); - // reset font in the outer graphic state - if ($this->FontFamily) { - $family = $this->FontFamily; - $this->FontFamily = ''; - $this->SetFont($family); - } - $this->lastUsedTemplateData = $tData; return array('w' => $_w, 'h' => $_h); @@ -236,7 +249,7 @@ class FPDF_TPL extends FPDF { * @return array The height and width of the template */ function getTemplateSize($tplidx, $_w = 0, $_h = 0) { - if (!$this->tpls[$tplidx]) + if (!isset($this->tpls[$tplidx])) return false; $tpl =& $this->tpls[$tplidx]; @@ -265,12 +278,6 @@ class FPDF_TPL extends FPDF { return call_user_func_array(array($this, 'TCPDF::SetFont'), $args); } - /** - * force the resetting of font changes in a template - */ - if ($this->_intpl) - $this->FontFamily = ''; - parent::SetFont($family, $style, $size); $fontkey = $this->FontFamily . $this->FontStyle; @@ -285,7 +292,11 @@ class FPDF_TPL extends FPDF { /** * See FPDF/TCPDF-Documentation ;-) */ - function Image($file, $x = null, $y = null, $w = 0, $h = 0, $type = '', $link = '') { + function Image( + $file, $x = '', $y = '', $w = 0, $h = 0, $type = '', $link = '', $align = '', $resize = false, + $dpi = 300, $palign = '', $ismask = false, $imgmask = false, $border = 0, $fitbox = false, + $hidden = false, $fitonpage = false, $alt = false, $altimgs = array() + ) { if (is_subclass_of($this, 'TCPDF')) { $args = func_get_args(); return call_user_func_array(array($this, 'TCPDF::Image'), $args); @@ -306,7 +317,7 @@ class FPDF_TPL extends FPDF { * * AddPage is not available when you're "in" a template. */ - function AddPage($orientation = '', $format = '') { + function AddPage($orientation = '', $format = '', $keepmargins = false, $tocpage = false) { if (is_subclass_of($this, 'TCPDF')) { $args = func_get_args(); return call_user_func_array(array($this, 'TCPDF::AddPage'), $args); @@ -321,7 +332,7 @@ class FPDF_TPL extends FPDF { /** * Preserve adding Links in Templates ...won't work */ - function Link($x, $y, $w, $h, $link) { + function Link($x, $y, $w, $h, $link, $spaces = 0) { if (is_subclass_of($this, 'TCPDF')) { $args = func_get_args(); return call_user_func_array(array($this, 'TCPDF::Link'), $args); From 0205848a0e09f3ccdf81e6af1199975713aefd23 Mon Sep 17 00:00:00 2001 From: aspangaro Date: Fri, 20 Feb 2015 05:21:18 +0100 Subject: [PATCH 161/173] Update FPDI library to 1.5.2 Contain FPDF_TPL natively --- COPYRIGHT | 3 +- .../includes/fpdfi/filters/FilterASCII85.php | 157 +- .../fpdfi/filters/FilterASCIIHexDecode.php | 52 + htdocs/includes/fpdfi/filters/FilterLZW.php | 278 +-- htdocs/includes/fpdfi/fpdf_tpl.php | 601 ++++--- htdocs/includes/fpdfi/fpdi.php | 544 +++--- htdocs/includes/fpdfi/fpdi2tcpdf_bridge.php | 167 -- htdocs/includes/fpdfi/fpdi_bridge.php | 215 +++ htdocs/includes/fpdfi/fpdi_pdf_parser.php | 420 ++--- htdocs/includes/fpdfi/pdf_context.php | 219 ++- htdocs/includes/fpdfi/pdf_parser.php | 1590 +++++++++-------- 11 files changed, 2391 insertions(+), 1855 deletions(-) create mode 100644 htdocs/includes/fpdfi/filters/FilterASCIIHexDecode.php delete mode 100644 htdocs/includes/fpdfi/fpdi2tcpdf_bridge.php create mode 100644 htdocs/includes/fpdfi/fpdi_bridge.php diff --git a/COPYRIGHT b/COPYRIGHT index 05651d8b0e4..8ce95782942 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -15,8 +15,7 @@ PHP libraries: AdoDb-Date 0.33 Modified BSD License Yes Date convertion (not into rpm package) ChromePHP 4.3.3 Apache Software License 2.0 Yes Return server log to chrome browser console CKEditor 4.3.3 LGPL-2.1+ Yes Editor WYSIWYG -FPDI 1.4.2 Apache Software License 2.0 Yes PDF templates management -FPDF_TPL 1.2.3 Apache Software License 2.0 Yes PDF templates management +FPDI 1.5.2 Apache Software License 2.0 Yes PDF templates management GeoIP 1.4 LGPL-2.1+ Yes Sample code to make geoip convert (not into deb package) NuSoap 0.9.5 LGPL 2.1+ Yes Library to develop SOAP Web services (not into rpm and deb package) odtPHP 1.0.1 GPL-2+ b Yes Library to build/edit ODT files diff --git a/htdocs/includes/fpdfi/filters/FilterASCII85.php b/htdocs/includes/fpdfi/filters/FilterASCII85.php index 01402ba1dc6..59bc845f3c9 100644 --- a/htdocs/includes/fpdfi/filters/FilterASCII85.php +++ b/htdocs/includes/fpdfi/filters/FilterASCII85.php @@ -1,8 +1,8 @@ ord('~'), + 'z' => ord('z'), + 'u' => ord('u'), + 'z' => ord('z'), + '!' => ord('!') + ); -if (!class_exists('FilterASCII85', false)) { + $out = ''; + $state = 0; + $chn = null; - class FilterASCII85 { - - function error($msg) { - die($msg); - } - - function decode($in) { - $out = ''; - $state = 0; - $chn = null; - - $l = strlen($in); - - for ($k = 0; $k < $l; ++$k) { - $ch = ord($in[$k]) & 0xff; - - if ($ch == ORD_tilde) { - break; - } - if (preg_match('/^\s$/',chr($ch))) { - continue; - } - if ($ch == ORD_z && $state == 0) { - $out .= chr(0) . chr(0) . chr(0) . chr(0); - continue; - } - if ($ch < ORD_exclmark || $ch > ORD_u) { - return $this->error('Illegal character in ASCII85Decode.'); - } - - $chn[$state++] = $ch - ORD_exclmark; - - if ($state == 5) { - $state = 0; - $r = 0; - for ($j = 0; $j < 5; ++$j) - $r = $r * 85 + $chn[$j]; - $out .= chr($r >> 24); - $out .= chr($r >> 16); - $out .= chr($r >> 8); - $out .= chr($r); - } + $l = strlen($in); + + for ($k = 0; $k < $l; ++$k) { + $ch = ord($in[$k]) & 0xff; + + if ($ch == $ord['~']) { + break; } - $r = 0; - - if ($state == 1) - return $this->error('Illegal length in ASCII85Decode.'); - if ($state == 2) { - $r = $chn[0] * 85 * 85 * 85 * 85 + ($chn[1]+1) * 85 * 85 * 85; - $out .= chr($r >> 24); + if (preg_match('/^\s$/',chr($ch))) { + continue; } - else if ($state == 3) { - $r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + ($chn[2]+1) * 85 * 85; - $out .= chr($r >> 24); - $out .= chr($r >> 16); + if ($ch == $ord['z'] && $state == 0) { + $out .= chr(0) . chr(0) . chr(0) . chr(0); + continue; } - else if ($state == 4) { - $r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + $chn[2] * 85 * 85 + ($chn[3]+1) * 85 ; + if ($ch < $ord['!'] || $ch > $ord['u']) { + throw new Exception('Illegal character in ASCII85Decode.'); + } + + $chn[$state++] = $ch - $ord['!']; + + if ($state == 5) { + $state = 0; + $r = 0; + for ($j = 0; $j < 5; ++$j) + $r = $r * 85 + $chn[$j]; $out .= chr($r >> 24); $out .= chr($r >> 16); $out .= chr($r >> 8); + $out .= chr($r); } - - return $out; } - - function encode($in) { - return $this->error("ASCII85 encoding not implemented."); + $r = 0; + + if ($state == 1) { + throw new Exception('Illegal length in ASCII85Decode.'); } + + if ($state == 2) { + $r = $chn[0] * 85 * 85 * 85 * 85 + ($chn[1]+1) * 85 * 85 * 85; + $out .= chr($r >> 24); + + } else if ($state == 3) { + $r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + ($chn[2]+1) * 85 * 85; + $out .= chr($r >> 24); + $out .= chr($r >> 16); + + } else if ($state == 4) { + $r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + $chn[2] * 85 * 85 + ($chn[3]+1) * 85 ; + $out .= chr($r >> 24); + $out .= chr($r >> 16); + $out .= chr($r >> 8); + } + + return $out; } -} + + /** + * NOT IMPLEMENTED + * + * @param string $in + * @return string + * @throws LogicException + */ + public function encode($in) + { + throw new LogicException("ASCII85 encoding not implemented."); + } +} \ No newline at end of file diff --git a/htdocs/includes/fpdfi/filters/FilterASCIIHexDecode.php b/htdocs/includes/fpdfi/filters/FilterASCIIHexDecode.php new file mode 100644 index 00000000000..4040302d32c --- /dev/null +++ b/htdocs/includes/fpdfi/filters/FilterASCIIHexDecode.php @@ -0,0 +1,52 @@ +')); + if ((strlen($data) % 2) == 1) { + $data .= '0'; + } + + return pack('H*', $data); + } + + /** + * Converts a string into ASCII hexadecimal representation. + * + * @param string $data The input string + * @param boolean $leaveEOD + * @return string + */ + public function encode($data, $leaveEOD = false) + { + return current(unpack('H*', $data)) . ($leaveEOD ? '' : '>'); + } +} \ No newline at end of file diff --git a/htdocs/includes/fpdfi/filters/FilterLZW.php b/htdocs/includes/fpdfi/filters/FilterLZW.php index 292461d248d..b4dfbe82be2 100644 --- a/htdocs/includes/fpdfi/filters/FilterLZW.php +++ b/htdocs/includes/fpdfi/filters/FilterLZW.php @@ -1,8 +1,8 @@ error('LZW flavour not supported.'); - } - - $this->initsTable(); - - $this->data = $data; - $this->dataLength = strlen($data); - - // Initialize pointers - $this->bytePointer = 0; - $this->bitPointer = 0; - - $this->nextData = 0; - $this->nextBits = 0; - - $oldCode = 0; - - $string = ''; - $uncompData = ''; - - while (($code = $this->getNextCode()) != 257) { - if ($code == 256) { - $this->initsTable(); - $code = $this->getNextCode(); - - if ($code == 257) { - break; - } - - $uncompData .= $this->sTable[$code]; + + $this->_initsTable(); + + $this->_data = $data; + $this->_dataLength = strlen($data); + + // Initialize pointers + $this->_bytePointer = 0; + $this->_bitPointer = 0; + + $this->_nextData = 0; + $this->_nextBits = 0; + + $oldCode = 0; + + $unCompData = ''; + + while (($code = $this->_getNextCode()) != 257) { + if ($code == 256) { + $this->_initsTable(); + $code = $this->_getNextCode(); + + if ($code == 257) { + break; + } + + if (!isset($this->_sTable[$code])) { + throw new Exception('Error while decompression LZW compressed data.'); + } + + $unCompData .= $this->_sTable[$code]; + $oldCode = $code; + + } else { + + if ($code < $this->_tIdx) { + $string = $this->_sTable[$code]; + $unCompData .= $string; + + $this->_addStringToTable($this->_sTable[$oldCode], $string[0]); $oldCode = $code; - } else { - - if ($code < $this->tIdx) { - $string = $this->sTable[$code]; - $uncompData .= $string; - - $this->addStringToTable($this->sTable[$oldCode], $string[0]); - $oldCode = $code; - } else { - $string = $this->sTable[$oldCode]; - $string = $string . $string[0]; - $uncompData .= $string; - - $this->addStringToTable($string); - $oldCode = $code; - } + $string = $this->_sTable[$oldCode]; + $string = $string . $string[0]; + $unCompData .= $string; + + $this->_addStringToTable($string); + $oldCode = $code; } } - - return $uncompData; } - - - /** - * Initialize the string table. - */ - function initsTable() { - $this->sTable = array(); - - for ($i = 0; $i < 256; $i++) - $this->sTable[$i] = chr($i); - - $this->tIdx = 258; - $this->bitsToGet = 9; - } - - /** - * Add a new string to the string table. - */ - function addStringToTable ($oldString, $newString='') { - $string = $oldString.$newString; - - // Add this new String to the table - $this->sTable[$this->tIdx++] = $string; - - if ($this->tIdx == 511) { - $this->bitsToGet = 10; - } else if ($this->tIdx == 1023) { - $this->bitsToGet = 11; - } else if ($this->tIdx == 2047) { - $this->bitsToGet = 12; - } - } - - // Returns the next 9, 10, 11 or 12 bits - function getNextCode() { - if ($this->bytePointer == $this->dataLength) { - return 257; - } - - $this->nextData = ($this->nextData << 8) | (ord($this->data[$this->bytePointer++]) & 0xff); - $this->nextBits += 8; - - if ($this->nextBits < $this->bitsToGet) { - $this->nextData = ($this->nextData << 8) | (ord($this->data[$this->bytePointer++]) & 0xff); - $this->nextBits += 8; - } - - $code = ($this->nextData >> ($this->nextBits - $this->bitsToGet)) & $this->andTable[$this->bitsToGet-9]; - $this->nextBits -= $this->bitsToGet; - - return $code; - } - - function encode($in) { - $this->error("LZW encoding not implemented."); + + return $unCompData; + } + + + /** + * Initialize the string table. + */ + protected function _initsTable() + { + $this->_sTable = array(); + + for ($i = 0; $i < 256; $i++) + $this->_sTable[$i] = chr($i); + + $this->_tIdx = 258; + $this->_bitsToGet = 9; + } + + /** + * Add a new string to the string table. + */ + protected function _addStringToTable($oldString, $newString = '') + { + $string = $oldString . $newString; + + // Add this new String to the table + $this->_sTable[$this->_tIdx++] = $string; + + if ($this->_tIdx == 511) { + $this->_bitsToGet = 10; + } else if ($this->_tIdx == 1023) { + $this->_bitsToGet = 11; + } else if ($this->_tIdx == 2047) { + $this->_bitsToGet = 12; } } -} + + /** + * Returns the next 9, 10, 11 or 12 bits + * + * @return int + */ + protected function _getNextCode() + { + if ($this->_bytePointer == $this->_dataLength) { + return 257; + } + + $this->_nextData = ($this->_nextData << 8) | (ord($this->_data[$this->_bytePointer++]) & 0xff); + $this->_nextBits += 8; + + if ($this->_nextBits < $this->_bitsToGet) { + $this->_nextData = ($this->_nextData << 8) | (ord($this->_data[$this->_bytePointer++]) & 0xff); + $this->_nextBits += 8; + } + + $code = ($this->_nextData >> ($this->_nextBits - $this->_bitsToGet)) & $this->_andTable[$this->_bitsToGet-9]; + $this->_nextBits -= $this->_bitsToGet; + + return $code; + } + + /** + * NOT IMPLEMENTED + * + * @param string $in + * @return string + * @throws LogicException + */ + public function encode($in) + { + throw new LogicException("LZW encoding not implemented."); + } +} \ No newline at end of file diff --git a/htdocs/includes/fpdfi/fpdf_tpl.php b/htdocs/includes/fpdfi/fpdf_tpl.php index 8482ba336ed..5da77aff0e0 100644 --- a/htdocs/includes/fpdfi/fpdf_tpl.php +++ b/htdocs/includes/fpdfi/fpdf_tpl.php @@ -1,8 +1,8 @@ Error('This method is only usable with FPDF. Use TCPDF methods startTemplate() instead.'); - return; - } - - if ($this->page <= 0) - $this->error("You have to add a page to fpdf first!"); + public function beginTemplate($x = null, $y = null, $w = null, $h = null) + { + if (is_subclass_of($this, 'TCPDF')) { + throw new LogicException('This method is only usable with FPDF. Use TCPDF methods startTemplate() instead.'); + } + + if ($this->page <= 0) { + throw new LogicException("You have to add at least a page first!"); + } if ($x == null) $x = 0; @@ -93,7 +106,7 @@ class FPDF_TPL extends FPDF { // Save settings $this->tpl++; - $tpl =& $this->tpls[$this->tpl]; + $tpl =& $this->_tpls[$this->tpl]; $tpl = array( 'o_x' => $this->x, 'o_y' => $this->y, @@ -116,41 +129,43 @@ class FPDF_TPL extends FPDF { ); $this->SetAutoPageBreak(false); - - // Define own high and width to calculate possitions correct + + // Define own high and width to calculate correct positions $this->h = $h; $this->w = $w; - $this->_intpl = true; + $this->_inTpl = true; $this->SetXY($x + $this->lMargin, $y + $this->tMargin); $this->SetRightMargin($this->w - $w + $this->rMargin); if ($this->CurrentFont) { - $fontkey = $this->FontFamily . $this->FontStyle; - $this->_res['tpl'][$this->tpl]['fonts'][$fontkey] =& $this->fonts[$fontkey]; - - $this->_out(sprintf('BT /F%d %.2f Tf ET', $this->CurrentFont['i'], $this->FontSizePt)); + $fontKey = $this->FontFamily . $this->FontStyle; + if ($fontKey) { + $this->_res['tpl'][$this->tpl]['fonts'][$fontKey] =& $this->fonts[$fontKey]; + $this->_out(sprintf('BT /F%d %.2F Tf ET', $this->CurrentFont['i'], $this->FontSizePt)); + } } - + return $this->tpl; } - + /** - * End Template + * End template. * - * This method ends a template and reset initiated variables on beginTemplate. + * This method ends a template and reset initiated variables collected in {@link beginTemplate()}. * - * @return mixed If a template is opened, the ID is returned. If not a false is returned. + * @return int|boolean If a template is opened, the id is returned. If not a false is returned. */ - function endTemplate() { - if (is_subclass_of($this, 'TCPDF')) { - $args = func_get_args(); - return call_user_func_array(array($this, 'TCPDF::endTemplate'), $args); + public function endTemplate() + { + if (is_subclass_of($this, 'TCPDF')) { + $args = func_get_args(); + return call_user_func_array(array($this, 'TCPDF::endTemplate'), $args); } - - if ($this->_intpl) { - $this->_intpl = false; - $tpl =& $this->tpls[$this->tpl]; + + if ($this->_inTpl) { + $this->_inTpl = false; + $tpl = $this->_tpls[$this->tpl]; $this->SetXY($tpl['o_x'], $tpl['o_y']); $this->tMargin = $tpl['o_tMargin']; $this->lMargin = $tpl['o_lMargin']; @@ -158,226 +173,285 @@ class FPDF_TPL extends FPDF { $this->h = $tpl['o_h']; $this->w = $tpl['o_w']; $this->SetAutoPageBreak($tpl['o_AutoPageBreak'], $tpl['o_bMargin']); - + $this->FontFamily = $tpl['o_FontFamily']; - $this->FontStyle = $tpl['o_FontStyle']; - $this->FontSizePt = $tpl['o_FontSizePt']; - $this->FontSize = $tpl['o_FontSize']; - - $fontkey = $this->FontFamily . $this->FontStyle; - if ($fontkey) - $this->CurrentFont =& $this->fonts[$fontkey]; - + $this->FontStyle = $tpl['o_FontStyle']; + $this->FontSizePt = $tpl['o_FontSizePt']; + $this->FontSize = $tpl['o_FontSize']; + + $fontKey = $this->FontFamily . $this->FontStyle; + if ($fontKey) + $this->CurrentFont =& $this->fonts[$fontKey]; + return $this->tpl; } else { return false; } } - + /** - * Use a Template in current Page or other Template + * Use a template in current page or other template. * * You can use a template in a page or in another template. - * You can give the used template a new size like you use the Image()-method. - * All parameters are optional. The width or height is calculated automaticaly + * You can give the used template a new size. + * All parameters are optional. The width or height is calculated automatically * if one is given. If no parameter is given the origin size as defined in - * beginTemplate() is used. + * {@link beginTemplate()} method is used. + * * The calculated or used width and height are returned as an array. * - * @param int $tplidx A valid template-Id - * @param int $_x The x-position - * @param int $_y The y-position - * @param int $_w The new width of the template - * @param int $_h The new height of the template - * @retrun array The height and width of the template + * @param int $tplIdx A valid template-id + * @param int $x The x-position + * @param int $y The y-position + * @param int $w The new width of the template + * @param int $h The new height of the template + * @return array The height and width of the template (array('w' => ..., 'h' => ...)) + * @throws LogicException|InvalidArgumentException */ - function useTemplate($tplidx, $_x = null, $_y = null, $_w = 0, $_h = 0) { - if ($this->page <= 0) - $this->error('You have to add a page first!'); - - if (!isset($this->tpls[$tplidx])) - $this->error('Template does not exist!'); - - if ($this->_intpl) { - $this->_res['tpl'][$this->tpl]['tpls'][$tplidx] =& $this->tpls[$tplidx]; + public function useTemplate($tplIdx, $x = null, $y = null, $w = 0, $h = 0) + { + if ($this->page <= 0) { + throw new LogicException('You have to add at least a page first!'); } - - $tpl =& $this->tpls[$tplidx]; - $w = $tpl['w']; - $h = $tpl['h']; - - if ($_x == null) - $_x = 0; - if ($_y == null) - $_y = 0; - - $_x += $tpl['x']; - $_y += $tpl['y']; - - $wh = $this->getTemplateSize($tplidx, $_w, $_h); - $_w = $wh['w']; - $_h = $wh['h']; - - $tData = array( + + if (!isset($this->_tpls[$tplIdx])) { + throw new InvalidArgumentException('Template does not exist!'); + } + + if ($this->_inTpl) { + $this->_res['tpl'][$this->tpl]['tpls'][$tplIdx] =& $this->_tpls[$tplIdx]; + } + + $tpl = $this->_tpls[$tplIdx]; + $_w = $tpl['w']; + $_h = $tpl['h']; + + if ($x == null) { + $x = 0; + } + + if ($y == null) { + $y = 0; + } + + $x += $tpl['x']; + $y += $tpl['y']; + + $wh = $this->getTemplateSize($tplIdx, $w, $h); + $w = $wh['w']; + $h = $wh['h']; + + $tplData = array( 'x' => $this->x, 'y' => $this->y, - 'w' => $_w, - 'h' => $_h, - 'scaleX' => ($_w / $w), - 'scaleY' => ($_h / $h), - 'tx' => $_x, - 'ty' => ($this->h - $_y - $_h), - 'lty' => ($this->h - $_y - $_h) - ($this->h - $h) * ($_h / $h) + 'w' => $w, + 'h' => $h, + 'scaleX' => ($w / $_w), + 'scaleY' => ($h / $_h), + 'tx' => $x, + 'ty' => ($this->h - $y - $h), + 'lty' => ($this->h - $y - $h) - ($this->h - $_h) * ($h / $_h) ); - - $this->_out(sprintf('q %.4F 0 0 %.4F %.4F %.4F cm', $tData['scaleX'], $tData['scaleY'], $tData['tx'] * $this->k, $tData['ty'] * $this->k)); // Translate - $this->_out(sprintf('%s%d Do Q', $this->tplprefix, $tplidx)); - $this->lastUsedTemplateData = $tData; - - return array('w' => $_w, 'h' => $_h); + $this->_out(sprintf('q %.4F 0 0 %.4F %.4F %.4F cm', + $tplData['scaleX'], $tplData['scaleY'], $tplData['tx'] * $this->k, $tplData['ty'] * $this->k) + ); // Translate + $this->_out(sprintf('%s%d Do Q', $this->tplPrefix, $tplIdx)); + + $this->lastUsedTemplateData = $tplData; + + return array('w' => $w, 'h' => $h); } - + /** - * Get The calculated Size of a Template + * Get the calculated size of a template. * * If one size is given, this method calculates the other one. * - * @param int $tplidx A valid template-Id - * @param int $_w The width of the template - * @param int $_h The height of the template - * @return array The height and width of the template + * @param int $tplIdx A valid template-id + * @param int $w The width of the template + * @param int $h The height of the template + * @return array The height and width of the template (array('w' => ..., 'h' => ...)) */ - function getTemplateSize($tplidx, $_w = 0, $_h = 0) { - if (!isset($this->tpls[$tplidx])) + public function getTemplateSize($tplIdx, $w = 0, $h = 0) + { + if (!isset($this->_tpls[$tplIdx])) return false; - $tpl =& $this->tpls[$tplidx]; - $w = $tpl['w']; - $h = $tpl['h']; - - if ($_w == 0 and $_h == 0) { - $_w = $w; - $_h = $h; + $tpl = $this->_tpls[$tplIdx]; + $_w = $tpl['w']; + $_h = $tpl['h']; + + if ($w == 0 && $h == 0) { + $w = $_w; + $h = $_h; } - if($_w == 0) - $_w = $_h * $w / $h; - if($_h == 0) - $_h = $_w * $h / $w; - - return array("w" => $_w, "h" => $_h); + if ($w == 0) + $w = $h * $_w / $_h; + if($h == 0) + $h = $w * $_h / $_w; + + return array("w" => $w, "h" => $h); } - + /** - * See FPDF/TCPDF-Documentation ;-) + * Sets the font used to print character strings. + * + * See FPDF/TCPDF documentation. + * + * @see http://fpdf.org/en/doc/setfont.htm + * @see http://www.tcpdf.org/doc/code/classTCPDF.html#afd56e360c43553830d543323e81bc045 */ - public function SetFont($family, $style = '', $size = 0) { + public function SetFont($family, $style = '', $size = null, $fontfile = '', $subset = 'default', $out = true) + { if (is_subclass_of($this, 'TCPDF')) { - $args = func_get_args(); - return call_user_func_array(array($this, 'TCPDF::SetFont'), $args); + $args = func_get_args(); + return call_user_func_array(array($this, 'TCPDF::SetFont'), $args); } - + parent::SetFont($family, $style, $size); - + $fontkey = $this->FontFamily . $this->FontStyle; - - if ($this->_intpl) { + + if ($this->_inTpl) { $this->_res['tpl'][$this->tpl]['fonts'][$fontkey] =& $this->fonts[$fontkey]; } else { $this->_res['page'][$this->page]['fonts'][$fontkey] =& $this->fonts[$fontkey]; } } - + /** - * See FPDF/TCPDF-Documentation ;-) + * Puts an image. + * + * See FPDF/TCPDF documentation. + * + * @see http://fpdf.org/en/doc/image.htm + * @see http://www.tcpdf.org/doc/code/classTCPDF.html#a714c2bee7d6b39d4d6d304540c761352 */ - function Image( - $file, $x = '', $y = '', $w = 0, $h = 0, $type = '', $link = '', $align = '', $resize = false, - $dpi = 300, $palign = '', $ismask = false, $imgmask = false, $border = 0, $fitbox = false, - $hidden = false, $fitonpage = false, $alt = false, $altimgs = array() - ) { + public function Image( + $file, $x = '', $y = '', $w = 0, $h = 0, $type = '', $link = '', $align = '', $resize = false, + $dpi = 300, $palign = '', $ismask = false, $imgmask = false, $border = 0, $fitbox = false, + $hidden = false, $fitonpage = false, $alt = false, $altimgs = array() + ) + { if (is_subclass_of($this, 'TCPDF')) { - $args = func_get_args(); - return call_user_func_array(array($this, 'TCPDF::Image'), $args); + $args = func_get_args(); + return call_user_func_array(array($this, 'TCPDF::Image'), $args); } - + $ret = parent::Image($file, $x, $y, $w, $h, $type, $link); - if ($this->_intpl) { + if ($this->_inTpl) { $this->_res['tpl'][$this->tpl]['images'][$file] =& $this->images[$file]; } else { $this->_res['page'][$this->page]['images'][$file] =& $this->images[$file]; } - + return $ret; } - + /** - * See FPDF-Documentation ;-) + * Adds a new page to the document. * - * AddPage is not available when you're "in" a template. + * See FPDF/TCPDF documentation. + * + * This method cannot be used if you'd started a template. + * + * @see http://fpdf.org/en/doc/addpage.htm + * @see http://www.tcpdf.org/doc/code/classTCPDF.html#a5171e20b366b74523709d84c349c1ced */ - function AddPage($orientation = '', $format = '', $keepmargins = false, $tocpage = false) { - if (is_subclass_of($this, 'TCPDF')) { - $args = func_get_args(); - return call_user_func_array(array($this, 'TCPDF::AddPage'), $args); + public function AddPage($orientation = '', $format = '', $keepmargins = false, $tocpage = false) + { + if (is_subclass_of($this, 'TCPDF')) { + $args = func_get_args(); + return call_user_func_array(array($this, 'TCPDF::AddPage'), $args); } - - if ($this->_intpl) - $this->Error('Adding pages in templates isn\'t possible!'); - + + if ($this->_inTpl) { + throw new LogicException('Adding pages in templates is not possible!'); + } + parent::AddPage($orientation, $format); } /** - * Preserve adding Links in Templates ...won't work + * Puts a link on a rectangular area of the page. + * + * Overwritten because adding links in a template will not work. + * + * @see http://fpdf.org/en/doc/link.htm + * @see http://www.tcpdf.org/doc/code/classTCPDF.html#ab87bf1826384fbfe30eb499d42f1d994 */ - function Link($x, $y, $w, $h, $link, $spaces = 0) { + public function Link($x, $y, $w, $h, $link, $spaces = 0) + { if (is_subclass_of($this, 'TCPDF')) { - $args = func_get_args(); - return call_user_func_array(array($this, 'TCPDF::Link'), $args); + $args = func_get_args(); + return call_user_func_array(array($this, 'TCPDF::Link'), $args); } - - if ($this->_intpl) - $this->Error('Using links in templates aren\'t possible!'); - + + if ($this->_inTpl) { + throw new LogicException('Using links in templates is not posible!'); + } + parent::Link($x, $y, $w, $h, $link); } - - function AddLink() { - if (is_subclass_of($this, 'TCPDF')) { - $args = func_get_args(); - return call_user_func_array(array($this, 'TCPDF::AddLink'), $args); + + /** + * Creates a new internal link and returns its identifier. + * + * Overwritten because adding links in a template will not work. + * + * @see http://fpdf.org/en/doc/addlink.htm + * @see http://www.tcpdf.org/doc/code/classTCPDF.html#a749522038ed7786c3e1701435dcb891e + */ + public function AddLink() + { + if (is_subclass_of($this, 'TCPDF')) { + $args = func_get_args(); + return call_user_func_array(array($this, 'TCPDF::AddLink'), $args); } - - if ($this->_intpl) - $this->Error('Adding links in templates aren\'t possible!'); + + if ($this->_inTpl) { + throw new LogicException('Adding links in templates is not possible!'); + } + return parent::AddLink(); } - - function SetLink($link, $y = 0, $page = -1) { - if (is_subclass_of($this, 'TCPDF')) { - $args = func_get_args(); - return call_user_func_array(array($this, 'TCPDF::SetLink'), $args); + + /** + * Defines the page and position a link points to. + * + * Overwritten because adding links in a template will not work. + * + * @see http://fpdf.org/en/doc/setlink.htm + * @see http://www.tcpdf.org/doc/code/classTCPDF.html#ace5be60e7857953ea5e2b89cb90df0ae + */ + public function SetLink($link, $y = 0, $page = -1) + { + if (is_subclass_of($this, 'TCPDF')) { + $args = func_get_args(); + return call_user_func_array(array($this, 'TCPDF::SetLink'), $args); } - - if ($this->_intpl) - $this->Error('Setting links in templates aren\'t possible!'); + + if ($this->_inTpl) { + throw new LogicException('Setting links in templates is not possible!'); + } + parent::SetLink($link, $y, $page); } - - /** - * Private Method that writes the form xobjects - */ - function _putformxobjects() { - $filter=($this->compress) ? '/Filter /FlateDecode ' : ''; - reset($this->tpls); - foreach($this->tpls AS $tplidx => $tpl) { - $p=($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer']; - $this->_newobj(); - $this->tpls[$tplidx]['n'] = $this->n; - $this->_out('<<'.$filter.'/Type /XObject'); + /** + * Writes the form XObjects to the PDF document. + */ + protected function _putformxobjects() + { + $filter=($this->compress) ? '/Filter /FlateDecode ' : ''; + reset($this->_tpls); + + foreach($this->_tpls AS $tplIdx => $tpl) { + $this->_newobj(); + $this->_tpls[$tplIdx]['n'] = $this->n; + $this->_out('<<'.$filter.'/Type /XObject'); $this->_out('/Subtype /Form'); $this->_out('/FormType 1'); $this->_out(sprintf('/BBox [%.2F %.2F %.2F %.2F]', @@ -390,69 +464,90 @@ class FPDF_TPL extends FPDF { // ury ($tpl['h'] - $tpl['y']) * $this->k )); - + if ($tpl['x'] != 0 || $tpl['y'] != 0) { $this->_out(sprintf('/Matrix [1 0 0 1 %.5F %.5F]', - -$tpl['x'] * $this->k * 2, $tpl['y'] * $this->k * 2 + -$tpl['x'] * $this->k * 2, $tpl['y'] * $this->k * 2 )); } - - $this->_out('/Resources '); + $this->_out('/Resources '); $this->_out('<_res['tpl'][$tplidx]['fonts']) && count($this->_res['tpl'][$tplidx]['fonts'])) { - $this->_out('/Font <<'); - foreach($this->_res['tpl'][$tplidx]['fonts'] as $font) - $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R'); - $this->_out('>>'); + + if (isset($this->_res['tpl'][$tplIdx])) { + $res = $this->_res['tpl'][$tplIdx]; + if (isset($res['fonts']) && count($res['fonts'])) { + $this->_out('/Font <<'); + + foreach($res['fonts'] as $font) { + $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R'); + } + + $this->_out('>>'); + } + + if(isset($res['images']) || isset($res['tpls'])) { + $this->_out('/XObject <<'); + + if (isset($res['images'])) { + foreach($res['images'] as $image) + $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R'); + } + + if (isset($res['tpls'])) { + foreach($res['tpls'] as $i => $_tpl) + $this->_out($this->tplPrefix . $i . ' ' . $_tpl['n'] . ' 0 R'); + } + + $this->_out('>>'); + } } - if(isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images']) || - isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) - { - $this->_out('/XObject <<'); - if (isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images'])) { - foreach($this->_res['tpl'][$tplidx]['images'] as $image) - $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R'); - } - if (isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) { - foreach($this->_res['tpl'][$tplidx]['tpls'] as $i => $tpl) - $this->_out($this->tplprefix . $i . ' ' . $tpl['n'] . ' 0 R'); - } - $this->_out('>>'); - } - $this->_out('>>'); - - $this->_out('/Length ' . strlen($p) . ' >>'); - $this->_putstream($p); - $this->_out('endobj'); + + $this->_out('>>'); + + $buffer = ($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer']; + $this->_out('/Length ' . strlen($buffer) . ' >>'); + $this->_putstream($buffer); + $this->_out('endobj'); } } - + /** - * Overwritten to add _putformxobjects() after _putimages() + * Output images. * + * Overwritten to add {@link _putformxobjects()} after _putimages(). */ - function _putimages() { + public function _putimages() + { parent::_putimages(); $this->_putformxobjects(); } - - function _putxobjectdict() { + + /** + * Writes the references of XObject resources to the document. + * + * Overwritten to add the the templates to the XObject resource dictionary. + */ + public function _putxobjectdict() + { parent::_putxobjectdict(); - - if (count($this->tpls)) { - foreach($this->tpls as $tplidx => $tpl) { - $this->_out(sprintf('%s%d %d 0 R', $this->tplprefix, $tplidx, $tpl['n'])); - } + + foreach($this->_tpls as $tplIdx => $tpl) { + $this->_out(sprintf('%s%d %d 0 R', $this->tplPrefix, $tplIdx, $tpl['n'])); } } /** - * Private Method + * Writes bytes to the resulting document. + * + * Overwritten to delegate the data to the template buffer. + * + * @param string $s */ - function _out($s) { - if ($this->state == 2 && $this->_intpl) { - $this->tpls[$this->tpl]['buffer'] .= $s . "\n"; + public function _out($s) + { + if ($this->state == 2 && $this->_inTpl) { + $this->_tpls[$this->tpl]['buffer'] .= $s . "\n"; } else { parent::_out($s); } diff --git a/htdocs/includes/fpdfi/fpdi.php b/htdocs/includes/fpdfi/fpdi.php index f6ba91f96de..957c50531e6 100644 --- a/htdocs/includes/fpdfi/fpdi.php +++ b/htdocs/includes/fpdfi/fpdi.php @@ -1,8 +1,8 @@ current_filename = $filename; + public function setSourceFile($filename) + { + $_filename = realpath($filename); + if (false !== $_filename) + $filename = $_filename; + + $this->currentFilename = $filename; - if (!isset($this->parsers[$filename])) + if (!isset($this->parsers[$filename])) { $this->parsers[$filename] = $this->_getPdfParser($filename); - $this->current_parser =& $this->parsers[$filename]; + $this->setPdfVersion( + max($this->getPdfVersion(), $this->parsers[$filename]->getPdfVersion()) + ); + } + + $this->currentParser =& $this->parsers[$filename]; return $this->parsers[$filename]->getPageCount(); } @@ -99,53 +122,80 @@ class FPDI extends FPDF_TPL { * @param string $filename * @return fpdi_pdf_parser */ - function _getPdfParser($filename) { - return new fpdi_pdf_parser($filename, $this); + protected function _getPdfParser($filename) + { + require_once('fpdi_pdf_parser.php'); + return new fpdi_pdf_parser($filename); } /** - * Get the current PDF version + * Get the current PDF version. * * @return string */ - function getPDFVersion() { + public function getPdfVersion() + { return $this->PDFVersion; } - /** - * Set the PDF version + /** + * Set the PDF version. * - * @return string + * @param string $version */ - function setPDFVersion($version = '1.3') { - $this->PDFVersion = $version; - } + public function setPdfVersion($version = '1.3') + { + $this->PDFVersion = sprintf('%.1F', $version); + } /** - * Import a page + * Import a page. * - * @param int $pageno pagenumber - * @return int Index of imported page - to use with fpdf_tpl::useTemplate() + * The second parameter defines the bounding box that should be used to transform the page into a + * form XObject. + * + * Following values are available: MediaBox, CropBox, BleedBox, TrimBox, ArtBox. + * If a box is not especially defined its default box will be used: + * + *
    + *
  • CropBox: Default -> MediaBox
  • + *
  • BleedBox: Default -> CropBox
  • + *
  • TrimBox: Default -> CropBox
  • + *
  • ArtBox: Default -> CropBox
  • + *
+ * + * It is possible to get the used page box by the {@link getLastUsedPageBox()} method. + * + * @param int $pageNo The page number + * @param string $boxName The boundary box to use when transforming the page into a form XObject + * @param boolean $groupXObject Define the form XObject as a group XObject to support transparency (if used) + * @return int An id of the imported page/template to use with e.g. fpdf_tpl::useTemplate() + * @throws LogicException|InvalidArgumentException + * @see getLastUsedPageBox() */ - function importPage($pageno, $boxName = '/CropBox') { - if ($this->_intpl) { - return $this->error('Please import the desired pages before creating a new template.'); + public function importPage($pageNo, $boxName = 'CropBox', $groupXObject = true) + { + if ($this->_inTpl) { + throw new LogicException('Please import the desired pages before creating a new template.'); } - $fn = $this->current_filename; - - // check if page already imported - $pageKey = $fn . '-' . ((int)$pageno) . $boxName; - if (isset($this->_importedPages[$pageKey])) - return $this->_importedPages[$pageKey]; - - $parser =& $this->parsers[$fn]; - $parser->setPageno($pageno); + $fn = $this->currentFilename; + $boxName = '/' . ltrim($boxName, '/'); - if (!in_array($boxName, $parser->availableBoxes)) - return $this->Error(sprintf('Unknown box: %s', $boxName)); + // check if page already imported + $pageKey = $fn . '-' . ((int)$pageNo) . $boxName; + if (isset($this->_importedPages[$pageKey])) { + return $this->_importedPages[$pageKey]; + } + + $parser = $this->parsers[$fn]; + $parser->setPageNo($pageNo); + + if (!in_array($boxName, $parser->availableBoxes)) { + throw new InvalidArgumentException(sprintf('Unknown box: %s', $boxName)); + } - $pageboxes = $parser->getPageBoxes($pageno, $this->k); + $pageBoxes = $parser->getPageBoxes($pageNo, $this->k); /** * MediaBox @@ -154,35 +204,39 @@ class FPDI extends FPDF_TPL { * TrimBox: Default -> CropBox * ArtBox: Default -> CropBox */ - if (!isset($pageboxes[$boxName]) && ($boxName == '/BleedBox' || $boxName == '/TrimBox' || $boxName == '/ArtBox')) + if (!isset($pageBoxes[$boxName]) && ($boxName == '/BleedBox' || $boxName == '/TrimBox' || $boxName == '/ArtBox')) $boxName = '/CropBox'; - if (!isset($pageboxes[$boxName]) && $boxName == '/CropBox') + if (!isset($pageBoxes[$boxName]) && $boxName == '/CropBox') $boxName = '/MediaBox'; - if (!isset($pageboxes[$boxName])) + if (!isset($pageBoxes[$boxName])) return false; $this->lastUsedPageBox = $boxName; - $box = $pageboxes[$boxName]; + $box = $pageBoxes[$boxName]; $this->tpl++; - $this->tpls[$this->tpl] = array(); - $tpl =& $this->tpls[$this->tpl]; - $tpl['parser'] =& $parser; + $this->_tpls[$this->tpl] = array(); + $tpl =& $this->_tpls[$this->tpl]; + $tpl['parser'] = $parser; $tpl['resources'] = $parser->getPageResources(); $tpl['buffer'] = $parser->getContent(); $tpl['box'] = $box; - + $tpl['groupXObject'] = $groupXObject; + if ($groupXObject) { + $this->setPdfVersion(max($this->getPdfVersion(), 1.4)); + } + // To build an array that can be used by PDF_TPL::useTemplate() - $this->tpls[$this->tpl] = array_merge($this->tpls[$this->tpl], $box); + $this->_tpls[$this->tpl] = array_merge($this->_tpls[$this->tpl], $box); - // An imported page will start at 0,0 everytime. Translation will be set in _putformxobjects() + // An imported page will start at 0,0 all the time. Translation will be set in _putformxobjects() $tpl['x'] = 0; $tpl['y'] = 0; // handle rotated pages - $rotation = $parser->getPageRotation($pageno); + $rotation = $parser->getPageRotation($pageNo); $tpl['_rotationAngle'] = 0; if (isset($rotation[1]) && ($angle = $rotation[1] % 360) != 0) { $steps = $angle / 90; @@ -204,18 +258,41 @@ class FPDI extends FPDF_TPL { } /** - * Returns the last used page box + * Returns the last used page boundary box. * - * @return string + * @return string The used boundary box: MediaBox, CropBox, BleedBox, TrimBox or ArtBox */ - function getLastUsedPageBox() { + public function getLastUsedPageBox() + { return $this->lastUsedPageBox; } - - - function useTemplate($tplidx, $_x = null, $_y = null, $_w = 0, $_h = 0, $adjustPageSize = false) { - if ($adjustPageSize == true && is_null($_x) && is_null($_y)) { - $size = $this->getTemplateSize($tplidx, $_w, $_h); + + /** + * Use a template or imported page in current page or other template. + * + * You can use a template in a page or in another template. + * You can give the used template a new size. All parameters are optional. + * The width or height is calculated automatically if one is given. If no + * parameter is given the origin size as defined in beginTemplate() or of + * the imported page is used. + * + * The calculated or used width and height are returned as an array. + * + * @param int $tplIdx A valid template-id + * @param int $x The x-position + * @param int $y The y-position + * @param int $w The new width of the template + * @param int $h The new height of the template + * @param boolean $adjustPageSize If set to true the current page will be resized to fit the dimensions + * of the template + * + * @return array The height and width of the template (array('w' => ..., 'h' => ...)) + * @throws LogicException|InvalidArgumentException + */ + public function useTemplate($tplIdx, $x = null, $y = null, $w = 0, $h = 0, $adjustPageSize = false) + { + if ($adjustPageSize == true && is_null($x) && is_null($y)) { + $size = $this->getTemplateSize($tplIdx, $w, $h); $orientation = $size['w'] > $size['h'] ? 'L' : 'P'; $size = array($size['w'], $size['h']); @@ -224,22 +301,21 @@ class FPDI extends FPDF_TPL { } else { $size = $this->_getpagesize($size); - if($orientation!=$this->CurOrientation || $size[0]!=$this->CurPageSize[0] || $size[1]!=$this->CurPageSize[1]) - { + if($orientation != $this->CurOrientation || + $size[0] != $this->CurPageSize[0] || + $size[1] != $this->CurPageSize[1] + ) { // New size or orientation - if($orientation=='P') - { + if ($orientation=='P') { $this->w = $size[0]; $this->h = $size[1]; - } - else - { + } else { $this->w = $size[1]; $this->h = $size[0]; } - $this->wPt = $this->w*$this->k; - $this->hPt = $this->h*$this->k; - $this->PageBreakTrigger = $this->h-$this->bMargin; + $this->wPt = $this->w * $this->k; + $this->hPt = $this->h * $this->k; + $this->PageBreakTrigger = $this->h - $this->bMargin; $this->CurOrientation = $orientation; $this->CurPageSize = $size; $this->PageSizes[$this->page] = array($this->wPt, $this->hPt); @@ -248,54 +324,57 @@ class FPDI extends FPDF_TPL { } $this->_out('q 0 J 1 w 0 j 0 G 0 g'); // reset standard values - $s = parent::useTemplate($tplidx, $_x, $_y, $_w, $_h); + $size = parent::useTemplate($tplIdx, $x, $y, $w, $h); $this->_out('Q'); - return $s; + return $size; } /** - * Private method, that rebuilds all needed objects of source files + * Copy all imported objects to the resulting document. */ - function _putimportedobjects() { - if (is_array($this->parsers) && count($this->parsers) > 0) { - foreach($this->parsers AS $filename => $p) { - $this->current_parser =& $this->parsers[$filename]; - if (isset($this->_obj_stack[$filename]) && is_array($this->_obj_stack[$filename])) { - while(($n = key($this->_obj_stack[$filename])) !== null) { - $nObj = $this->current_parser->pdf_resolve_object($this->current_parser->c, $this->_obj_stack[$filename][$n][1]); - - $this->_newobj($this->_obj_stack[$filename][$n][0]); - - if ($nObj[0] == PDF_TYPE_STREAM) { - $this->pdf_write_value($nObj); - } else { - $this->pdf_write_value($nObj[1]); - } - - $this->_out('endobj'); - $this->_obj_stack[$filename][$n] = null; // free memory - unset($this->_obj_stack[$filename][$n]); - reset($this->_obj_stack[$filename]); - } + protected function _putimportedobjects() + { + foreach($this->parsers AS $filename => $p) { + $this->currentParser =& $p; + if (!isset($this->_objStack[$filename]) || !is_array($this->_objStack[$filename])) { + continue; + } + while(($n = key($this->_objStack[$filename])) !== null) { + try { + $nObj = $this->currentParser->resolveObject($this->_objStack[$filename][$n][1]); + } catch (Exception $e) { + $nObj = array(pdf_parser::TYPE_OBJECT, pdf_parser::TYPE_NULL); } + + $this->_newobj($this->_objStack[$filename][$n][0]); + + if ($nObj[0] == pdf_parser::TYPE_STREAM) { + $this->_writeValue($nObj); + } else { + $this->_writeValue($nObj[1]); + } + + $this->_out("\nendobj"); + $this->_objStack[$filename][$n] = null; // free memory + unset($this->_objStack[$filename][$n]); + reset($this->_objStack[$filename]); } } } - - + /** - * Private Method that writes the form xobjects + * Writes the form XObjects to the PDF document. */ - function _putformxobjects() { - $filter=($this->compress) ? '/Filter /FlateDecode ' : ''; - reset($this->tpls); - foreach($this->tpls AS $tplidx => $tpl) { - $p=($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer']; - $this->_newobj(); - $cN = $this->n; // TCPDF/Protection: rem current "n" + protected function _putformxobjects() + { + $filter = ($this->compress) ? '/Filter /FlateDecode ' : ''; + reset($this->_tpls); + foreach($this->_tpls AS $tplIdx => $tpl) { + $this->_newobj(); + $currentN = $this->n; // TCPDF/Protection: rem current "n" - $this->tpls[$tplidx]['n'] = $this->n; + $this->_tpls[$tplIdx]['n'] = $this->n; $this->_out('<<' . $filter . '/Type /XObject'); $this->_out('/Subtype /Form'); $this->_out('/FormType 1'); @@ -318,8 +397,8 @@ class FPDI extends FPDF_TPL { if ($tpl['_rotationAngle'] <> 0) { $angle = $tpl['_rotationAngle'] * M_PI/180; - $c=cos($angle); - $s=sin($angle); + $c = cos($angle); + $s = sin($angle); switch($tpl['_rotationAngle']) { case -90: @@ -353,87 +432,107 @@ class FPDI extends FPDF_TPL { $this->_out('/Resources '); if (isset($tpl['resources'])) { - $this->current_parser =& $tpl['parser']; - $this->pdf_write_value($tpl['resources']); // "n" will be changed + $this->currentParser = $tpl['parser']; + $this->_writeValue($tpl['resources']); // "n" will be changed } else { + $this->_out('<_res['tpl'][$tplidx]['fonts']) && count($this->_res['tpl'][$tplidx]['fonts'])) { - $this->_out('/Font <<'); - foreach($this->_res['tpl'][$tplidx]['fonts'] as $font) - $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R'); - $this->_out('>>'); - } - if(isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images']) || - isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) - { - $this->_out('/XObject <<'); - if (isset($this->_res['tpl'][$tplidx]['images']) && count($this->_res['tpl'][$tplidx]['images'])) { - foreach($this->_res['tpl'][$tplidx]['images'] as $image) - $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R'); + if (isset($this->_res['tpl'][$tplIdx])) { + $res = $this->_res['tpl'][$tplIdx]; + + if (isset($res['fonts']) && count($res['fonts'])) { + $this->_out('/Font <<'); + foreach ($res['fonts'] as $font) + $this->_out('/F' . $font['i'] . ' ' . $font['n'] . ' 0 R'); + $this->_out('>>'); } - if (isset($this->_res['tpl'][$tplidx]['tpls']) && count($this->_res['tpl'][$tplidx]['tpls'])) { - foreach($this->_res['tpl'][$tplidx]['tpls'] as $i => $tpl) - $this->_out($this->tplprefix . $i . ' ' . $tpl['n'] . ' 0 R'); + if (isset($res['images']) && count($res['images']) || + isset($res['tpls']) && count($res['tpls'])) + { + $this->_out('/XObject <<'); + if (isset($res['images'])) { + foreach ($res['images'] as $image) + $this->_out('/I' . $image['i'] . ' ' . $image['n'] . ' 0 R'); + } + if (isset($res['tpls'])) { + foreach ($res['tpls'] as $i => $_tpl) + $this->_out($this->tplPrefix . $i . ' ' . $_tpl['n'] . ' 0 R'); + } + $this->_out('>>'); } $this->_out('>>'); - } - $this->_out('>>'); + } } - $nN = $this->n; // TCPDF: rem new "n" - $this->n = $cN; // TCPDF: reset to current "n" + if (isset($tpl['groupXObject']) && $tpl['groupXObject']) { + $this->_out('/Group <>'); + } + + $newN = $this->n; // TCPDF: rem new "n" + $this->n = $currentN; // TCPDF: reset to current "n" + + $buffer = ($this->compress) ? gzcompress($tpl['buffer']) : $tpl['buffer']; + if (is_subclass_of($this, 'TCPDF')) { - $p = $this->_getrawstream($p); - $this->_out('/Length ' . strlen($p) . ' >>'); - $this->_out("stream\n" . $p . "\nendstream"); + $buffer = $this->_getrawstream($buffer); + $this->_out('/Length ' . strlen($buffer) . ' >>'); + $this->_out("stream\n" . $buffer . "\nendstream"); } else { - $this->_out('/Length ' . strlen($p) . ' >>'); - $this->_putstream($p); + $this->_out('/Length ' . strlen($buffer) . ' >>'); + $this->_putstream($buffer); } $this->_out('endobj'); - $this->n = $nN; // TCPDF: reset to new "n" + $this->n = $newN; // TCPDF: reset to new "n" } $this->_putimportedobjects(); } /** + * Creates and optionally write the object definition to the document. + * * Rewritten to handle existing own defined objects + * + * @param bool $objId + * @param bool $onlyNewObj + * @return bool|int */ - function _newobj($obj_id = false, $onlynewobj = false) { - if (!$obj_id) { - $obj_id = ++$this->n; + public function _newobj($objId = false, $onlyNewObj = false) + { + if (!$objId) { + $objId = ++$this->n; } //Begin a new object - if (!$onlynewobj) { - $this->offsets[$obj_id] = is_subclass_of($this, 'TCPDF') ? $this->bufferlen : strlen($this->buffer); - $this->_out($obj_id . ' 0 obj'); - $this->_current_obj_id = $obj_id; // for later use with encryption + if (!$onlyNewObj) { + $this->offsets[$objId] = is_subclass_of($this, 'TCPDF') ? $this->bufferlen : strlen($this->buffer); + $this->_out($objId . ' 0 obj'); + $this->_currentObjId = $objId; // for later use with encryption } - return $obj_id; + return $objId; } /** - * Writes a value + * Writes a PDF value to the resulting document. + * * Needed to rebuild the source document * * @param mixed $value A PDF-Value. Structure of values see cases in this method */ - function pdf_write_value(&$value) + protected function _writeValue(&$value) { if (is_subclass_of($this, 'TCPDF')) { - parent::pdf_write_value($value); + parent::_prepareValue($value); } switch ($value[0]) { - case PDF_TYPE_TOKEN: + case pdf_parser::TYPE_TOKEN: $this->_straightOut($value[1] . ' '); break; - case PDF_TYPE_NUMERIC: - case PDF_TYPE_REAL: + case pdf_parser::TYPE_NUMERIC: + case pdf_parser::TYPE_REAL: if (is_float($value[1]) && $value[1] != 0) { $this->_straightOut(rtrim(rtrim(sprintf('%F', $value[1]), '0'), '.') . ' '); } else { @@ -441,20 +540,20 @@ class FPDI extends FPDF_TPL { } break; - case PDF_TYPE_ARRAY: + case pdf_parser::TYPE_ARRAY: // An array. Output the proper // structure and move on. $this->_straightOut('['); for ($i = 0; $i < count($value[1]); $i++) { - $this->pdf_write_value($value[1][$i]); + $this->_writeValue($value[1][$i]); } $this->_out(']'); break; - case PDF_TYPE_DICTIONARY: + case pdf_parser::TYPE_DICTIONARY: // A dictionary. $this->_straightOut('<<'); @@ -463,55 +562,54 @@ class FPDI extends FPDF_TPL { while (list($k, $v) = each($value[1])) { $this->_straightOut($k . ' '); - $this->pdf_write_value($v); + $this->_writeValue($v); } $this->_straightOut('>>'); break; - case PDF_TYPE_OBJREF: + case pdf_parser::TYPE_OBJREF: // An indirect object reference // Fill the object stack if needed - $cpfn =& $this->current_parser->filename; - - if (!isset($this->_don_obj_stack[$cpfn][$value[1]])) { + $cpfn =& $this->currentParser->filename; + if (!isset($this->_doneObjStack[$cpfn][$value[1]])) { $this->_newobj(false, true); - $this->_obj_stack[$cpfn][$value[1]] = array($this->n, $value); - $this->_don_obj_stack[$cpfn][$value[1]] = array($this->n, $value); // Value is maybee obsolete!!! + $this->_objStack[$cpfn][$value[1]] = array($this->n, $value); + $this->_doneObjStack[$cpfn][$value[1]] = array($this->n, $value); } - $objid = $this->_don_obj_stack[$cpfn][$value[1]][0]; + $objId = $this->_doneObjStack[$cpfn][$value[1]][0]; - $this->_out($objid . ' 0 R'); + $this->_out($objId . ' 0 R'); break; - case PDF_TYPE_STRING: + case pdf_parser::TYPE_STRING: // A string. $this->_straightOut('(' . $value[1] . ')'); break; - case PDF_TYPE_STREAM: + case pdf_parser::TYPE_STREAM: // A stream. First, output the // stream dictionary, then the // stream data itself. - $this->pdf_write_value($value[1]); + $this->_writeValue($value[1]); $this->_out('stream'); $this->_out($value[2][1]); - $this->_out('endstream'); + $this->_straightOut("endstream"); break; - case PDF_TYPE_HEX: + case pdf_parser::TYPE_HEX: $this->_straightOut('<' . $value[1] . '>'); break; - case PDF_TYPE_BOOLEAN: + case pdf_parser::TYPE_BOOLEAN: $this->_straightOut($value[1] ? 'true ' : 'false '); break; - case PDF_TYPE_NULL: + case pdf_parser::TYPE_NULL: // The null object. $this->_straightOut('null '); @@ -521,51 +619,77 @@ class FPDI extends FPDF_TPL { /** - * Modified so not each call will add a newline to the output. + * Modified _out() method so not each call will add a newline to the output. */ - function _straightOut($s) { + protected function _straightOut($s) + { if (!is_subclass_of($this, 'TCPDF')) { - if($this->state==2) + if ($this->state == 2) { $this->pages[$this->page] .= $s; - else + } else { $this->buffer .= $s; + } + } else { if ($this->state == 2) { - if (isset($this->footerlen[$this->page]) AND ($this->footerlen[$this->page] > 0)) { + if ($this->inxobj) { + // we are inside an XObject template + $this->xobjects[$this->xobjid]['outdata'] .= $s; + } else if ((!$this->InFooter) AND isset($this->footerlen[$this->page]) AND ($this->footerlen[$this->page] > 0)) { // puts data before page footer - $page = substr($this->getPageBuffer($this->page), 0, -$this->footerlen[$this->page]); - $footer = substr($this->getPageBuffer($this->page), -$this->footerlen[$this->page]); - $this->setPageBuffer($this->page, $page . ' ' . $s . "\n" . $footer); + $pagebuff = $this->getPageBuffer($this->page); + $page = substr($pagebuff, 0, -$this->footerlen[$this->page]); + $footer = substr($pagebuff, -$this->footerlen[$this->page]); + $this->setPageBuffer($this->page, $page . $s . $footer); + // update footer position + $this->footerpos[$this->page] += strlen($s); } else { + // set page data $this->setPageBuffer($this->page, $s, true); } - } else { + } else if ($this->state > 0) { + // set general data $this->setBuffer($s); } } } /** - * rewritten to close opened parsers + * Ends the document * + * Overwritten to close opened parsers */ - function _enddoc() { + public function _enddoc() + { parent::_enddoc(); $this->_closeParsers(); } /** - * close all files opened by parsers + * Close all files opened by parsers. + * + * @return boolean */ - function _closeParsers() { - if ($this->state > 2 && count($this->parsers) > 0) { - foreach ($this->parsers as $k => $_){ - $this->parsers[$k]->closeFile(); - $this->parsers[$k] = null; - unset($this->parsers[$k]); - } + protected function _closeParsers() + { + if ($this->state > 2) { + $this->cleanUp(); return true; } + return false; } + + /** + * Removes cycled references and closes the file handles of the parser objects. + */ + public function cleanUp() + { + while (($parser = array_pop($this->parsers)) !== null) { + /** + * @var fpdi_pdf_parser $parser + */ + $parser->closeFile(); + } + } } \ No newline at end of file diff --git a/htdocs/includes/fpdfi/fpdi2tcpdf_bridge.php b/htdocs/includes/fpdfi/fpdi2tcpdf_bridge.php deleted file mode 100644 index 8a031a38c69..00000000000 --- a/htdocs/includes/fpdfi/fpdi2tcpdf_bridge.php +++ /dev/null @@ -1,167 +0,0 @@ -_out($this->_getstream($s)); - } - - function _getxobjectdict() { - $out = parent::_getxobjectdict(); - if (count($this->tpls)) { - foreach($this->tpls as $tplidx => $tpl) { - $out .= sprintf('%s%d %d 0 R', $this->tplprefix, $tplidx, $tpl['n']); - } - } - - return $out; - } - - /** - * Encryption of imported data by FPDI - * - * @param array $value - */ - function pdf_write_value(&$value) { - switch ($value[0]) { - case PDF_TYPE_STRING: - if ($this->encrypted) { - $value[1] = $this->_unescape($value[1]); - $value[1] = $this->_encrypt_data($this->_current_obj_id, $value[1]); - $value[1] = $this->_escape($value[1]); - } - break; - - case PDF_TYPE_STREAM: - if ($this->encrypted) { - $value[2][1] = $this->_encrypt_data($this->_current_obj_id, $value[2][1]); - $value[1][1]['/Length'] = array( - PDF_TYPE_NUMERIC, - strlen($value[2][1]) - ); - } - break; - - case PDF_TYPE_HEX: - if ($this->encrypted) { - $value[1] = $this->hex2str($value[1]); - $value[1] = $this->_encrypt_data($this->_current_obj_id, $value[1]); - - // remake hexstring of encrypted string - $value[1] = $this->str2hex($value[1]); - } - break; - } - } - - /** - * Unescapes a PDF string - * - * @param string $s - * @return string - */ - function _unescape($s) { - $out = ''; - for ($count = 0, $n = strlen($s); $count < $n; $count++) { - if ($s[$count] != '\\' || $count == $n-1) { - $out .= $s[$count]; - } else { - switch ($s[++$count]) { - case ')': - case '(': - case '\\': - $out .= $s[$count]; - break; - case 'f': - $out .= chr(0x0C); - break; - case 'b': - $out .= chr(0x08); - break; - case 't': - $out .= chr(0x09); - break; - case 'r': - $out .= chr(0x0D); - break; - case 'n': - $out .= chr(0x0A); - break; - case "\r": - if ($count != $n-1 && $s[$count+1] == "\n") - $count++; - break; - case "\n": - break; - default: - // Octal-Values - if (ord($s[$count]) >= ord('0') && - ord($s[$count]) <= ord('9')) { - $oct = ''. $s[$count]; - - if (ord($s[$count+1]) >= ord('0') && - ord($s[$count+1]) <= ord('9')) { - $oct .= $s[++$count]; - - if (ord($s[$count+1]) >= ord('0') && - ord($s[$count+1]) <= ord('9')) { - $oct .= $s[++$count]; - } - } - - $out .= chr(octdec($oct)); - } else { - $out .= $s[$count]; - } - } - } - } - return $out; - } - - /** - * Hexadecimal to string - * - * @param string $hex - * @return string - */ - function hex2str($hex) { - return pack('H*', str_replace(array("\r", "\n", ' '), '', $hex)); - } - - /** - * String to hexadecimal - * - * @param string $str - * @return string - */ - function str2hex($str) { - return current(unpack('H*', $str)); - } -} \ No newline at end of file diff --git a/htdocs/includes/fpdfi/fpdi_bridge.php b/htdocs/includes/fpdfi/fpdi_bridge.php new file mode 100644 index 00000000000..f89822d9510 --- /dev/null +++ b/htdocs/includes/fpdfi/fpdi_bridge.php @@ -0,0 +1,215 @@ +_tpls as $tplIdx => $tpl) { + $out .= sprintf('%s%d %d 0 R', $this->tplPrefix, $tplIdx, $tpl['n']); + } + + return $out; + } + + /** + * Writes a PDF value to the resulting document. + * + * Prepares the value for encryption of imported data by FPDI + * + * @param array $value + */ + protected function _prepareValue(&$value) + { + switch ($value[0]) { + case pdf_parser::TYPE_STRING: + if ($this->encrypted) { + $value[1] = $this->_unescape($value[1]); + $value[1] = $this->_encrypt_data($this->_currentObjId, $value[1]); + $value[1] = TCPDF_STATIC::_escape($value[1]); + } + break; + + case pdf_parser::TYPE_STREAM: + if ($this->encrypted) { + $value[2][1] = $this->_encrypt_data($this->_currentObjId, $value[2][1]); + $value[1][1]['/Length'] = array( + pdf_parser::TYPE_NUMERIC, + strlen($value[2][1]) + ); + } + break; + + case pdf_parser::TYPE_HEX: + if ($this->encrypted) { + $value[1] = $this->hex2str($value[1]); + $value[1] = $this->_encrypt_data($this->_currentObjId, $value[1]); + + // remake hexstring of encrypted string + $value[1] = $this->str2hex($value[1]); + } + break; + } + } + + /** + * Un-escapes a PDF string + * + * @param string $s + * @return string + */ + protected function _unescape($s) + { + $out = ''; + for ($count = 0, $n = strlen($s); $count < $n; $count++) { + if ($s[$count] != '\\' || $count == $n-1) { + $out .= $s[$count]; + } else { + switch ($s[++$count]) { + case ')': + case '(': + case '\\': + $out .= $s[$count]; + break; + case 'f': + $out .= chr(0x0C); + break; + case 'b': + $out .= chr(0x08); + break; + case 't': + $out .= chr(0x09); + break; + case 'r': + $out .= chr(0x0D); + break; + case 'n': + $out .= chr(0x0A); + break; + case "\r": + if ($count != $n-1 && $s[$count+1] == "\n") + $count++; + break; + case "\n": + break; + default: + // Octal-Values + if (ord($s[$count]) >= ord('0') && + ord($s[$count]) <= ord('9')) { + $oct = ''. $s[$count]; + + if (ord($s[$count+1]) >= ord('0') && + ord($s[$count+1]) <= ord('9')) { + $oct .= $s[++$count]; + + if (ord($s[$count+1]) >= ord('0') && + ord($s[$count+1]) <= ord('9')) { + $oct .= $s[++$count]; + } + } + + $out .= chr(octdec($oct)); + } else { + $out .= $s[$count]; + } + } + } + } + return $out; + } + + /** + * Hexadecimal to string + * + * @param string $data + * @return string + */ + public function hex2str($data) + { + $data = preg_replace('/[^0-9A-Fa-f]/', '', rtrim($data, '>')); + if ((strlen($data) % 2) == 1) { + $data .= '0'; + } + + return pack('H*', $data); + } + + /** + * String to hexadecimal + * + * @param string $str + * @return string + */ + public function str2hex($str) + { + return current(unpack('H*', $str)); + } + } +} \ No newline at end of file diff --git a/htdocs/includes/fpdfi/fpdi_pdf_parser.php b/htdocs/includes/fpdfi/fpdi_pdf_parser.php index 9da790507f3..9e76341b0cd 100644 --- a/htdocs/includes/fpdfi/fpdi_pdf_parser.php +++ b/htdocs/includes/fpdfi/fpdi_pdf_parser.php @@ -1,8 +1,8 @@ fpdi =& $fpdi; - - parent::pdf_parser($filename); + public function __construct($filename) + { + parent::__construct($filename); // resolve Pages-Dictonary - $pages = $this->pdf_resolve_object($this->c, $this->root[1][1]['/Pages']); + $pages = $this->resolveObject($this->_root[1][1]['/Pages']); // Read pages - $this->read_pages($this->c, $pages, $this->pages); + $this->_readPages($pages, $this->_pages); // count pages; - $this->page_count = count($this->pages); + $this->_pageCount = count($this->_pages); } /** - * Overwrite parent::error() - * - * @param string $msg Error-Message - */ - function error($msg) { - $this->fpdi->error($msg); - } - - /** - * Get pagecount from sourcefile + * Get page count from source file. * * @return int */ - function getPageCount() { - return $this->page_count; + public function getPageCount() + { + return $this->_pageCount; } - /** - * Set pageno + * Set the page number. * - * @param int $pageno Pagenumber to use + * @param int $pageNo Page number to use + * @throws InvalidArgumentException */ - function setPageno($pageno) { - $pageno = ((int) $pageno) - 1; + public function setPageNo($pageNo) + { + $pageNo = ((int) $pageNo) - 1; - if ($pageno < 0 || $pageno >= $this->getPageCount()) { - $this->fpdi->error('Pagenumber is wrong!'); + if ($pageNo < 0 || $pageNo >= $this->getPageCount()) { + throw new InvalidArgumentException('Invalid page number!'); } - $this->pageno = $pageno; + $this->pageNo = $pageNo; } /** * Get page-resources from current page * - * @return array + * @return array|boolean */ - function getPageResources() { - return $this->_getPageResources($this->pages[$this->pageno]); + public function getPageResources() + { + return $this->_getPageResources($this->_pages[$this->pageNo]); } /** - * Get page-resources from /Page + * Get page-resources from a /Page dictionary. * * @param array $obj Array of pdf-data + * @return array|boolean */ - function _getPageResources ($obj) { // $obj = /Page - $obj = $this->pdf_resolve_object($this->c, $obj); + protected function _getPageResources($obj) + { + $obj = $this->resolveObject($obj); // If the current object has a resources // dictionary associated with it, we use // it. Otherwise, we move back to its // parent object. - if (isset ($obj[1][1]['/Resources'])) { - $res = $this->pdf_resolve_object($this->c, $obj[1][1]['/Resources']); - if ($res[0] == PDF_TYPE_OBJECT) + if (isset($obj[1][1]['/Resources'])) { + $res = $this->resolveObject($obj[1][1]['/Resources']); + if ($res[0] == pdf_parser::TYPE_OBJECT) return $res[1]; return $res; - } else { - if (!isset ($obj[1][1]['/Parent'])) { - return false; - } else { - $res = $this->_getPageResources($obj[1][1]['/Parent']); - if ($res[0] == PDF_TYPE_OBJECT) - return $res[1]; - return $res; - } } + + if (!isset($obj[1][1]['/Parent'])) { + return false; + } + + $res = $this->_getPageResources($obj[1][1]['/Parent']); + if ($res[0] == pdf_parser::TYPE_OBJECT) + return $res[1]; + return $res; } - /** - * Get content of current page + * Get content of current page. * - * If more /Contents is an array, the streams are concated + * If /Contents is an array, the streams are concatenated * * @return string */ - function getContent() { + public function getContent() + { $buffer = ''; - if (isset($this->pages[$this->pageno][1][1]['/Contents'])) { - $contents = $this->_getPageContent($this->pages[$this->pageno][1][1]['/Contents']); - foreach($contents AS $tmp_content) { - $buffer .= $this->_rebuildContentStream($tmp_content) . ' '; + if (isset($this->_pages[$this->pageNo][1][1]['/Contents'])) { + $contents = $this->_getPageContent($this->_pages[$this->pageNo][1][1]['/Contents']); + foreach ($contents AS $tmpContent) { + $buffer .= $this->_unFilterStream($tmpContent) . ' '; } } return $buffer; } - - + /** - * Resolve all content-objects + * Resolve all content objects. * - * @param array $content_ref + * @param array $contentRef * @return array */ - function _getPageContent($content_ref) { + protected function _getPageContent($contentRef) + { $contents = array(); - if ($content_ref[0] == PDF_TYPE_OBJREF) { - $content = $this->pdf_resolve_object($this->c, $content_ref); - if ($content[1][0] == PDF_TYPE_ARRAY) { + if ($contentRef[0] == pdf_parser::TYPE_OBJREF) { + $content = $this->resolveObject($contentRef); + if ($content[1][0] == pdf_parser::TYPE_ARRAY) { $contents = $this->_getPageContent($content[1]); } else { $contents[] = $content; } - } else if ($content_ref[0] == PDF_TYPE_ARRAY) { - foreach ($content_ref[1] AS $tmp_content_ref) { - $contents = array_merge($contents,$this->_getPageContent($tmp_content_ref)); + } else if ($contentRef[0] == pdf_parser::TYPE_ARRAY) { + foreach ($contentRef[1] AS $tmp_content_ref) { + $contents = array_merge($contents, $this->_getPageContent($tmp_content_ref)); } } return $contents; } - /** - * Rebuild content-streams + * Get a boundary box from a page * - * @param array $obj - * @return string - */ - function _rebuildContentStream($obj) { - $filters = array(); - - if (isset($obj[1][1]['/Filter'])) { - $_filter = $obj[1][1]['/Filter']; - - if ($_filter[0] == PDF_TYPE_OBJREF) { - $tmpFilter = $this->pdf_resolve_object($this->c, $_filter); - $_filter = $tmpFilter[1]; - } - - if ($_filter[0] == PDF_TYPE_TOKEN) { - $filters[] = $_filter; - } else if ($_filter[0] == PDF_TYPE_ARRAY) { - $filters = $_filter[1]; - } - } - - $stream = $obj[2][1]; - - foreach ($filters AS $_filter) { - switch ($_filter[1]) { - case '/FlateDecode': - case '/Fl': - // $stream .= "\x0F\x0D"; // in an errorious stream this suffix could work - // $stream .= "\x0A"; - // $stream .= "\x0D"; - if (function_exists('gzuncompress')) { - $stream = (strlen($stream) > 0) ? @gzuncompress($stream) : ''; - } else { - $this->error(sprintf('To handle %s filter, please compile php with zlib support.',$_filter[1])); - } - - if ($stream === false) { - $this->error('Error while decompressing stream.'); - } - break; - case '/LZWDecode': - include_once('filters/FilterLZW_FPDI.php'); - $decoder = new FilterLZW_FPDI($this->fpdi); - $stream = $decoder->decode($stream); - break; - case '/ASCII85Decode': - include_once('filters/FilterASCII85_FPDI.php'); - $decoder = new FilterASCII85_FPDI($this->fpdi); - $stream = $decoder->decode($stream); - break; - case null: - $stream = $stream; - break; - default: - $this->error(sprintf('Unsupported Filter: %s',$_filter[1])); - } - } - - return $stream; - } - - - /** - * Get a Box from a page - * Arrayformat is same as used by fpdf_tpl + * Array format is same as used by FPDF_TPL. * - * @param array $page a /Page - * @param string $box_index Type of Box @see $availableBoxes + * @param array $page a /Page dictionary + * @param string $boxIndex Type of box {see {@link $availableBoxes}) * @param float Scale factor from user space units to points - * @return array + * + * @return array|boolean */ - function getPageBox($page, $box_index, $k) { - $page = $this->pdf_resolve_object($this->c, $page); + protected function _getPageBox($page, $boxIndex, $k) + { + $page = $this->resolveObject($page); $box = null; - if (isset($page[1][1][$box_index])) - $box =& $page[1][1][$box_index]; + if (isset($page[1][1][$boxIndex])) { + $box = $page[1][1][$boxIndex]; + } - if (!is_null($box) && $box[0] == PDF_TYPE_OBJREF) { - $tmp_box = $this->pdf_resolve_object($this->c, $box); + if (!is_null($box) && $box[0] == pdf_parser::TYPE_OBJREF) { + $tmp_box = $this->resolveObject($box); $box = $tmp_box[1]; } - if (!is_null($box) && $box[0] == PDF_TYPE_ARRAY) { - $b =& $box[1]; - return array('x' => $b[0][1] / $k, - 'y' => $b[1][1] / $k, - 'w' => abs($b[0][1] - $b[2][1]) / $k, - 'h' => abs($b[1][1] - $b[3][1]) / $k, - 'llx' => min($b[0][1], $b[2][1]) / $k, - 'lly' => min($b[1][1], $b[3][1]) / $k, - 'urx' => max($b[0][1], $b[2][1]) / $k, - 'ury' => max($b[1][1], $b[3][1]) / $k, - ); - } else if (!isset ($page[1][1]['/Parent'])) { + if (!is_null($box) && $box[0] == pdf_parser::TYPE_ARRAY) { + $b = $box[1]; + return array( + 'x' => $b[0][1] / $k, + 'y' => $b[1][1] / $k, + 'w' => abs($b[0][1] - $b[2][1]) / $k, + 'h' => abs($b[1][1] - $b[3][1]) / $k, + 'llx' => min($b[0][1], $b[2][1]) / $k, + 'lly' => min($b[1][1], $b[3][1]) / $k, + 'urx' => max($b[0][1], $b[2][1]) / $k, + 'ury' => max($b[1][1], $b[3][1]) / $k, + ); + } else if (!isset($page[1][1]['/Parent'])) { return false; } else { - return $this->getPageBox($this->pdf_resolve_object($this->c, $page[1][1]['/Parent']), $box_index, $k); + return $this->_getPageBox($this->resolveObject($page[1][1]['/Parent']), $boxIndex, $k); } } /** - * Get all page boxes by page no + * Get all page boundary boxes by page number * - * @param int The page number - * @param float Scale factor from user space units to points + * @param int $pageNo The page number + * @param float $k Scale factor from user space units to points * @return array + * @throws InvalidArgumentException */ - function getPageBoxes($pageno, $k) { - return $this->_getPageBoxes($this->pages[$pageno - 1], $k); + public function getPageBoxes($pageNo, $k) + { + if (!isset($this->_pages[$pageNo - 1])) { + throw new InvalidArgumentException('Page ' . $pageNo . ' does not exists.'); + } + + return $this->_getPageBoxes($this->_pages[$pageNo - 1], $k); } /** - * Get all boxes from /Page + * Get all boxes from /Page dictionary * - * @param array a /Page + * @param array $page A /Page dictionary + * @param float $k Scale factor from user space units to points * @return array */ - function _getPageBoxes($page, $k) { + protected function _getPageBoxes($page, $k) + { $boxes = array(); foreach($this->availableBoxes AS $box) { - if ($_box = $this->getPageBox($page, $box, $k)) { + if ($_box = $this->_getPageBox($page, $box, $k)) { $boxes[$box] = $_box; } } @@ -334,75 +276,79 @@ class fpdi_pdf_parser extends pdf_parser { } /** - * Get the page rotation by pageno + * Get the page rotation by page number * - * @param integer $pageno + * @param integer $pageNo + * @throws InvalidArgumentException * @return array */ - function getPageRotation($pageno) { - return $this->_getPageRotation($this->pages[$pageno - 1]); + public function getPageRotation($pageNo) + { + if (!isset($this->_pages[$pageNo - 1])) { + throw new InvalidArgumentException('Page ' . $pageNo . ' does not exists.'); + } + + return $this->_getPageRotation($this->_pages[$pageNo - 1]); } - - function _getPageRotation($obj) { // $obj = /Page - $obj = $this->pdf_resolve_object($this->c, $obj); - if (isset ($obj[1][1]['/Rotate'])) { - $res = $this->pdf_resolve_object($this->c, $obj[1][1]['/Rotate']); - if ($res[0] == PDF_TYPE_OBJECT) + + /** + * Get the rotation value of a page + * + * @param array $obj A /Page dictionary + * @return array|bool + */ + protected function _getPageRotation($obj) + { + $obj = $this->resolveObject($obj); + if (isset($obj[1][1]['/Rotate'])) { + $res = $this->resolveObject($obj[1][1]['/Rotate']); + if ($res[0] == pdf_parser::TYPE_OBJECT) return $res[1]; return $res; - } else { - if (!isset ($obj[1][1]['/Parent'])) { - return false; - } else { - $res = $this->_getPageRotation($obj[1][1]['/Parent']); - if ($res[0] == PDF_TYPE_OBJECT) - return $res[1]; - return $res; - } } - } - - /** - * Read all /Page(es) - * - * @param object pdf_context - * @param array /Pages - * @param array the result-array - */ - function read_pages(&$c, &$pages, &$result) { - // Get the kids dictionary - $_kids = $this->pdf_resolve_object ($c, $pages[1][1]['/Kids']); - - if (!is_array($_kids)) - $this->error('Cannot find /Kids in current /Page-Dictionary'); - - if ($_kids[1][0] == PDF_TYPE_ARRAY) { - $kids = $_kids[1][1]; - } else { - $kids = $_kids[1]; + + if (!isset($obj[1][1]['/Parent'])) { + return false; } - + + $res = $this->_getPageRotation($obj[1][1]['/Parent']); + if ($res[0] == pdf_parser::TYPE_OBJECT) + return $res[1]; + + return $res; + } + + /** + * Read all pages + * + * @param array $pages /Pages dictionary + * @param array $result The result array + * @throws Exception + */ + protected function _readPages(&$pages, &$result) + { + // Get the kids dictionary + $_kids = $this->resolveObject($pages[1][1]['/Kids']); + + if (!is_array($_kids)) { + throw new Exception('Cannot find /Kids in current /Page-Dictionary'); + } + + if ($_kids[0] === self::TYPE_OBJECT) { + $_kids = $_kids[1]; + } + + $kids = $_kids[1]; + foreach ($kids as $v) { - $pg = $this->pdf_resolve_object ($c, $v); + $pg = $this->resolveObject($v); if ($pg[1][1]['/Type'][1] === '/Pages') { // If one of the kids is an embedded // /Pages array, resolve it as well. - $this->read_pages($c, $pg, $result); + $this->_readPages($pg, $result); } else { $result[] = $pg; } } } - - - - /** - * Get PDF-Version - * - * And reset the PDF Version used in FPDI if needed - */ - function getPDFVersion() { - parent::getPDFVersion(); - $this->fpdi->setPDFVersion(max($this->fpdi->getPDFVersion(), $this->pdfVersion)); - } } \ No newline at end of file diff --git a/htdocs/includes/fpdfi/pdf_context.php b/htdocs/includes/fpdfi/pdf_context.php index 78b7b4ae6de..88f3aedefff 100644 --- a/htdocs/includes/fpdfi/pdf_context.php +++ b/htdocs/includes/fpdfi/pdf_context.php @@ -1,8 +1,8 @@ file =& $f; - if (is_string($this->file)) - $this->_mode = 1; - $this->reset(); - } - - // Optionally move the file - // pointer to a new location - // and reset the buffered data - - function reset($pos = null, $l = 100) { - if ($this->_mode == 0) { - if (!is_null ($pos)) { - fseek ($this->file, $pos); - } - - $this->buffer = $l > 0 ? fread($this->file, $l) : ''; - $this->length = strlen($this->buffer); - if ($this->length < $l) - $this->increase_length($l - $this->length); - } else { - $this->buffer = $this->file; - $this->length = strlen($this->buffer); - } - $this->offset = 0; - $this->stack = array(); - } - - // Make sure that there is at least one - // character beyond the current offset in - // the buffer to prevent the tokenizer - // from attempting to access data that does - // not exist - - function ensure_content() { - if ($this->offset >= $this->length - 1) { - return $this->increase_length(); - } else { - return true; - } - } - - // Forcefully read more data into the buffer - - function increase_length($l = 100) { - if ($this->_mode == 0 && feof($this->file)) { - return false; - } else if ($this->_mode == 0) { - $totalLength = $this->length + $l; - do { - $toRead = $totalLength - $this->length; - if ($toRead < 1) - break; - - $this->buffer .= fread($this->file, $toRead); - } while ((($this->length = strlen($this->buffer)) != $totalLength) && !feof($this->file)); - - return true; - } else { - return false; - } - } +/** + * Class pdf_context + */ +class pdf_context +{ + /** + * Mode + * + * @var integer 0 = file | 1 = string + */ + protected $_mode = 0; + + /** + * @var resource|string + */ + public $file; + + /** + * @var string + */ + public $buffer; + + /** + * @var integer + */ + public $offset; + + /** + * @var integer + */ + public $length; + + /** + * @var array + */ + public $stack; + + /** + * The constructor + * + * @param resource $f + */ + public function __construct(&$f) + { + $this->file =& $f; + if (is_string($this->file)) + $this->_mode = 1; + + $this->reset(); + } + + /** + * Get the position in the file stream + * + * @return int + */ + public function getPos() + { + if ($this->_mode == 0) { + return ftell($this->file); + } else { + return 0; + } + } + + /** + * Reset the position in the file stream. + * + * Optionally move the file pointer to a new location and reset the buffered data. + * + * @param null $pos + * @param int $l + */ + public function reset($pos = null, $l = 100) + { + if ($this->_mode == 0) { + if (!is_null($pos)) { + fseek ($this->file, $pos); + } + + $this->buffer = $l > 0 ? fread($this->file, $l) : ''; + $this->length = strlen($this->buffer); + if ($this->length < $l) + $this->increaseLength($l - $this->length); + } else { + $this->buffer = $this->file; + $this->length = strlen($this->buffer); + } + $this->offset = 0; + $this->stack = array(); + } + + /** + * Make sure that there is at least one character beyond the current offset in the buffer. + * + * To prevent the tokenizer from attempting to access data that does not exist. + * + * @return bool + */ + public function ensureContent() + { + if ($this->offset >= $this->length - 1) { + return $this->increaseLength(); + } else { + return true; + } + } + + /** + * Forcefully read more data into the buffer + * + * @param int $l + * @return bool + */ + public function increaseLength($l = 100) + { + if ($this->_mode == 0 && feof($this->file)) { + return false; + } else if ($this->_mode == 0) { + $totalLength = $this->length + $l; + do { + $toRead = $totalLength - $this->length; + if ($toRead < 1) + break; + + $this->buffer .= fread($this->file, $toRead); + } while ((($this->length = strlen($this->buffer)) != $totalLength) && !feof($this->file)); + + return true; + } else { + return false; + } } } \ No newline at end of file diff --git a/htdocs/includes/fpdfi/pdf_parser.php b/htdocs/includes/fpdfi/pdf_parser.php index 238e10c0def..a1c82dec23c 100644 --- a/htdocs/includes/fpdfi/pdf_parser.php +++ b/htdocs/includes/fpdfi/pdf_parser.php @@ -1,8 +1,8 @@ filename = $filename; - - $this->f = @fopen($this->filename, 'rb'); - - if (!$this->f) - $this->error(sprintf('Cannot open %s !', $filename)); - - $this->getPDFVersion(); - - $this->c = new pdf_context($this->f); - - // Read xref-Data - $this->xref = array(); - $this->pdf_read_xref($this->xref, $this->pdf_find_xref()); - - // Check for Encryption - $this->getEncryption(); - - // Read root - $this->pdf_read_root(); + /** + * Type constant + * + * @var integer + */ + const TYPE_NUMERIC = 1; + + /** + * Type constant + * + * @var integer + */ + const TYPE_TOKEN = 2; + + /** + * Type constant + * + * @var integer + */ + const TYPE_HEX = 3; + + /** + * Type constant + * + * @var integer + */ + const TYPE_STRING = 4; + + /** + * Type constant + * + * @var integer + */ + const TYPE_DICTIONARY = 5; + + /** + * Type constant + * + * @var integer + */ + const TYPE_ARRAY = 6; + + /** + * Type constant + * + * @var integer + */ + const TYPE_OBJDEC = 7; + + /** + * Type constant + * + * @var integer + */ + const TYPE_OBJREF = 8; + + /** + * Type constant + * + * @var integer + */ + const TYPE_OBJECT = 9; + + /** + * Type constant + * + * @var integer + */ + const TYPE_STREAM = 10; + + /** + * Type constant + * + * @var integer + */ + const TYPE_BOOLEAN = 11; + + /** + * Type constant + * + * @var integer + */ + const TYPE_REAL = 12; + + /** + * Define the amount of byte in which the initial keyword of a PDF document should be searched. + * + * @var int + */ + static public $searchForStartxrefLength = 5500; + + /** + * Filename + * + * @var string + */ + public $filename; + + /** + * File resource + * + * @var resource + */ + protected $_f; + + /** + * PDF Context + * + * @var pdf_context + */ + protected $_c; + + /** + * xref-Data + * + * @var array + */ + protected $_xref; + + /** + * Data of the Root object + * + * @var array + */ + protected $_root; + + /** + * PDF version of the loaded document + * + * @var string + */ + protected $_pdfVersion; + + /** + * For reading encrypted documents and xref/object streams are in use + * + * @var boolean + */ + protected $_readPlain = true; + + /** + * The current read object + * + * @var array + */ + protected $_currentObj; + + /** + * Constructor + * + * @param string $filename Source filename + * @throws InvalidArgumentException + */ + public function __construct($filename) + { + $this->filename = $filename; + + $this->_f = @fopen($this->filename, 'rb'); + + if (!$this->_f) { + throw new InvalidArgumentException(sprintf('Cannot open %s !', $filename)); } - - /** - * Close the opened file - */ - function closeFile() { - if (isset($this->f) && is_resource($this->f)) { - fclose($this->f); - unset($this->f); - } - } - - /** - * Print Error and die - * - * @param string $msg Error-Message - */ - function error($msg) { - die('PDF-Parser Error: ' . $msg); - } - - /** - * Check Trailer for Encryption - */ - function getEncryption() { - if (isset($this->xref['trailer'][1]['/Encrypt'])) { - $this->error('File is encrypted!'); - } - } - - /** - * Find/Return /Root - * - * @return array - */ - function pdf_find_root() { - if ($this->xref['trailer'][1]['/Root'][0] != PDF_TYPE_OBJREF) { - $this->error('Wrong Type of Root-Element! Must be an indirect reference'); - } - - return $this->xref['trailer'][1]['/Root']; - } - - /** - * Read the /Root - */ - function pdf_read_root() { - // read root - $this->root = $this->pdf_resolve_object($this->c, $this->pdf_find_root()); - } - - /** - * Get PDF-Version - * - * And reset the PDF Version used in FPDI if needed - */ - function getPDFVersion() { - fseek($this->f, 0); - preg_match('/\d\.\d/',fread($this->f, 16), $m); - if (isset($m[0])) - $this->pdfVersion = $m[0]; - return $this->pdfVersion; - } - - /** - * Find the xref-Table - */ - function pdf_find_xref() { - $toRead = 1500; - - $stat = fseek ($this->f, -$toRead, SEEK_END); - if ($stat === -1) { - fseek ($this->f, 0); - } - $data = fread($this->f, $toRead); - - $pos = strlen($data) - strpos(strrev($data), strrev('startxref')); - $data = substr($data, $pos); - - if (!preg_match('/\s*(\d+).*$/s', $data, $matches)) { - $this->error('Unable to find pointer to xref table'); - } - - return (int) $matches[1]; - } - - /** - * Read xref-table - * - * @param array $result Array of xref-table - * @param integer $offset of xref-table - */ - function pdf_read_xref(&$result, $offset) { - $o_pos = $offset-min(20, $offset); - fseek($this->f, $o_pos); // set some bytes backwards to fetch errorious docs - - $data = fread($this->f, 100); - - $xrefPos = strrpos($data, 'xref'); - - if ($xrefPos === false) { - fseek($this->f, $offset); - $c = new pdf_context($this->f); - $xrefStreamObjDec = $this->pdf_read_value($c); - - if (is_array($xrefStreamObjDec) && isset($xrefStreamObjDec[0]) && $xrefStreamObjDec[0] == PDF_TYPE_OBJDEC) { - $this->error(sprintf('This document (%s) probably uses a compression technique which is not supported by the free parser shipped with FPDI.', $this->filename)); - } else { - $this->error('Unable to find xref table.'); - } - } - - if (!isset($result['xref_location'])) { - $result['xref_location'] = $o_pos + $xrefPos; - $result['max_object'] = 0; - } - - $cylces = -1; - $bytesPerCycle = 100; - - fseek($this->f, $o_pos = $o_pos + $xrefPos + 4); // set the handle directly after the "xref"-keyword - $data = fread($this->f, $bytesPerCycle); - - while (($trailerPos = strpos($data, 'trailer', max($bytesPerCycle * $cylces++, 0))) === false && !feof($this->f)) { - $data .= fread($this->f, $bytesPerCycle); - } - - if ($trailerPos === false) { - $this->error('Trailer keyword not found after xref table'); - } - - $data = substr($data, 0, $trailerPos); - - // get Line-Ending - preg_match_all("/(\r\n|\n|\r)/", substr($data, 0, 100), $m); // check the first 100 bytes for linebreaks - - $differentLineEndings = count(array_unique($m[0])); - if ($differentLineEndings > 1) { - $lines = preg_split("/(\r\n|\n|\r)/", $data, -1, PREG_SPLIT_NO_EMPTY); - } else { - $lines = explode($m[0][1], $data); - } - - $data = $differentLineEndings = $m = null; - unset($data, $differentLineEndings, $m); - - $linesCount = count($lines); - - $start = 1; - - for ($i = 0; $i < $linesCount; $i++) { - $line = trim($lines[$i]); - if ($line) { - $pieces = explode(' ', $line); - $c = count($pieces); - switch($c) { - case 2: - $start = (int)$pieces[0]; - $end = $start + (int)$pieces[1]; - if ($end > $result['max_object']) - $result['max_object'] = $end; - break; - case 3: - if (!isset($result['xref'][$start])) - $result['xref'][$start] = array(); - - if (!array_key_exists($gen = (int) $pieces[1], $result['xref'][$start])) { - $result['xref'][$start][$gen] = $pieces[2] == 'n' ? (int) $pieces[0] : null; - } - $start++; - break; - default: - $this->error('Unexpected data in xref table'); - } - } - } - - $lines = $pieces = $line = $start = $end = $gen = null; - unset($lines, $pieces, $line, $start, $end, $gen); - - fseek($this->f, $o_pos + $trailerPos + 7); - - $c = new pdf_context($this->f); - $trailer = $this->pdf_read_value($c); - - $c = null; - unset($c); - - if (!isset($result['trailer'])) { - $result['trailer'] = $trailer; - } - - if (isset($trailer[1]['/Prev'])) { - $this->pdf_read_xref($result, $trailer[1]['/Prev'][1]); - } - - $trailer = null; - unset($trailer); - - return true; - } - - /** - * Reads an Value - * - * @param object $c pdf_context - * @param string $token a Token - * @return mixed - */ - function pdf_read_value(&$c, $token = null) { - if (is_null($token)) { - $token = $this->pdf_read_token($c); - } - - if ($token === false) { - return false; - } - - switch ($token) { - case '<': - // This is a hex string. - // Read the value, then the terminator - - $pos = $c->offset; - - while(1) { - - $match = strpos ($c->buffer, '>', $pos); - - // If you can't find it, try - // reading more data from the stream - - if ($match === false) { - if (!$c->increase_length()) { - return false; - } else { - continue; - } - } - - $result = substr ($c->buffer, $c->offset, $match - $c->offset); - $c->offset = $match + 1; - - return array (PDF_TYPE_HEX, $result); - } - - break; - case '<<': - // This is a dictionary. - - $result = array(); - - // Recurse into this function until we reach - // the end of the dictionary. - while (($key = $this->pdf_read_token($c)) !== '>>') { - if ($key === false) { - return false; - } - - if (($value = $this->pdf_read_value($c)) === false) { - return false; - } - - // Catch missing value - if ($value[0] == PDF_TYPE_TOKEN && $value[1] == '>>') { - $result[$key] = array(PDF_TYPE_NULL); - break; - } - - $result[$key] = $value; - } - - return array (PDF_TYPE_DICTIONARY, $result); - - case '[': - // This is an array. - - $result = array(); - - // Recurse into this function until we reach - // the end of the array. - while (($token = $this->pdf_read_token($c)) !== ']') { - if ($token === false) { - return false; - } - - if (($value = $this->pdf_read_value($c, $token)) === false) { - return false; - } - - $result[] = $value; - } - - return array (PDF_TYPE_ARRAY, $result); - - case '(' : - // This is a string - $pos = $c->offset; - - $openBrackets = 1; - do { - for (; $openBrackets != 0 && $pos < $c->length; $pos++) { - switch (ord($c->buffer[$pos])) { - case 0x28: // '(' - $openBrackets++; - break; - case 0x29: // ')' - $openBrackets--; - break; - case 0x5C: // backslash - $pos++; - } - } - } while($openBrackets != 0 && $c->increase_length()); - - $result = substr($c->buffer, $c->offset, $pos - $c->offset - 1); - $c->offset = $pos; - - return array (PDF_TYPE_STRING, $result); - - case 'stream': - $o_pos = ftell($c->file)-strlen($c->buffer); - $o_offset = $c->offset; - - $c->reset($startpos = $o_pos + $o_offset); - - $e = 0; // ensure line breaks in front of the stream - if ($c->buffer[0] == chr(10) || $c->buffer[0] == chr(13)) - $e++; - if ($c->buffer[1] == chr(10) && $c->buffer[0] != chr(10)) - $e++; - - if ($this->actual_obj[1][1]['/Length'][0] == PDF_TYPE_OBJREF) { - $tmp_c = new pdf_context($this->f); - $tmp_length = $this->pdf_resolve_object($tmp_c, $this->actual_obj[1][1]['/Length']); - $length = $tmp_length[1][1]; - } else { - $length = $this->actual_obj[1][1]['/Length'][1]; - } - - if ($length > 0) { - $c->reset($startpos + $e,$length); - $v = $c->buffer; - } else { - $v = ''; - } - $c->reset($startpos + $e + $length + 9); // 9 = strlen("endstream") - - return array(PDF_TYPE_STREAM, $v); - - default : - if (is_numeric ($token)) { - // A numeric token. Make sure that - // it is not part of something else. - if (($tok2 = $this->pdf_read_token ($c)) !== false) { - if (is_numeric ($tok2)) { - - // Two numeric tokens in a row. - // In this case, we're probably in - // front of either an object reference - // or an object specification. - // Determine the case and return the data - if (($tok3 = $this->pdf_read_token ($c)) !== false) { - switch ($tok3) { - case 'obj': - return array (PDF_TYPE_OBJDEC, (int) $token, (int) $tok2); - case 'R': - return array (PDF_TYPE_OBJREF, (int) $token, (int) $tok2); - } - // If we get to this point, that numeric value up - // there was just a numeric value. Push the extra - // tokens back into the stack and return the value. - array_push ($c->stack, $tok3); - } - } - - array_push ($c->stack, $tok2); - } - - if ($token === (string)((int)$token)) - return array (PDF_TYPE_NUMERIC, (int)$token); - else - return array (PDF_TYPE_REAL, (float)$token); - } else if ($token == 'true' || $token == 'false') { - return array (PDF_TYPE_BOOLEAN, $token == 'true'); - } else if ($token == 'null') { - return array (PDF_TYPE_NULL); - } else { - // Just a token. Return it. - return array (PDF_TYPE_TOKEN, $token); - } - } - } - - /** - * Resolve an object - * - * @param object $c pdf_context - * @param array $obj_spec The object-data - * @param boolean $encapsulate Must set to true, cause the parsing and fpdi use this method only without this para - */ - function pdf_resolve_object(&$c, $obj_spec, $encapsulate = true) { - // Exit if we get invalid data - if (!is_array($obj_spec)) { - $ret = false; - return $ret; - } - - if ($obj_spec[0] == PDF_TYPE_OBJREF) { - - // This is a reference, resolve it - if (isset($this->xref['xref'][$obj_spec[1]][$obj_spec[2]])) { - - // Save current file position - // This is needed if you want to resolve - // references while you're reading another object - // (e.g.: if you need to determine the length - // of a stream) - - $old_pos = ftell($c->file); - - // Reposition the file pointer and - // load the object header. - - $c->reset($this->xref['xref'][$obj_spec[1]][$obj_spec[2]]); - - $header = $this->pdf_read_value($c); - - if ($header[0] != PDF_TYPE_OBJDEC || $header[1] != $obj_spec[1] || $header[2] != $obj_spec[2]) { - $toSearchFor = $obj_spec[1] . ' ' . $obj_spec[2] . ' obj'; - if (preg_match('/' . $toSearchFor . '/', $c->buffer)) { - $c->offset = strpos($c->buffer, $toSearchFor) + strlen($toSearchFor); - // reset stack - $c->stack = array(); - } else { - $this->error("Unable to find object ({$obj_spec[1]}, {$obj_spec[2]}) at expected location"); - } - } - - // If we're being asked to store all the information - // about the object, we add the object ID and generation - // number for later use - $result = array(); - $this->actual_obj =& $result; - if ($encapsulate) { - $result = array ( - PDF_TYPE_OBJECT, - 'obj' => $obj_spec[1], - 'gen' => $obj_spec[2] - ); - } - - // Now simply read the object data until - // we encounter an end-of-object marker - while(1) { - $value = $this->pdf_read_value($c); - if ($value === false || count($result) > 4) { - // in this case the parser coudn't find an endobj so we break here - break; - } - - if ($value[0] == PDF_TYPE_TOKEN && $value[1] === 'endobj') { - break; - } - - $result[] = $value; - } - - $c->reset($old_pos); - - if (isset($result[2][0]) && $result[2][0] == PDF_TYPE_STREAM) { - $result[0] = PDF_TYPE_STREAM; - } - - return $result; - } - } else { - return $obj_spec; - } - } - - - - /** - * Reads a token from the file - * - * @param object $c pdf_context - * @return mixed - */ - function pdf_read_token(&$c) - { - // If there is a token available - // on the stack, pop it out and - // return it. - - if (count($c->stack)) { - return array_pop($c->stack); - } - - // Strip away any whitespace - - do { - if (!$c->ensure_content()) { - return false; - } - $c->offset += strspn($c->buffer, " \n\r\t", $c->offset); - } while ($c->offset >= $c->length - 1); - - // Get the first character in the stream - - $char = $c->buffer[$c->offset++]; - - switch ($char) { - - case '[': - case ']': - case '(': - case ')': - - // This is either an array or literal string - // delimiter, Return it - - return $char; - - case '<': - case '>': - - // This could either be a hex string or - // dictionary delimiter. Determine the - // appropriate case and return the token - - if ($c->buffer[$c->offset] == $char) { - if (!$c->ensure_content()) { - return false; - } - $c->offset++; - return $char . $char; - } else { - return $char; - } - - case '%': - - // This is a comment - jump over it! - - $pos = $c->offset; - while(1) { - $match = preg_match("/(\r\n|\r|\n)/", $c->buffer, $m, PREG_OFFSET_CAPTURE, $pos); - if ($match === 0) { - if (!$c->increase_length()) { - return false; - } else { - continue; - } - } - - $c->offset = $m[0][1]+strlen($m[0][0]); - - return $this->pdf_read_token($c); - } - - default: - - // This is "another" type of token (probably - // a dictionary entry or a numeric value) - // Find the end and return it. - - if (!$c->ensure_content()) { - return false; - } - - while(1) { - - // Determine the length of the token - - $pos = strcspn($c->buffer, " %[]<>()\r\n\t/", $c->offset); - - if ($c->offset + $pos <= $c->length - 1) { - break; - } else { - // If the script reaches this point, - // the token may span beyond the end - // of the current buffer. Therefore, - // we increase the size of the buffer - // and try again--just to be safe. - - $c->increase_length(); - } - } - - $result = substr($c->buffer, $c->offset - 1, $pos + 1); - - $c->offset += $pos; - return $result; - } + + $this->getPdfVersion(); + + require_once('pdf_context.php'); + $this->_c = new pdf_context($this->_f); + + // Read xref-Data + $this->_xref = array(); + $this->_readXref($this->_xref, $this->_findXref()); + + // Check for Encryption + $this->getEncryption(); + + // Read root + $this->_readRoot(); + } + + /** + * Destructor + */ + public function __destruct() + { + $this->closeFile(); + } + + /** + * Close the opened file + */ + public function closeFile() + { + if (isset($this->_f) && is_resource($this->_f)) { + fclose($this->_f); + unset($this->_f); } } -} + + /** + * Check Trailer for Encryption + * + * @throws Exception + */ + public function getEncryption() + { + if (isset($this->_xref['trailer'][1]['/Encrypt'])) { + throw new Exception('File is encrypted!'); + } + } + + /** + * Get PDF-Version + * + * @return string + */ + public function getPdfVersion() + { + if ($this->_pdfVersion === null) { + fseek($this->_f, 0); + preg_match('/\d\.\d/', fread($this->_f, 16), $m); + if (isset($m[0])) + $this->_pdfVersion = $m[0]; + } + + return $this->_pdfVersion; + } + + /** + * Read the /Root dictionary + */ + protected function _readRoot() + { + if ($this->_xref['trailer'][1]['/Root'][0] != self::TYPE_OBJREF) { + throw new Exception('Wrong Type of Root-Element! Must be an indirect reference'); + } + + $this->_root = $this->resolveObject($this->_xref['trailer'][1]['/Root']); + } + + /** + * Find the xref table + * + * @return integer + * @throws Exception + */ + protected function _findXref() + { + $toRead = self::$searchForStartxrefLength; + + $stat = fseek($this->_f, -$toRead, SEEK_END); + if ($stat === -1) { + fseek($this->_f, 0); + } + + $data = fread($this->_f, $toRead); + + $keywordPos = strpos(strrev($data), strrev('startxref')); + if (false === $keywordPos) { + $keywordPos = strpos(strrev($data), strrev('startref')); + } + + if (false === $keywordPos) { + throw new Exception('Unable to find "startxref" keyword.'); + } + + $pos = strlen($data) - $keywordPos; + $data = substr($data, $pos); + + if (!preg_match('/\s*(\d+).*$/s', $data, $matches)) { + throw new Exception('Unable to find pointer to xref table.'); + } + + return (int) $matches[1]; + } + + /** + * Read the xref table + * + * @param array $result Array of xref table entries + * @param integer $offset of xref table + * @return boolean + * @throws Exception + */ + protected function _readXref(&$result, $offset) + { + $tempPos = $offset - min(20, $offset); + fseek($this->_f, $tempPos); // set some bytes backwards to fetch corrupted docs + + $data = fread($this->_f, 100); + + $xrefPos = strrpos($data, 'xref'); + + if ($xrefPos === false) { + $this->_c->reset($offset); + $xrefStreamObjDec = $this->_readValue($this->_c); + + if (is_array($xrefStreamObjDec) && isset($xrefStreamObjDec[0]) && $xrefStreamObjDec[0] == self::TYPE_OBJDEC) { + throw new Exception( + sprintf( + 'This document (%s) probably uses a compression technique which is not supported by the ' . + 'free parser shipped with FPDI. (See https://www.setasign.com/fpdi-pdf-parser for more details)', + $this->filename + ) + ); + } else { + throw new Exception('Unable to find xref table.'); + } + } + + if (!isset($result['xrefLocation'])) { + $result['xrefLocation'] = $tempPos + $xrefPos; + $result['maxObject'] = 0; + } + + $cycles = -1; + $bytesPerCycle = 100; + + fseek($this->_f, $tempPos = $tempPos + $xrefPos + 4); // set the handle directly after the "xref"-keyword + $data = fread($this->_f, $bytesPerCycle); + + while (($trailerPos = strpos($data, 'trailer', max($bytesPerCycle * $cycles++, 0))) === false && !feof($this->_f)) { + $data .= fread($this->_f, $bytesPerCycle); + } + + if ($trailerPos === false) { + throw new Exception('Trailer keyword not found after xref table'); + } + + $data = ltrim(substr($data, 0, $trailerPos)); + + // get Line-Ending + preg_match_all("/(\r\n|\n|\r)/", substr($data, 0, 100), $m); // check the first 100 bytes for line breaks + + $differentLineEndings = count(array_unique($m[0])); + if ($differentLineEndings > 1) { + $lines = preg_split("/(\r\n|\n|\r)/", $data, -1, PREG_SPLIT_NO_EMPTY); + } else { + $lines = explode($m[0][0], $data); + } + + $data = $differentLineEndings = $m = null; + unset($data, $differentLineEndings, $m); + + $linesCount = count($lines); + + $start = 1; + + for ($i = 0; $i < $linesCount; $i++) { + $line = trim($lines[$i]); + if ($line) { + $pieces = explode(' ', $line); + $c = count($pieces); + switch($c) { + case 2: + $start = (int)$pieces[0]; + $end = $start + (int)$pieces[1]; + if ($end > $result['maxObject']) + $result['maxObject'] = $end; + break; + case 3: + if (!isset($result['xref'][$start])) + $result['xref'][$start] = array(); + + if (!array_key_exists($gen = (int) $pieces[1], $result['xref'][$start])) { + $result['xref'][$start][$gen] = $pieces[2] == 'n' ? (int) $pieces[0] : null; + } + $start++; + break; + default: + throw new Exception('Unexpected data in xref table'); + } + } + } + + $lines = $pieces = $line = $start = $end = $gen = null; + unset($lines, $pieces, $line, $start, $end, $gen); + + $this->_c->reset($tempPos + $trailerPos + 7); + $trailer = $this->_readValue($this->_c); + + if (!isset($result['trailer'])) { + $result['trailer'] = $trailer; + } + + if (isset($trailer[1]['/Prev'])) { + $this->_readXref($result, $trailer[1]['/Prev'][1]); + } + + $trailer = null; + unset($trailer); + + return true; + } + + /** + * Reads a PDF value + * + * @param pdf_context $c + * @param string $token A token + * @return mixed + */ + protected function _readValue(&$c, $token = null) + { + if (is_null($token)) { + $token = $this->_readToken($c); + } + + if ($token === false) { + return false; + } + + switch ($token) { + case '<': + // This is a hex string. + // Read the value, then the terminator + + $pos = $c->offset; + + while(1) { + + $match = strpos ($c->buffer, '>', $pos); + + // If you can't find it, try + // reading more data from the stream + + if ($match === false) { + if (!$c->increaseLength()) { + return false; + } else { + continue; + } + } + + $result = substr ($c->buffer, $c->offset, $match - $c->offset); + $c->offset = $match + 1; + + return array (self::TYPE_HEX, $result); + } + break; + + case '<<': + // This is a dictionary. + + $result = array(); + + // Recurse into this function until we reach + // the end of the dictionary. + while (($key = $this->_readToken($c)) !== '>>') { + if ($key === false) { + return false; + } + + if (($value = $this->_readValue($c)) === false) { + return false; + } + + // Catch missing value + if ($value[0] == self::TYPE_TOKEN && $value[1] == '>>') { + $result[$key] = array(self::TYPE_NULL); + break; + } + + $result[$key] = $value; + } + + return array (self::TYPE_DICTIONARY, $result); + + case '[': + // This is an array. + + $result = array(); + + // Recurse into this function until we reach + // the end of the array. + while (($token = $this->_readToken($c)) !== ']') { + if ($token === false) { + return false; + } + + if (($value = $this->_readValue($c, $token)) === false) { + return false; + } + + $result[] = $value; + } + + return array (self::TYPE_ARRAY, $result); + + case '(': + // This is a string + $pos = $c->offset; + + $openBrackets = 1; + do { + for (; $openBrackets != 0 && $pos < $c->length; $pos++) { + switch (ord($c->buffer[$pos])) { + case 0x28: // '(' + $openBrackets++; + break; + case 0x29: // ')' + $openBrackets--; + break; + case 0x5C: // backslash + $pos++; + } + } + } while($openBrackets != 0 && $c->increaseLength()); + + $result = substr($c->buffer, $c->offset, $pos - $c->offset - 1); + $c->offset = $pos; + + return array (self::TYPE_STRING, $result); + + case 'stream': + $tempPos = $c->getPos() - strlen($c->buffer); + $tempOffset = $c->offset; + + $c->reset($startPos = $tempPos + $tempOffset); + + $e = 0; // ensure line breaks in front of the stream + if ($c->buffer[0] == chr(10) || $c->buffer[0] == chr(13)) + $e++; + if ($c->buffer[1] == chr(10) && $c->buffer[0] != chr(10)) + $e++; + + if ($this->_currentObj[1][1]['/Length'][0] == self::TYPE_OBJREF) { + $tmpLength = $this->resolveObject($this->_currentObj[1][1]['/Length']); + $length = $tmpLength[1][1]; + } else { + $length = $this->_currentObj[1][1]['/Length'][1]; + } + + if ($length > 0) { + $c->reset($startPos + $e, $length); + $v = $c->buffer; + } else { + $v = ''; + } + + $c->reset($startPos + $e + $length); + $endstream = $this->_readToken($c); + + if ($endstream != 'endstream') { + $c->reset($startPos + $e + $length + 9); // 9 = strlen("endstream") + // We don't throw an error here because the next + // round trip will start at a new offset + } + + return array(self::TYPE_STREAM, $v); + + default : + if (is_numeric($token)) { + // A numeric token. Make sure that + // it is not part of something else. + if (($tok2 = $this->_readToken($c)) !== false) { + if (is_numeric($tok2)) { + + // Two numeric tokens in a row. + // In this case, we're probably in + // front of either an object reference + // or an object specification. + // Determine the case and return the data + if (($tok3 = $this->_readToken($c)) !== false) { + switch ($tok3) { + case 'obj': + return array(self::TYPE_OBJDEC, (int)$token, (int)$tok2); + case 'R': + return array(self::TYPE_OBJREF, (int)$token, (int)$tok2); + } + // If we get to this point, that numeric value up + // there was just a numeric value. Push the extra + // tokens back into the stack and return the value. + array_push($c->stack, $tok3); + } + } + + array_push($c->stack, $tok2); + } + + if ($token === (string)((int)$token)) + return array(self::TYPE_NUMERIC, (int)$token); + else + return array(self::TYPE_REAL, (float)$token); + } else if ($token == 'true' || $token == 'false') { + return array(self::TYPE_BOOLEAN, $token == 'true'); + } else if ($token == 'null') { + return array(self::TYPE_NULL); + } else { + // Just a token. Return it. + return array(self::TYPE_TOKEN, $token); + } + } + } + + /** + * Resolve an object + * + * @param array $objSpec The object-data + * @return array|boolean + * @throws Exception + */ + public function resolveObject($objSpec) + { + $c = $this->_c; + + // Exit if we get invalid data + if (!is_array($objSpec)) { + return false; + } + + if ($objSpec[0] == self::TYPE_OBJREF) { + + // This is a reference, resolve it + if (isset($this->_xref['xref'][$objSpec[1]][$objSpec[2]])) { + + // Save current file position + // This is needed if you want to resolve + // references while you're reading another object + // (e.g.: if you need to determine the length + // of a stream) + + $oldPos = $c->getPos(); + + // Reposition the file pointer and + // load the object header. + + $c->reset($this->_xref['xref'][$objSpec[1]][$objSpec[2]]); + + $header = $this->_readValue($c); + + if ($header[0] != self::TYPE_OBJDEC || $header[1] != $objSpec[1] || $header[2] != $objSpec[2]) { + $toSearchFor = $objSpec[1] . ' ' . $objSpec[2] . ' obj'; + if (preg_match('/' . $toSearchFor . '/', $c->buffer)) { + $c->offset = strpos($c->buffer, $toSearchFor) + strlen($toSearchFor); + // reset stack + $c->stack = array(); + } else { + throw new Exception( + sprintf("Unable to find object (%s, %s) at expected location.", $objSpec[1], $objSpec[2]) + ); + } + } + + // If we're being asked to store all the information + // about the object, we add the object ID and generation + // number for later use + $result = array ( + self::TYPE_OBJECT, + 'obj' => $objSpec[1], + 'gen' => $objSpec[2] + ); + + $this->_currentObj =& $result; + + // Now simply read the object data until + // we encounter an end-of-object marker + while (true) { + $value = $this->_readValue($c); + if ($value === false || count($result) > 4) { + // in this case the parser couldn't find an "endobj" so we break here + break; + } + + if ($value[0] == self::TYPE_TOKEN && $value[1] === 'endobj') { + break; + } + + $result[] = $value; + } + + $c->reset($oldPos); + + if (isset($result[2][0]) && $result[2][0] == self::TYPE_STREAM) { + $result[0] = self::TYPE_STREAM; + } + + } else { + throw new Exception( + sprintf("Unable to find object (%s, %s) at expected location.", $objSpec[1], $objSpec[2]) + ); + } + + return $result; + } else { + return $objSpec; + } + } + + /** + * Reads a token from the context + * + * @param pdf_context $c + * @return mixed + */ + protected function _readToken($c) + { + // If there is a token available + // on the stack, pop it out and + // return it. + + if (count($c->stack)) { + return array_pop($c->stack); + } + + // Strip away any whitespace + + do { + if (!$c->ensureContent()) { + return false; + } + $c->offset += strspn($c->buffer, "\x20\x0A\x0C\x0D\x09\x00", $c->offset); + } while ($c->offset >= $c->length - 1); + + // Get the first character in the stream + + $char = $c->buffer[$c->offset++]; + + switch ($char) { + + case '[': + case ']': + case '(': + case ')': + + // This is either an array or literal string + // delimiter, Return it + + return $char; + + case '<': + case '>': + + // This could either be a hex string or + // dictionary delimiter. Determine the + // appropriate case and return the token + + if ($c->buffer[$c->offset] == $char) { + if (!$c->ensureContent()) { + return false; + } + $c->offset++; + return $char . $char; + } else { + return $char; + } + + case '%': + + // This is a comment - jump over it! + + $pos = $c->offset; + while(1) { + $match = preg_match("/(\r\n|\r|\n)/", $c->buffer, $m, PREG_OFFSET_CAPTURE, $pos); + if ($match === 0) { + if (!$c->increaseLength()) { + return false; + } else { + continue; + } + } + + $c->offset = $m[0][1] + strlen($m[0][0]); + + return $this->_readToken($c); + } + + default: + + // This is "another" type of token (probably + // a dictionary entry or a numeric value) + // Find the end and return it. + + if (!$c->ensureContent()) { + return false; + } + + while(1) { + + // Determine the length of the token + + $pos = strcspn($c->buffer, "\x20%[]<>()/\x0A\x0C\x0D\x09\x00", $c->offset); + + if ($c->offset + $pos <= $c->length - 1) { + break; + } else { + // If the script reaches this point, + // the token may span beyond the end + // of the current buffer. Therefore, + // we increase the size of the buffer + // and try again--just to be safe. + + $c->increaseLength(); + } + } + + $result = substr($c->buffer, $c->offset - 1, $pos + 1); + + $c->offset += $pos; + + return $result; + } + } + + /** + * Un-filter a stream object + * + * @param array $obj + * @return string + * @throws Exception + */ + protected function _unFilterStream($obj) + { + $filters = array(); + + if (isset($obj[1][1]['/Filter'])) { + $filter = $obj[1][1]['/Filter']; + + if ($filter[0] == pdf_parser::TYPE_OBJREF) { + $tmpFilter = $this->resolveObject($filter); + $filter = $tmpFilter[1]; + } + + if ($filter[0] == pdf_parser::TYPE_TOKEN) { + $filters[] = $filter; + } else if ($filter[0] == pdf_parser::TYPE_ARRAY) { + $filters = $filter[1]; + } + } + + $stream = $obj[2][1]; + + foreach ($filters AS $filter) { + switch ($filter[1]) { + case '/FlateDecode': + case '/Fl': + if (function_exists('gzuncompress')) { + $oStream = $stream; + $stream = (strlen($stream) > 0) ? @gzuncompress($stream) : ''; + } else { + throw new Exception( + sprintf('To handle %s filter, please compile php with zlib support.', $filter[1]) + ); + } + + if ($stream === false) { + $tries = 0; + while ($tries < 8 && ($stream === false || strlen($stream) < strlen($oStream))) { + $oStream = substr($oStream, 1); + $stream = @gzinflate($oStream); + $tries++; + } + + if ($stream === false) { + throw new Exception('Error while decompressing stream.'); + } + } + break; + case '/LZWDecode': + require_once('filters/FilterLZW.php'); + $decoder = new FilterLZW(); + $stream = $decoder->decode($stream); + break; + case '/ASCII85Decode': + require_once('filters/FilterASCII85.php'); + $decoder = new FilterASCII85(); + $stream = $decoder->decode($stream); + break; + case '/ASCIIHexDecode': + require_once('filters/FilterASCIIHexDecode.php'); + $decoder = new FilterASCIIHexDecode(); + $stream = $decoder->decode($stream); + break; + case null: + break; + default: + throw new Exception(sprintf('Unsupported Filter: %s', $filter[1])); + } + } + + return $stream; + } +} \ No newline at end of file From 50990bc8623745a458484f26134dda91ff450367 Mon Sep 17 00:00:00 2001 From: aspangaro Date: Fri, 20 Feb 2015 05:50:36 +0100 Subject: [PATCH 162/173] Update PHPExcel library to 1.8.0 --- COPYRIGHT | 2 +- htdocs/includes/phpexcel/PHPExcel.php | 1572 +++-- .../includes/phpexcel/PHPExcel/Autoloader.php | 84 +- .../PHPExcel/CachedObjectStorage/APC.php | 405 +- .../CachedObjectStorage/CacheBase.php | 131 +- .../PHPExcel/CachedObjectStorage/DiscISAM.php | 40 +- .../PHPExcel/CachedObjectStorage/ICache.php | 16 +- .../PHPExcel/CachedObjectStorage/Igbinary.php | 36 +- .../PHPExcel/CachedObjectStorage/Memcache.php | 54 +- .../PHPExcel/CachedObjectStorage/Memory.php | 32 +- .../CachedObjectStorage/MemoryGZip.php | 36 +- .../CachedObjectStorage/MemorySerialized.php | 36 +- .../PHPExcel/CachedObjectStorage/PHPTemp.php | 36 +- .../PHPExcel/CachedObjectStorage/SQLite.php | 76 +- .../PHPExcel/CachedObjectStorage/SQLite3.php | 154 +- .../PHPExcel/CachedObjectStorage/Wincache.php | 50 +- .../PHPExcel/CachedObjectStorageFactory.php | 404 +- .../CalcEngine/CyclicReferenceStack.php | 98 + .../phpexcel/PHPExcel/CalcEngine/Logger.php | 153 + .../phpexcel/PHPExcel/Calculation.php | 1032 ++-- .../PHPExcel/Calculation/Database.php | 8 +- .../PHPExcel/Calculation/DateTime.php | 38 +- .../PHPExcel/Calculation/Engineering.php | 29 +- .../PHPExcel/Calculation/Exception.php | 10 +- .../PHPExcel/Calculation/ExceptionHandler.php | 8 +- .../PHPExcel/Calculation/Financial.php | 96 +- .../PHPExcel/Calculation/FormulaParser.php | 16 +- .../PHPExcel/Calculation/FormulaToken.php | 8 +- .../PHPExcel/Calculation/Function.php | 16 +- .../PHPExcel/Calculation/Functions.php | 115 +- .../phpexcel/PHPExcel/Calculation/Logical.php | 8 +- .../PHPExcel/Calculation/LookupRef.php | 123 +- .../PHPExcel/Calculation/MathTrig.php | 35 +- .../PHPExcel/Calculation/Statistical.php | 31 +- .../PHPExcel/Calculation/TextData.php | 58 +- .../PHPExcel/Calculation/Token/Stack.php | 70 +- htdocs/includes/phpexcel/PHPExcel/Cell.php | 160 +- .../PHPExcel/Cell/AdvancedValueBinder.php | 284 +- .../phpexcel/PHPExcel/Cell/DataType.php | 148 +- .../phpexcel/PHPExcel/Cell/DataValidation.php | 674 +- .../PHPExcel/Cell/DefaultValueBinder.php | 112 +- .../phpexcel/PHPExcel/Cell/Hyperlink.php | 155 +- .../phpexcel/PHPExcel/Cell/IValueBinder.php | 26 +- htdocs/includes/phpexcel/PHPExcel/Chart.php | 34 +- .../phpexcel/PHPExcel/Chart/DataSeries.php | 19 +- .../PHPExcel/Chart/DataSeriesValues.php | 16 +- .../phpexcel/PHPExcel/Chart/Exception.php | 10 +- .../phpexcel/PHPExcel/Chart/Layout.php | 42 +- .../phpexcel/PHPExcel/Chart/Legend.php | 8 +- .../phpexcel/PHPExcel/Chart/PlotArea.php | 13 +- .../PHPExcel/Chart/Renderer/jpgraph.php | 54 +- .../phpexcel/PHPExcel/Chart/Title.php | 11 +- htdocs/includes/phpexcel/PHPExcel/Comment.php | 224 +- .../phpexcel/PHPExcel/DocumentProperties.php | 1041 ++-- .../phpexcel/PHPExcel/DocumentSecurity.php | 8 +- .../includes/phpexcel/PHPExcel/Exception.php | 40 +- .../includes/phpexcel/PHPExcel/HashTable.php | 18 +- .../phpexcel/PHPExcel/IComparable.php | 6 +- .../includes/phpexcel/PHPExcel/IOFactory.php | 34 +- .../includes/phpexcel/PHPExcel/NamedRange.php | 11 +- .../phpexcel/PHPExcel/Reader/Abstract.php | 227 + .../includes/phpexcel/PHPExcel/Reader/CSV.php | 242 +- .../PHPExcel/Reader/DefaultReadFilter.php | 8 +- .../phpexcel/PHPExcel/Reader/Excel2003XML.php | 154 +- .../phpexcel/PHPExcel/Reader/Excel2007.php | 747 ++- .../PHPExcel/Reader/Excel2007/Chart.php | 16 +- .../PHPExcel/Reader/Excel2007/Theme.php | 8 +- .../phpexcel/PHPExcel/Reader/Excel5.php | 648 +- .../PHPExcel/Reader/Excel5/Escher.php | 8 +- .../phpexcel/PHPExcel/Reader/Excel5/MD5.php | 221 + .../phpexcel/PHPExcel/Reader/Excel5/RC4.php | 88 + .../phpexcel/PHPExcel/Reader/Exception.php | 52 + .../phpexcel/PHPExcel/Reader/Gnumeric.php | 269 +- .../phpexcel/PHPExcel/Reader/HTML.php | 139 +- .../phpexcel/PHPExcel/Reader/IReadFilter.php | 8 +- .../phpexcel/PHPExcel/Reader/IReader.php | 14 +- .../phpexcel/PHPExcel/Reader/OOCalc.php | 1066 ++-- .../phpexcel/PHPExcel/Reader/SYLK.php | 112 +- .../phpexcel/PHPExcel/ReferenceHelper.php | 507 +- .../includes/phpexcel/PHPExcel/RichText.php | 179 +- .../PHPExcel/RichText/ITextElement.php | 6 +- .../phpexcel/PHPExcel/RichText/Run.php | 8 +- .../PHPExcel/RichText/TextElement.php | 6 +- .../includes/phpexcel/PHPExcel/Settings.php | 563 +- .../phpexcel/PHPExcel/Shared/CodePage.php | 21 +- .../phpexcel/PHPExcel/Shared/Date.php | 131 +- .../phpexcel/PHPExcel/Shared/Drawing.php | 8 +- .../phpexcel/PHPExcel/Shared/Escher.php | 8 +- .../PHPExcel/Shared/Escher/DgContainer.php | 8 +- .../Escher/DgContainer/SpgrContainer.php | 8 +- .../DgContainer/SpgrContainer/SpContainer.php | 8 +- .../PHPExcel/Shared/Escher/DggContainer.php | 8 +- .../Escher/DggContainer/BstoreContainer.php | 8 +- .../DggContainer/BstoreContainer/BSE.php | 8 +- .../DggContainer/BstoreContainer/BSE/Blip.php | 8 +- .../phpexcel/PHPExcel/Shared/Excel5.php | 22 +- .../phpexcel/PHPExcel/Shared/File.php | 49 +- .../phpexcel/PHPExcel/Shared/Font.php | 32 +- .../Shared/JAMA/CholeskyDecomposition.php | 8 +- .../PHPExcel/Shared/JAMA/LUDecomposition.php | 12 +- .../phpexcel/PHPExcel/Shared/JAMA/Matrix.php | 124 +- .../PHPExcel/Shared/JAMA/QRDecomposition.php | 6 +- .../Shared/JAMA/examples/LMQuadTest.php | 116 - .../JAMA/examples/LagrangeInterpolation.php | 59 - .../JAMA/examples/LagrangeInterpolation2.php | 59 - .../JAMA/examples/LevenbergMarquardt.php | 185 - .../JAMA/examples/MagicSquareExample.php | 182 - .../PHPExcel/Shared/JAMA/examples/Stats.php | 1605 ----- .../Shared/JAMA/examples/benchmark.php | 263 - .../PHPExcel/Shared/JAMA/examples/polyfit.php | 73 - .../PHPExcel/Shared/JAMA/examples/tile.php | 78 - .../PHPExcel/Shared/JAMA/tests/TestMatrix.php | 415 -- .../PHPExcel/Shared/JAMA/utils/Maths.php | 2 +- .../includes/phpexcel/PHPExcel/Shared/OLE.php | 6 +- .../Shared/OLE/ChainedBlockStream.php | 21 +- .../phpexcel/PHPExcel/Shared/OLE/PPS/Root.php | 4 +- .../phpexcel/PHPExcel/Shared/OLERead.php | 70 +- .../PHPExcel/Shared/PasswordHasher.php | 21 +- .../phpexcel/PHPExcel/Shared/String.php | 98 +- .../phpexcel/PHPExcel/Shared/TimeZone.php | 140 + .../phpexcel/PHPExcel/Shared/XMLWriter.php | 8 +- .../phpexcel/PHPExcel/Shared/ZipArchive.php | 71 +- .../PHPExcel/Shared/ZipStreamWrapper.php | 28 +- .../PHPExcel/Shared/trend/bestFitClass.php | 8 +- .../Shared/trend/exponentialBestFitClass.php | 8 +- .../Shared/trend/linearBestFitClass.php | 8 +- .../Shared/trend/logarithmicBestFitClass.php | 8 +- .../Shared/trend/polynomialBestFitClass.php | 8 +- .../Shared/trend/powerBestFitClass.php | 8 +- .../PHPExcel/Shared/trend/trendClass.php | 8 +- htdocs/includes/phpexcel/PHPExcel/Style.php | 1020 ++-- .../phpexcel/PHPExcel/Style/Alignment.php | 156 +- .../phpexcel/PHPExcel/Style/Border.php | 172 +- .../phpexcel/PHPExcel/Style/Borders.php | 158 +- .../phpexcel/PHPExcel/Style/Color.php | 113 +- .../phpexcel/PHPExcel/Style/Conditional.php | 10 +- .../includes/phpexcel/PHPExcel/Style/Fill.php | 118 +- .../includes/phpexcel/PHPExcel/Style/Font.php | 158 +- .../phpexcel/PHPExcel/Style/NumberFormat.php | 300 +- .../phpexcel/PHPExcel/Style/Protection.php | 121 +- .../phpexcel/PHPExcel/Style/Supervisor.php | 132 + .../includes/phpexcel/PHPExcel/Worksheet.php | 5428 +++++++++-------- .../PHPExcel/Worksheet/AutoFilter.php | 39 +- .../PHPExcel/Worksheet/AutoFilter/Column.php | 31 +- .../Worksheet/AutoFilter/Column/Rule.php | 20 +- .../PHPExcel/Worksheet/BaseDrawing.php | 14 +- .../PHPExcel/Worksheet/CellIterator.php | 8 +- .../PHPExcel/Worksheet/ColumnDimension.php | 12 +- .../phpexcel/PHPExcel/Worksheet/Drawing.php | 12 +- .../PHPExcel/Worksheet/Drawing/Shadow.php | 10 +- .../PHPExcel/Worksheet/HeaderFooter.php | 16 +- .../Worksheet/HeaderFooterDrawing.php | 12 +- .../PHPExcel/Worksheet/MemoryDrawing.php | 8 +- .../PHPExcel/Worksheet/PageMargins.php | 8 +- .../phpexcel/PHPExcel/Worksheet/PageSetup.php | 36 +- .../PHPExcel/Worksheet/Protection.php | 8 +- .../phpexcel/PHPExcel/Worksheet/Row.php | 8 +- .../PHPExcel/Worksheet/RowDimension.php | 12 +- .../PHPExcel/Worksheet/RowIterator.php | 8 +- .../phpexcel/PHPExcel/Worksheet/SheetView.php | 20 +- .../phpexcel/PHPExcel/WorksheetIterator.php | 89 +- .../phpexcel/PHPExcel/Writer/Abstract.php | 158 + .../includes/phpexcel/PHPExcel/Writer/CSV.php | 75 +- .../phpexcel/PHPExcel/Writer/Excel2007.php | 197 +- .../PHPExcel/Writer/Excel2007/Chart.php | 82 +- .../PHPExcel/Writer/Excel2007/Comments.php | 16 +- .../Writer/Excel2007/ContentTypes.php | 56 +- .../PHPExcel/Writer/Excel2007/DocProps.php | 14 +- .../PHPExcel/Writer/Excel2007/Drawing.php | 22 +- .../PHPExcel/Writer/Excel2007/Rels.php | 42 +- .../PHPExcel/Writer/Excel2007/RelsRibbon.php | 77 + .../PHPExcel/Writer/Excel2007/RelsVBA.php | 72 + .../PHPExcel/Writer/Excel2007/StringTable.php | 20 +- .../PHPExcel/Writer/Excel2007/Style.php | 43 +- .../PHPExcel/Writer/Excel2007/Theme.php | 16 +- .../PHPExcel/Writer/Excel2007/Workbook.php | 46 +- .../PHPExcel/Writer/Excel2007/Worksheet.php | 81 +- .../PHPExcel/Writer/Excel2007/WriterPart.php | 16 +- .../phpexcel/PHPExcel/Writer/Excel5.php | 50 +- .../PHPExcel/Writer/Excel5/BIFFwriter.php | 10 +- .../PHPExcel/Writer/Excel5/Escher.php | 8 +- .../phpexcel/PHPExcel/Writer/Excel5/Font.php | 8 +- .../PHPExcel/Writer/Excel5/Parser.php | 57 +- .../PHPExcel/Writer/Excel5/Workbook.php | 22 +- .../PHPExcel/Writer/Excel5/Worksheet.php | 787 ++- .../phpexcel/PHPExcel/Writer/Excel5/Xf.php | 11 +- .../phpexcel/PHPExcel/Writer/Exception.php | 52 + .../phpexcel/PHPExcel/Writer/HTML.php | 301 +- .../phpexcel/PHPExcel/Writer/IWriter.php | 59 +- .../includes/phpexcel/PHPExcel/Writer/PDF.php | 110 +- .../phpexcel/PHPExcel/Writer/PDF/Core.php | 523 +- .../phpexcel/PHPExcel/Writer/PDF/DomPDF.php | 188 +- .../phpexcel/PHPExcel/Writer/PDF/mPDF.php | 201 +- .../phpexcel/PHPExcel/Writer/PDF/tcPDF.php | 217 +- .../phpexcel/PHPExcel/locale/bg/config | 49 + .../phpexcel/PHPExcel/locale/cs/config | 8 +- .../phpexcel/PHPExcel/locale/cs/functions | 8 +- .../phpexcel/PHPExcel/locale/da/config | 8 +- .../phpexcel/PHPExcel/locale/da/functions | 8 +- .../phpexcel/PHPExcel/locale/de/config | 8 +- .../phpexcel/PHPExcel/locale/de/functions | 8 +- .../phpexcel/PHPExcel/locale/en/uk/config | 8 +- .../phpexcel/PHPExcel/locale/es/config | 8 +- .../phpexcel/PHPExcel/locale/es/functions | 8 +- .../phpexcel/PHPExcel/locale/fi/config | 8 +- .../phpexcel/PHPExcel/locale/fi/functions | 8 +- .../phpexcel/PHPExcel/locale/fr/config | 8 +- .../phpexcel/PHPExcel/locale/fr/functions | 8 +- .../phpexcel/PHPExcel/locale/hu/config | 8 +- .../phpexcel/PHPExcel/locale/hu/functions | 8 +- .../phpexcel/PHPExcel/locale/it/config | 8 +- .../phpexcel/PHPExcel/locale/it/functions | 8 +- .../phpexcel/PHPExcel/locale/nl/config | 8 +- .../phpexcel/PHPExcel/locale/nl/functions | 8 +- .../phpexcel/PHPExcel/locale/no/config | 8 +- .../phpexcel/PHPExcel/locale/no/functions | 8 +- .../phpexcel/PHPExcel/locale/pl/config | 8 +- .../phpexcel/PHPExcel/locale/pl/functions | 8 +- .../phpexcel/PHPExcel/locale/pt/br/config | 8 +- .../phpexcel/PHPExcel/locale/pt/br/functions | 2 +- .../phpexcel/PHPExcel/locale/pt/config | 8 +- .../phpexcel/PHPExcel/locale/pt/functions | 2 +- .../phpexcel/PHPExcel/locale/ru/config | 8 +- .../phpexcel/PHPExcel/locale/ru/functions | 8 +- .../phpexcel/PHPExcel/locale/sv/config | 8 +- .../phpexcel/PHPExcel/locale/sv/functions | 2 +- .../phpexcel/PHPExcel/locale/tr/config | 8 +- .../phpexcel/PHPExcel/locale/tr/functions | 8 +- htdocs/includes/phpexcel/changelog.txt | 139 +- htdocs/includes/phpexcel/install.txt | 18 +- 230 files changed, 15081 insertions(+), 14862 deletions(-) create mode 100644 htdocs/includes/phpexcel/PHPExcel/CalcEngine/CyclicReferenceStack.php create mode 100644 htdocs/includes/phpexcel/PHPExcel/CalcEngine/Logger.php create mode 100644 htdocs/includes/phpexcel/PHPExcel/Reader/Abstract.php create mode 100644 htdocs/includes/phpexcel/PHPExcel/Reader/Excel5/MD5.php create mode 100644 htdocs/includes/phpexcel/PHPExcel/Reader/Excel5/RC4.php create mode 100644 htdocs/includes/phpexcel/PHPExcel/Reader/Exception.php delete mode 100644 htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/LMQuadTest.php delete mode 100644 htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/LagrangeInterpolation.php delete mode 100644 htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/LagrangeInterpolation2.php delete mode 100644 htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/LevenbergMarquardt.php delete mode 100644 htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/MagicSquareExample.php delete mode 100644 htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/Stats.php delete mode 100644 htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/benchmark.php delete mode 100644 htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/polyfit.php delete mode 100644 htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/tile.php delete mode 100644 htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/tests/TestMatrix.php create mode 100644 htdocs/includes/phpexcel/PHPExcel/Shared/TimeZone.php create mode 100644 htdocs/includes/phpexcel/PHPExcel/Style/Supervisor.php create mode 100644 htdocs/includes/phpexcel/PHPExcel/Writer/Abstract.php create mode 100644 htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/RelsRibbon.php create mode 100644 htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/RelsVBA.php create mode 100644 htdocs/includes/phpexcel/PHPExcel/Writer/Exception.php create mode 100644 htdocs/includes/phpexcel/PHPExcel/locale/bg/config diff --git a/COPYRIGHT b/COPYRIGHT index cf31432caf0..eec322ef052 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -20,7 +20,7 @@ FPDF_TPL 1.2 Apache Software License 2.0 Yes GeoIP 1.4 LGPL-2.1+ Yes Sample code to make geoip convert (not into deb package) NuSoap 0.9.5 LGPL 2.1+ Yes Library to develop SOAP Web services (not into rpm and deb package) odtPHP 1.0.1 GPL-2+ b Yes Library to build/edit ODT files -PHPExcel 1.7.8 LGPL-2.1+ Yes Read/Write XLS files, read ODS files +PHPExcel 1.8.0 LGPL-2.1+ Yes Read/Write XLS files, read ODS files php-iban 1.4.6 LGPL-3+ Yes Parse and validate IBAN (and IIBAN) bank account information in PHP PHPPrintIPP 1.3 GPL-2+ Yes Library to send print IPP requests TCPDF 6.0.093 LGPL-3+ Yes PDF generation diff --git a/htdocs/includes/phpexcel/PHPExcel.php b/htdocs/includes/phpexcel/PHPExcel.php index f0b39e7961a..bf6f60f5fd0 100644 --- a/htdocs/includes/phpexcel/PHPExcel.php +++ b/htdocs/includes/phpexcel/PHPExcel.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,16 +20,16 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.8.0, 2014-03-02 */ /** PHPExcel root directory */ if (!defined('PHPEXCEL_ROOT')) { - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/'); - require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); } @@ -38,165 +38,441 @@ if (!defined('PHPEXCEL_ROOT')) { * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel { - /** - * Document properties + /** + * Unique ID + * + * @var string + */ + private $_uniqueID; + + /** + * Document properties + * + * @var PHPExcel_DocumentProperties + */ + private $_properties; + + /** + * Document security + * + * @var PHPExcel_DocumentSecurity + */ + private $_security; + + /** + * Collection of Worksheet objects + * + * @var PHPExcel_Worksheet[] + */ + private $_workSheetCollection = array(); + + /** + * Calculation Engine * - * @var PHPExcel_DocumentProperties + * @var PHPExcel_Calculation */ - private $_properties; + private $_calculationEngine = NULL; + + /** + * Active sheet index + * + * @var int + */ + private $_activeSheetIndex = 0; + + /** + * Named ranges + * + * @var PHPExcel_NamedRange[] + */ + private $_namedRanges = array(); + + /** + * CellXf supervisor + * + * @var PHPExcel_Style + */ + private $_cellXfSupervisor; + + /** + * CellXf collection + * + * @var PHPExcel_Style[] + */ + private $_cellXfCollection = array(); + + /** + * CellStyleXf collection + * + * @var PHPExcel_Style[] + */ + private $_cellStyleXfCollection = array(); /** - * Document security - * - * @var PHPExcel_DocumentSecurity - */ - private $_security; + * _hasMacros : this workbook have macros ? + * + * @var bool + */ + private $_hasMacros = FALSE; /** - * Collection of Worksheet objects - * - * @var PHPExcel_Worksheet[] - */ - private $_workSheetCollection = array(); + * _macrosCode : all macros code (the vbaProject.bin file, this include form, code, etc.), NULL if no macro + * + * @var binary + */ + private $_macrosCode=NULL; + /** + * _macrosCertificate : if macros are signed, contains vbaProjectSignature.bin file, NULL if not signed + * + * @var binary + */ + private $_macrosCertificate=NULL; /** - * Active sheet index - * - * @var int - */ - private $_activeSheetIndex = 0; + * _ribbonXMLData : NULL if workbook is'nt Excel 2007 or not contain a customized UI + * + * @var NULL|string + */ + private $_ribbonXMLData=NULL; /** - * Named ranges - * - * @var PHPExcel_NamedRange[] - */ - private $_namedRanges = array(); + * _ribbonBinObjects : NULL if workbook is'nt Excel 2007 or not contain embedded objects (picture(s)) for Ribbon Elements + * ignored if $_ribbonXMLData is null + * + * @var NULL|array + */ + private $_ribbonBinObjects=NULL; /** - * CellXf supervisor - * - * @var PHPExcel_Style - */ - private $_cellXfSupervisor; + * The workbook has macros ? + * + * @return true if workbook has macros, false if not + */ + public function hasMacros(){ + return $this->_hasMacros; + } /** - * CellXf collection - * - * @var PHPExcel_Style[] - */ - private $_cellXfCollection = array(); + * Define if a workbook has macros + * + * @param true|false + */ + public function setHasMacros($hasMacros=false){ + $this->_hasMacros=(bool)$hasMacros; + } /** - * CellStyleXf collection - * - * @var PHPExcel_Style[] - */ - private $_cellStyleXfCollection = array(); + * Set the macros code + * + * @param binary string|null + */ + public function setMacrosCode($MacrosCode){ + $this->_macrosCode=$MacrosCode; + $this->setHasMacros(!is_null($MacrosCode)); + } /** + * Return the macros code + * + * @return binary|null + */ + public function getMacrosCode(){ + return $this->_macrosCode; + } + + /** + * Set the macros certificate + * + * @param binary|null + */ + public function setMacrosCertificate($Certificate=NULL){ + $this->_macrosCertificate=$Certificate; + } + + /** + * Is the project signed ? + * + * @return true|false + */ + public function hasMacrosCertificate(){ + return !is_null($this->_macrosCertificate); + } + + /** + * Return the macros certificate + * + * @return binary|null + */ + public function getMacrosCertificate(){ + return $this->_macrosCertificate; + } + + /** + * Remove all macros, certificate from spreadsheet + * + * @param none + * @return void + */ + public function discardMacros(){ + $this->_hasMacros=false; + $this->_macrosCode=NULL; + $this->_macrosCertificate=NULL; + } + + /** + * set ribbon XML data + * + */ + public function setRibbonXMLData($Target=NULL, $XMLData=NULL){ + if(!is_null($Target) && !is_null($XMLData)){ + $this->_ribbonXMLData=array('target'=>$Target, 'data'=>$XMLData); + }else{ + $this->_ribbonXMLData=NULL; + } + } + + /** + * retrieve ribbon XML Data + * + * return string|null|array + */ + public function getRibbonXMLData($What='all'){//we need some constants here... + $ReturnData=NULL; + $What=strtolower($What); + switch($What){ + case 'all': + $ReturnData=$this->_ribbonXMLData; + break; + case 'target': + case 'data': + if(is_array($this->_ribbonXMLData) && array_key_exists($What,$this->_ribbonXMLData)){ + $ReturnData=$this->_ribbonXMLData[$What]; + }//else $ReturnData stay at null + break; + }//default: $ReturnData at null + return $ReturnData; + } + + /** + * store binaries ribbon objects (pictures) + * + */ + public function setRibbonBinObjects($BinObjectsNames=NULL, $BinObjectsData=NULL){ + if(!is_null($BinObjectsNames) && !is_null($BinObjectsData)){ + $this->_ribbonBinObjects=array('names'=>$BinObjectsNames, 'data'=>$BinObjectsData); + }else{ + $this->_ribbonBinObjects=NULL; + } + } + /** + * return the extension of a filename. Internal use for a array_map callback (php<5.3 don't like lambda function) + * + */ + private function _getExtensionOnly($ThePath){ + return pathinfo($ThePath, PATHINFO_EXTENSION); + } + + /** + * retrieve Binaries Ribbon Objects + * + */ + public function getRibbonBinObjects($What='all'){ + $ReturnData=NULL; + $What=strtolower($What); + switch($What){ + case 'all': + return $this->_ribbonBinObjects; + break; + case 'names': + case 'data': + if(is_array($this->_ribbonBinObjects) && array_key_exists($What, $this->_ribbonBinObjects)){ + $ReturnData=$this->_ribbonBinObjects[$What]; + } + break; + case 'types': + if(is_array($this->_ribbonBinObjects) && array_key_exists('data', $this->_ribbonBinObjects) && is_array($this->_ribbonBinObjects['data'])){ + $tmpTypes=array_keys($this->_ribbonBinObjects['data']); + $ReturnData=array_unique(array_map(array($this,'_getExtensionOnly'), $tmpTypes)); + }else + $ReturnData=array();//the caller want an array... not null if empty + break; + } + return $ReturnData; + } + + /** + * This workbook have a custom UI ? + * + * @return true|false + */ + public function hasRibbon(){ + return !is_null($this->_ribbonXMLData); + } + + /** + * This workbook have additionnal object for the ribbon ? + * + * @return true|false + */ + public function hasRibbonBinObjects(){ + return !is_null($this->_ribbonBinObjects); + } + + /** + * Check if a sheet with a specified code name already exists + * + * @param string $pSheetCodeName Name of the worksheet to check + * @return boolean + */ + public function sheetCodeNameExists($pSheetCodeName) + { + return ($this->getSheetByCodeName($pSheetCodeName) !== NULL); + } + + /** + * Get sheet by code name. Warning : sheet don't have always a code name ! + * + * @param string $pName Sheet name + * @return PHPExcel_Worksheet + */ + public function getSheetByCodeName($pName = '') + { + $worksheetCount = count($this->_workSheetCollection); + for ($i = 0; $i < $worksheetCount; ++$i) { + if ($this->_workSheetCollection[$i]->getCodeName() == $pName) { + return $this->_workSheetCollection[$i]; + } + } + + return null; + } + + /** * Create a new PHPExcel with one Worksheet */ public function __construct() { + $this->_uniqueID = uniqid(); + $this->_calculationEngine = PHPExcel_Calculation::getInstance($this); + // Initialise worksheet collection and add one worksheet $this->_workSheetCollection = array(); $this->_workSheetCollection[] = new PHPExcel_Worksheet($this); $this->_activeSheetIndex = 0; - // Create document properties - $this->_properties = new PHPExcel_DocumentProperties(); + // Create document properties + $this->_properties = new PHPExcel_DocumentProperties(); - // Create document security - $this->_security = new PHPExcel_DocumentSecurity(); + // Create document security + $this->_security = new PHPExcel_DocumentSecurity(); - // Set named ranges - $this->_namedRanges = array(); + // Set named ranges + $this->_namedRanges = array(); - // Create the cellXf supervisor - $this->_cellXfSupervisor = new PHPExcel_Style(true); - $this->_cellXfSupervisor->bindParent($this); + // Create the cellXf supervisor + $this->_cellXfSupervisor = new PHPExcel_Style(true); + $this->_cellXfSupervisor->bindParent($this); - // Create the default style - $this->addCellXf(new PHPExcel_Style); - $this->addCellStyleXf(new PHPExcel_Style); - } + // Create the default style + $this->addCellXf(new PHPExcel_Style); + $this->addCellStyleXf(new PHPExcel_Style); + } + /** + * Code to execute when this worksheet is unset() + * + */ + public function __destruct() { + PHPExcel_Calculation::unsetInstance($this); + $this->disconnectWorksheets(); + } // function __destruct() + + /** + * Disconnect all worksheets from this PHPExcel workbook object, + * typically so that the PHPExcel object can be unset + * + */ + public function disconnectWorksheets() + { + $worksheet = NULL; + foreach($this->_workSheetCollection as $k => &$worksheet) { + $worksheet->disconnectCells(); + $this->_workSheetCollection[$k] = null; + } + unset($worksheet); + $this->_workSheetCollection = array(); + } /** - * Disconnect all worksheets from this PHPExcel workbook object, - * typically so that the PHPExcel object can be unset + * Return the calculation engine for this worksheet * + * @return PHPExcel_Calculation */ - public function disconnectWorksheets() { - foreach($this->_workSheetCollection as $k => &$worksheet) { - $worksheet->disconnectCells(); - $this->_workSheetCollection[$k] = null; - } - unset($worksheet); - $this->_workSheetCollection = array(); - } - - /** - * Get properties - * - * @return PHPExcel_DocumentProperties - */ - public function getProperties() + public function getCalculationEngine() { - return $this->_properties; - } + return $this->_calculationEngine; + } // function getCellCacheController() - /** - * Set properties - * - * @param PHPExcel_DocumentProperties $pValue - */ - public function setProperties(PHPExcel_DocumentProperties $pValue) - { - $this->_properties = $pValue; - } + /** + * Get properties + * + * @return PHPExcel_DocumentProperties + */ + public function getProperties() + { + return $this->_properties; + } - /** - * Get security - * - * @return PHPExcel_DocumentSecurity - */ - public function getSecurity() - { - return $this->_security; - } + /** + * Set properties + * + * @param PHPExcel_DocumentProperties $pValue + */ + public function setProperties(PHPExcel_DocumentProperties $pValue) + { + $this->_properties = $pValue; + } - /** - * Set security - * - * @param PHPExcel_DocumentSecurity $pValue - */ - public function setSecurity(PHPExcel_DocumentSecurity $pValue) - { - $this->_security = $pValue; - } + /** + * Get security + * + * @return PHPExcel_DocumentSecurity + */ + public function getSecurity() + { + return $this->_security; + } - /** - * Get active sheet - * - * @return PHPExcel_Worksheet - */ - public function getActiveSheet() - { - return $this->_workSheetCollection[$this->_activeSheetIndex]; - } + /** + * Set security + * + * @param PHPExcel_DocumentSecurity $pValue + */ + public function setSecurity(PHPExcel_DocumentSecurity $pValue) + { + $this->_security = $pValue; + } + + /** + * Get active sheet + * + * @return PHPExcel_Worksheet + */ + public function getActiveSheet() + { + return $this->_workSheetCollection[$this->_activeSheetIndex]; + } /** * Create sheet and add it to this workbook * - * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last) + * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last) * @return PHPExcel_Worksheet - * @throws Exception + * @throws PHPExcel_Exception */ public function createSheet($iSheetIndex = NULL) { @@ -206,33 +482,35 @@ class PHPExcel } /** - * Chech if a sheet with a specified name already exists + * Check if a sheet with a specified name already exists * - * @param string $pSheetName Name of the worksheet to check + * @param string $pSheetName Name of the worksheet to check * @return boolean */ public function sheetNameExists($pSheetName) { - return ($this->getSheetByName($pSheetName) !== NULL); + return ($this->getSheetByName($pSheetName) !== NULL); } /** * Add sheet * - * @param PHPExcel_Worksheet $pSheet - * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last) + * @param PHPExcel_Worksheet $pSheet + * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last) * @return PHPExcel_Worksheet - * @throws Exception + * @throws PHPExcel_Exception */ public function addSheet(PHPExcel_Worksheet $pSheet, $iSheetIndex = NULL) { - if ($this->sheetNameExists($pSheet->getTitle())) { - throw new Exception("Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename this worksheet first."); - } + if ($this->sheetNameExists($pSheet->getTitle())) { + throw new PHPExcel_Exception( + "Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename this worksheet first." + ); + } if($iSheetIndex === NULL) { if ($this->_activeSheetIndex < 0) { - $this->_activeSheetIndex = 0; + $this->_activeSheetIndex = 0; } $this->_workSheetCollection[] = $pSheet; } else { @@ -244,104 +522,120 @@ class PHPExcel array($pSheet) ); - // Adjust active sheet index if necessary - if ($this->_activeSheetIndex >= $iSheetIndex) { - ++$this->_activeSheetIndex; - } + // Adjust active sheet index if necessary + if ($this->_activeSheetIndex >= $iSheetIndex) { + ++$this->_activeSheetIndex; + } } - return $pSheet; + + if ($pSheet->getParent() === null) { + $pSheet->rebindParent($this); + } + + return $pSheet; } - /** - * Remove sheet by index - * - * @param int $pIndex Active sheet index - * @throws Exception - */ - public function removeSheetByIndex($pIndex = 0) - { - if ($pIndex > count($this->_workSheetCollection) - 1) { - throw new Exception("Sheet index is out of bounds."); - } else { - array_splice($this->_workSheetCollection, $pIndex, 1); - } - // Adjust active sheet index if necessary - if (($this->_activeSheetIndex >= $pIndex) && - ($pIndex > count($this->_workSheetCollection) - 1)) { - --$this->_activeSheetIndex; - } + /** + * Remove sheet by index + * + * @param int $pIndex Active sheet index + * @throws PHPExcel_Exception + */ + public function removeSheetByIndex($pIndex = 0) + { - } + $numSheets = count($this->_workSheetCollection); - /** - * Get sheet by index - * - * @param int $pIndex Sheet index - * @return PHPExcel_Worksheet - * @throws Exception - */ - public function getSheet($pIndex = 0) - { - if ($pIndex > count($this->_workSheetCollection) - 1) { - throw new Exception("Sheet index is out of bounds."); - } else { - return $this->_workSheetCollection[$pIndex]; - } - } + if ($pIndex > $numSheets - 1) { + throw new PHPExcel_Exception( + "You tried to remove a sheet by the out of bounds index: {$pIndex}. The actual number of sheets is {$numSheets}." + ); + } else { + array_splice($this->_workSheetCollection, $pIndex, 1); + } + // Adjust active sheet index if necessary + if (($this->_activeSheetIndex >= $pIndex) && + ($pIndex > count($this->_workSheetCollection) - 1)) { + --$this->_activeSheetIndex; + } - /** - * Get all sheets - * - * @return PHPExcel_Worksheet[] - */ - public function getAllSheets() - { - return $this->_workSheetCollection; - } - - /** - * Get sheet by name - * - * @param string $pName Sheet name - * @return PHPExcel_Worksheet - * @throws Exception - */ - public function getSheetByName($pName = '') - { - $worksheetCount = count($this->_workSheetCollection); - for ($i = 0; $i < $worksheetCount; ++$i) { - if ($this->_workSheetCollection[$i]->getTitle() == $pName) { - return $this->_workSheetCollection[$i]; - } - } - - return null; - } - - /** - * Get index for sheet - * - * @param PHPExcel_Worksheet $pSheet - * @return Sheet index - * @throws Exception - */ - public function getIndex(PHPExcel_Worksheet $pSheet) - { - foreach ($this->_workSheetCollection as $key => $value) { - if ($value->getHashCode() == $pSheet->getHashCode()) { - return $key; - } - } - } + } /** - * Set index for sheet by sheet name. - * - * @param string $sheetName Sheet name to modify index for - * @param int $newIndex New index for the sheet - * @return New sheet index - * @throws Exception - */ + * Get sheet by index + * + * @param int $pIndex Sheet index + * @return PHPExcel_Worksheet + * @throws PHPExcel_Exception + */ + public function getSheet($pIndex = 0) + { + + $numSheets = count($this->_workSheetCollection); + + if ($pIndex > $numSheets - 1) { + throw new PHPExcel_Exception( + "Your requested sheet index: {$pIndex} is out of bounds. The actual number of sheets is {$numSheets}." + ); + } else { + return $this->_workSheetCollection[$pIndex]; + } + } + + /** + * Get all sheets + * + * @return PHPExcel_Worksheet[] + */ + public function getAllSheets() + { + return $this->_workSheetCollection; + } + + /** + * Get sheet by name + * + * @param string $pName Sheet name + * @return PHPExcel_Worksheet + */ + public function getSheetByName($pName = '') + { + $worksheetCount = count($this->_workSheetCollection); + for ($i = 0; $i < $worksheetCount; ++$i) { + if ($this->_workSheetCollection[$i]->getTitle() === $pName) { + return $this->_workSheetCollection[$i]; + } + } + + return NULL; + } + + /** + * Get index for sheet + * + * @param PHPExcel_Worksheet $pSheet + * @return Sheet index + * @throws PHPExcel_Exception + */ + public function getIndex(PHPExcel_Worksheet $pSheet) + { + foreach ($this->_workSheetCollection as $key => $value) { + if ($value->getHashCode() == $pSheet->getHashCode()) { + return $key; + } + } + + throw new PHPExcel_Exception("Sheet does not exist."); + } + + /** + * Set index for sheet by sheet name. + * + * @param string $sheetName Sheet name to modify index for + * @param int $newIndex New index for the sheet + * @return New sheet index + * @throws PHPExcel_Exception + */ public function setIndexByName($sheetName, $newIndex) { $oldIndex = $this->getIndex($this->getSheetByName($sheetName)); @@ -349,475 +643,497 @@ class PHPExcel $this->_workSheetCollection, $oldIndex, 1 - ); + ); array_splice( $this->_workSheetCollection, $newIndex, 0, $pSheet - ); + ); return $newIndex; } - /** - * Get sheet count - * - * @return int - */ - public function getSheetCount() - { - return count($this->_workSheetCollection); - } + /** + * Get sheet count + * + * @return int + */ + public function getSheetCount() + { + return count($this->_workSheetCollection); + } - /** - * Get active sheet index - * - * @return int Active sheet index - */ - public function getActiveSheetIndex() - { - return $this->_activeSheetIndex; - } + /** + * Get active sheet index + * + * @return int Active sheet index + */ + public function getActiveSheetIndex() + { + return $this->_activeSheetIndex; + } - /** - * Set active sheet index - * - * @param int $pIndex Active sheet index - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function setActiveSheetIndex($pIndex = 0) - { - if ($pIndex > count($this->_workSheetCollection) - 1) { - throw new Exception("Active sheet index is out of bounds."); - } else { - $this->_activeSheetIndex = $pIndex; - } - return $this->getActiveSheet(); - } + /** + * Set active sheet index + * + * @param int $pIndex Active sheet index + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setActiveSheetIndex($pIndex = 0) + { + $numSheets = count($this->_workSheetCollection); - /** - * Set active sheet index by name - * - * @param string $pValue Sheet title - * @return PHPExcel_Worksheet - * @throws Exception - */ - public function setActiveSheetIndexByName($pValue = '') - { - if (($worksheet = $this->getSheetByName($pValue)) instanceof PHPExcel_Worksheet) { - $this->setActiveSheetIndex($this->getIndex($worksheet)); - return $worksheet; - } + if ($pIndex > $numSheets - 1) { + throw new PHPExcel_Exception( + "You tried to set a sheet active by the out of bounds index: {$pIndex}. The actual number of sheets is {$numSheets}." + ); + } else { + $this->_activeSheetIndex = $pIndex; + } + return $this->getActiveSheet(); + } - throw new Exception('Workbook does not contain sheet:' . $pValue); - } + /** + * Set active sheet index by name + * + * @param string $pValue Sheet title + * @return PHPExcel_Worksheet + * @throws PHPExcel_Exception + */ + public function setActiveSheetIndexByName($pValue = '') + { + if (($worksheet = $this->getSheetByName($pValue)) instanceof PHPExcel_Worksheet) { + $this->setActiveSheetIndex($this->getIndex($worksheet)); + return $worksheet; + } - /** - * Get sheet names - * - * @return string[] - */ - public function getSheetNames() - { - $returnValue = array(); - $worksheetCount = $this->getSheetCount(); - for ($i = 0; $i < $worksheetCount; ++$i) { - $returnValue[] = $this->getSheet($i)->getTitle(); - } + throw new PHPExcel_Exception('Workbook does not contain sheet:' . $pValue); + } - return $returnValue; - } + /** + * Get sheet names + * + * @return string[] + */ + public function getSheetNames() + { + $returnValue = array(); + $worksheetCount = $this->getSheetCount(); + for ($i = 0; $i < $worksheetCount; ++$i) { + $returnValue[] = $this->getSheet($i)->getTitle(); + } - /** - * Add external sheet - * - * @param PHPExcel_Worksheet $pSheet External sheet to add - * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last) - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function addExternalSheet(PHPExcel_Worksheet $pSheet, $iSheetIndex = null) { - if ($this->sheetNameExists($pSheet->getTitle())) { - throw new Exception("Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename the external sheet first."); - } + return $returnValue; + } - // count how many cellXfs there are in this workbook currently, we will need this below - $countCellXfs = count($this->_cellXfCollection); + /** + * Add external sheet + * + * @param PHPExcel_Worksheet $pSheet External sheet to add + * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function addExternalSheet(PHPExcel_Worksheet $pSheet, $iSheetIndex = null) { + if ($this->sheetNameExists($pSheet->getTitle())) { + throw new PHPExcel_Exception("Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename the external sheet first."); + } - // copy all the shared cellXfs from the external workbook and append them to the current - foreach ($pSheet->getParent()->getCellXfCollection() as $cellXf) { - $this->addCellXf(clone $cellXf); - } + // count how many cellXfs there are in this workbook currently, we will need this below + $countCellXfs = count($this->_cellXfCollection); - // move sheet to this workbook - $pSheet->rebindParent($this); + // copy all the shared cellXfs from the external workbook and append them to the current + foreach ($pSheet->getParent()->getCellXfCollection() as $cellXf) { + $this->addCellXf(clone $cellXf); + } - // update the cellXfs - foreach ($pSheet->getCellCollection(false) as $cellID) { - $cell = $pSheet->getCell($cellID); - $cell->setXfIndex( $cell->getXfIndex() + $countCellXfs ); - } + // move sheet to this workbook + $pSheet->rebindParent($this); - return $this->addSheet($pSheet, $iSheetIndex); - } + // update the cellXfs + foreach ($pSheet->getCellCollection(false) as $cellID) { + $cell = $pSheet->getCell($cellID); + $cell->setXfIndex( $cell->getXfIndex() + $countCellXfs ); + } - /** - * Get named ranges - * - * @return PHPExcel_NamedRange[] - */ - public function getNamedRanges() { - return $this->_namedRanges; - } + return $this->addSheet($pSheet, $iSheetIndex); + } - /** - * Add named range - * - * @param PHPExcel_NamedRange $namedRange - * @return PHPExcel - */ - public function addNamedRange(PHPExcel_NamedRange $namedRange) { - if ($namedRange->getScope() == null) { - // global scope - $this->_namedRanges[$namedRange->getName()] = $namedRange; - } else { - // local scope - $this->_namedRanges[$namedRange->getScope()->getTitle().'!'.$namedRange->getName()] = $namedRange; - } - return true; - } + /** + * Get named ranges + * + * @return PHPExcel_NamedRange[] + */ + public function getNamedRanges() { + return $this->_namedRanges; + } - /** - * Get named range - * - * @param string $namedRange - * @param PHPExcel_Worksheet|null $pSheet Scope. Use null for global scope - * @return PHPExcel_NamedRange|null - */ - public function getNamedRange($namedRange, PHPExcel_Worksheet $pSheet = null) { - $returnValue = null; + /** + * Add named range + * + * @param PHPExcel_NamedRange $namedRange + * @return PHPExcel + */ + public function addNamedRange(PHPExcel_NamedRange $namedRange) { + if ($namedRange->getScope() == null) { + // global scope + $this->_namedRanges[$namedRange->getName()] = $namedRange; + } else { + // local scope + $this->_namedRanges[$namedRange->getScope()->getTitle().'!'.$namedRange->getName()] = $namedRange; + } + return true; + } - if ($namedRange != '' && ($namedRange !== NULL)) { - // first look for global defined name - if (isset($this->_namedRanges[$namedRange])) { - $returnValue = $this->_namedRanges[$namedRange]; - } + /** + * Get named range + * + * @param string $namedRange + * @param PHPExcel_Worksheet|null $pSheet Scope. Use null for global scope + * @return PHPExcel_NamedRange|null + */ + public function getNamedRange($namedRange, PHPExcel_Worksheet $pSheet = null) { + $returnValue = null; - // then look for local defined name (has priority over global defined name if both names exist) - if (($pSheet !== NULL) && isset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange])) { - $returnValue = $this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange]; - } - } + if ($namedRange != '' && ($namedRange !== NULL)) { + // first look for global defined name + if (isset($this->_namedRanges[$namedRange])) { + $returnValue = $this->_namedRanges[$namedRange]; + } - return $returnValue; - } + // then look for local defined name (has priority over global defined name if both names exist) + if (($pSheet !== NULL) && isset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange])) { + $returnValue = $this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange]; + } + } - /** - * Remove named range - * - * @param string $namedRange - * @param PHPExcel_Worksheet|null $pSheet Scope: use null for global scope. - * @return PHPExcel - */ - public function removeNamedRange($namedRange, PHPExcel_Worksheet $pSheet = null) { - if ($pSheet === NULL) { - if (isset($this->_namedRanges[$namedRange])) { - unset($this->_namedRanges[$namedRange]); - } - } else { - if (isset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange])) { - unset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange]); - } - } - return $this; - } + return $returnValue; + } - /** - * Get worksheet iterator - * - * @return PHPExcel_WorksheetIterator - */ - public function getWorksheetIterator() { - return new PHPExcel_WorksheetIterator($this); - } + /** + * Remove named range + * + * @param string $namedRange + * @param PHPExcel_Worksheet|null $pSheet Scope: use null for global scope. + * @return PHPExcel + */ + public function removeNamedRange($namedRange, PHPExcel_Worksheet $pSheet = null) { + if ($pSheet === NULL) { + if (isset($this->_namedRanges[$namedRange])) { + unset($this->_namedRanges[$namedRange]); + } + } else { + if (isset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange])) { + unset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange]); + } + } + return $this; + } - /** - * Copy workbook (!= clone!) - * - * @return PHPExcel - */ - public function copy() { - $copied = clone $this; + /** + * Get worksheet iterator + * + * @return PHPExcel_WorksheetIterator + */ + public function getWorksheetIterator() { + return new PHPExcel_WorksheetIterator($this); + } - $worksheetCount = count($this->_workSheetCollection); - for ($i = 0; $i < $worksheetCount; ++$i) { - $this->_workSheetCollection[$i] = $this->_workSheetCollection[$i]->copy(); - $this->_workSheetCollection[$i]->rebindParent($this); - } + /** + * Copy workbook (!= clone!) + * + * @return PHPExcel + */ + public function copy() { + $copied = clone $this; - return $copied; - } + $worksheetCount = count($this->_workSheetCollection); + for ($i = 0; $i < $worksheetCount; ++$i) { + $this->_workSheetCollection[$i] = $this->_workSheetCollection[$i]->copy(); + $this->_workSheetCollection[$i]->rebindParent($this); + } - /** - * Implement PHP __clone to create a deep clone, not just a shallow copy. - */ - public function __clone() { - foreach($this as $key => $val) { - if (is_object($val) || (is_array($val))) { - $this->{$key} = unserialize(serialize($val)); - } - } - } + return $copied; + } - /** - * Get the workbook collection of cellXfs - * - * @return PHPExcel_Style[] - */ - public function getCellXfCollection() - { - return $this->_cellXfCollection; - } + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + foreach($this as $key => $val) { + if (is_object($val) || (is_array($val))) { + $this->{$key} = unserialize(serialize($val)); + } + } + } - /** - * Get cellXf by index - * - * @param int $pIndex - * @return PHPExcel_Style - */ - public function getCellXfByIndex($pIndex = 0) - { - return $this->_cellXfCollection[$pIndex]; - } + /** + * Get the workbook collection of cellXfs + * + * @return PHPExcel_Style[] + */ + public function getCellXfCollection() + { + return $this->_cellXfCollection; + } - /** - * Get cellXf by hash code - * - * @param string $pValue - * @return PHPExcel_Style|false - */ - public function getCellXfByHashCode($pValue = '') - { - foreach ($this->_cellXfCollection as $cellXf) { - if ($cellXf->getHashCode() == $pValue) { - return $cellXf; - } - } - return false; - } + /** + * Get cellXf by index + * + * @param int $pIndex + * @return PHPExcel_Style + */ + public function getCellXfByIndex($pIndex = 0) + { + return $this->_cellXfCollection[$pIndex]; + } - /** - * Get default style - * - * @return PHPExcel_Style - * @throws Exception - */ - public function getDefaultStyle() - { - if (isset($this->_cellXfCollection[0])) { - return $this->_cellXfCollection[0]; - } - throw new Exception('No default style found for this workbook'); - } + /** + * Get cellXf by hash code + * + * @param string $pValue + * @return PHPExcel_Style|false + */ + public function getCellXfByHashCode($pValue = '') + { + foreach ($this->_cellXfCollection as $cellXf) { + if ($cellXf->getHashCode() == $pValue) { + return $cellXf; + } + } + return false; + } - /** - * Add a cellXf to the workbook - * - * @param PHPExcel_Style $style - */ - public function addCellXf(PHPExcel_Style $style) - { - $this->_cellXfCollection[] = $style; - $style->setIndex(count($this->_cellXfCollection) - 1); - } + /** + * Check if style exists in style collection + * + * @param PHPExcel_Style $pCellStyle + * @return boolean + */ + public function cellXfExists($pCellStyle = null) + { + return in_array($pCellStyle, $this->_cellXfCollection, true); + } - /** - * Remove cellXf by index. It is ensured that all cells get their xf index updated. - * - * @param int $pIndex Index to cellXf - * @throws Exception - */ - public function removeCellXfByIndex($pIndex = 0) - { - if ($pIndex > count($this->_cellXfCollection) - 1) { - throw new Exception("CellXf index is out of bounds."); - } else { - // first remove the cellXf - array_splice($this->_cellXfCollection, $pIndex, 1); + /** + * Get default style + * + * @return PHPExcel_Style + * @throws PHPExcel_Exception + */ + public function getDefaultStyle() + { + if (isset($this->_cellXfCollection[0])) { + return $this->_cellXfCollection[0]; + } + throw new PHPExcel_Exception('No default style found for this workbook'); + } - // then update cellXf indexes for cells - foreach ($this->_workSheetCollection as $worksheet) { - foreach ($worksheet->getCellCollection(false) as $cellID) { - $cell = $worksheet->getCell($cellID); - $xfIndex = $cell->getXfIndex(); - if ($xfIndex > $pIndex ) { - // decrease xf index by 1 - $cell->setXfIndex($xfIndex - 1); - } else if ($xfIndex == $pIndex) { - // set to default xf index 0 - $cell->setXfIndex(0); - } - } - } - } - } + /** + * Add a cellXf to the workbook + * + * @param PHPExcel_Style $style + */ + public function addCellXf(PHPExcel_Style $style) + { + $this->_cellXfCollection[] = $style; + $style->setIndex(count($this->_cellXfCollection) - 1); + } - /** - * Get the cellXf supervisor - * - * @return PHPExcel_Style - */ - public function getCellXfSupervisor() - { - return $this->_cellXfSupervisor; - } + /** + * Remove cellXf by index. It is ensured that all cells get their xf index updated. + * + * @param int $pIndex Index to cellXf + * @throws PHPExcel_Exception + */ + public function removeCellXfByIndex($pIndex = 0) + { + if ($pIndex > count($this->_cellXfCollection) - 1) { + throw new PHPExcel_Exception("CellXf index is out of bounds."); + } else { + // first remove the cellXf + array_splice($this->_cellXfCollection, $pIndex, 1); - /** - * Get the workbook collection of cellStyleXfs - * - * @return PHPExcel_Style[] - */ - public function getCellStyleXfCollection() - { - return $this->_cellStyleXfCollection; - } + // then update cellXf indexes for cells + foreach ($this->_workSheetCollection as $worksheet) { + foreach ($worksheet->getCellCollection(false) as $cellID) { + $cell = $worksheet->getCell($cellID); + $xfIndex = $cell->getXfIndex(); + if ($xfIndex > $pIndex ) { + // decrease xf index by 1 + $cell->setXfIndex($xfIndex - 1); + } else if ($xfIndex == $pIndex) { + // set to default xf index 0 + $cell->setXfIndex(0); + } + } + } + } + } - /** - * Get cellStyleXf by index - * - * @param int $pIndex - * @return PHPExcel_Style - */ - public function getCellStyleXfByIndex($pIndex = 0) - { - return $this->_cellStyleXfCollection[$pIndex]; - } + /** + * Get the cellXf supervisor + * + * @return PHPExcel_Style + */ + public function getCellXfSupervisor() + { + return $this->_cellXfSupervisor; + } - /** - * Get cellStyleXf by hash code - * - * @param string $pValue - * @return PHPExcel_Style|false - */ - public function getCellStyleXfByHashCode($pValue = '') - { - foreach ($this->_cellXfStyleCollection as $cellStyleXf) { - if ($cellStyleXf->getHashCode() == $pValue) { - return $cellStyleXf; - } - } - return false; - } + /** + * Get the workbook collection of cellStyleXfs + * + * @return PHPExcel_Style[] + */ + public function getCellStyleXfCollection() + { + return $this->_cellStyleXfCollection; + } - /** - * Add a cellStyleXf to the workbook - * - * @param PHPExcel_Style $pStyle - */ - public function addCellStyleXf(PHPExcel_Style $pStyle) - { - $this->_cellStyleXfCollection[] = $pStyle; - $pStyle->setIndex(count($this->_cellStyleXfCollection) - 1); - } + /** + * Get cellStyleXf by index + * + * @param int $pIndex + * @return PHPExcel_Style + */ + public function getCellStyleXfByIndex($pIndex = 0) + { + return $this->_cellStyleXfCollection[$pIndex]; + } - /** - * Remove cellStyleXf by index - * - * @param int $pIndex - * @throws Exception - */ - public function removeCellStyleXfByIndex($pIndex = 0) - { - if ($pIndex > count($this->_cellStyleXfCollection) - 1) { - throw new Exception("CellStyleXf index is out of bounds."); - } else { - array_splice($this->_cellStyleXfCollection, $pIndex, 1); - } - } + /** + * Get cellStyleXf by hash code + * + * @param string $pValue + * @return PHPExcel_Style|false + */ + public function getCellStyleXfByHashCode($pValue = '') + { + foreach ($this->_cellXfStyleCollection as $cellStyleXf) { + if ($cellStyleXf->getHashCode() == $pValue) { + return $cellStyleXf; + } + } + return false; + } - /** - * Eliminate all unneeded cellXf and afterwards update the xfIndex for all cells - * and columns in the workbook - */ - public function garbageCollect() - { - // how many references are there to each cellXf ? - $countReferencesCellXf = array(); - foreach ($this->_cellXfCollection as $index => $cellXf) { - $countReferencesCellXf[$index] = 0; - } + /** + * Add a cellStyleXf to the workbook + * + * @param PHPExcel_Style $pStyle + */ + public function addCellStyleXf(PHPExcel_Style $pStyle) + { + $this->_cellStyleXfCollection[] = $pStyle; + $pStyle->setIndex(count($this->_cellStyleXfCollection) - 1); + } - foreach ($this->getWorksheetIterator() as $sheet) { + /** + * Remove cellStyleXf by index + * + * @param int $pIndex + * @throws PHPExcel_Exception + */ + public function removeCellStyleXfByIndex($pIndex = 0) + { + if ($pIndex > count($this->_cellStyleXfCollection) - 1) { + throw new PHPExcel_Exception("CellStyleXf index is out of bounds."); + } else { + array_splice($this->_cellStyleXfCollection, $pIndex, 1); + } + } - // from cells - foreach ($sheet->getCellCollection(false) as $cellID) { - $cell = $sheet->getCell($cellID); - ++$countReferencesCellXf[$cell->getXfIndex()]; - } + /** + * Eliminate all unneeded cellXf and afterwards update the xfIndex for all cells + * and columns in the workbook + */ + public function garbageCollect() + { + // how many references are there to each cellXf ? + $countReferencesCellXf = array(); + foreach ($this->_cellXfCollection as $index => $cellXf) { + $countReferencesCellXf[$index] = 0; + } - // from row dimensions - foreach ($sheet->getRowDimensions() as $rowDimension) { - if ($rowDimension->getXfIndex() !== null) { - ++$countReferencesCellXf[$rowDimension->getXfIndex()]; - } - } + foreach ($this->getWorksheetIterator() as $sheet) { - // from column dimensions - foreach ($sheet->getColumnDimensions() as $columnDimension) { - ++$countReferencesCellXf[$columnDimension->getXfIndex()]; - } - } + // from cells + foreach ($sheet->getCellCollection(false) as $cellID) { + $cell = $sheet->getCell($cellID); + ++$countReferencesCellXf[$cell->getXfIndex()]; + } - // remove cellXfs without references and create mapping so we can update xfIndex - // for all cells and columns - $countNeededCellXfs = 0; - foreach ($this->_cellXfCollection as $index => $cellXf) { - if ($countReferencesCellXf[$index] > 0 || $index == 0) { // we must never remove the first cellXf - ++$countNeededCellXfs; - } else { - unset($this->_cellXfCollection[$index]); - } - $map[$index] = $countNeededCellXfs - 1; - } - $this->_cellXfCollection = array_values($this->_cellXfCollection); + // from row dimensions + foreach ($sheet->getRowDimensions() as $rowDimension) { + if ($rowDimension->getXfIndex() !== null) { + ++$countReferencesCellXf[$rowDimension->getXfIndex()]; + } + } - // update the index for all cellXfs - foreach ($this->_cellXfCollection as $i => $cellXf) { - $cellXf->setIndex($i); - } + // from column dimensions + foreach ($sheet->getColumnDimensions() as $columnDimension) { + ++$countReferencesCellXf[$columnDimension->getXfIndex()]; + } + } - // make sure there is always at least one cellXf (there should be) - if (empty($this->_cellXfCollection)) { - $this->_cellXfCollection[] = new PHPExcel_Style(); - } + // remove cellXfs without references and create mapping so we can update xfIndex + // for all cells and columns + $countNeededCellXfs = 0; + foreach ($this->_cellXfCollection as $index => $cellXf) { + if ($countReferencesCellXf[$index] > 0 || $index == 0) { // we must never remove the first cellXf + ++$countNeededCellXfs; + } else { + unset($this->_cellXfCollection[$index]); + } + $map[$index] = $countNeededCellXfs - 1; + } + $this->_cellXfCollection = array_values($this->_cellXfCollection); - // update the xfIndex for all cells, row dimensions, column dimensions - foreach ($this->getWorksheetIterator() as $sheet) { + // update the index for all cellXfs + foreach ($this->_cellXfCollection as $i => $cellXf) { + $cellXf->setIndex($i); + } - // for all cells - foreach ($sheet->getCellCollection(false) as $cellID) { - $cell = $sheet->getCell($cellID); - $cell->setXfIndex( $map[$cell->getXfIndex()] ); - } + // make sure there is always at least one cellXf (there should be) + if (empty($this->_cellXfCollection)) { + $this->_cellXfCollection[] = new PHPExcel_Style(); + } - // for all row dimensions - foreach ($sheet->getRowDimensions() as $rowDimension) { - if ($rowDimension->getXfIndex() !== null) { - $rowDimension->setXfIndex( $map[$rowDimension->getXfIndex()] ); - } - } + // update the xfIndex for all cells, row dimensions, column dimensions + foreach ($this->getWorksheetIterator() as $sheet) { - // for all column dimensions - foreach ($sheet->getColumnDimensions() as $columnDimension) { - $columnDimension->setXfIndex( $map[$columnDimension->getXfIndex()] ); - } - } + // for all cells + foreach ($sheet->getCellCollection(false) as $cellID) { + $cell = $sheet->getCell($cellID); + $cell->setXfIndex( $map[$cell->getXfIndex()] ); + } - // also do garbage collection for all the sheets - foreach ($this->getWorksheetIterator() as $sheet) { - $sheet->garbageCollect(); - } - } + // for all row dimensions + foreach ($sheet->getRowDimensions() as $rowDimension) { + if ($rowDimension->getXfIndex() !== null) { + $rowDimension->setXfIndex( $map[$rowDimension->getXfIndex()] ); + } + } + + // for all column dimensions + foreach ($sheet->getColumnDimensions() as $columnDimension) { + $columnDimension->setXfIndex( $map[$columnDimension->getXfIndex()] ); + } + + // also do garbage collection for all the sheets + $sheet->garbageCollect(); + } + } + + /** + * Return the unique ID value assigned to this spreadsheet workbook + * + * @return string + */ + public function getID() { + return $this->_uniqueID; + } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Autoloader.php b/htdocs/includes/phpexcel/PHPExcel/Autoloader.php index 15193278b63..a36dfcc905e 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Autoloader.php +++ b/htdocs/includes/phpexcel/PHPExcel/Autoloader.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,18 +20,18 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ PHPExcel_Autoloader::Register(); -// As we always try to run the autoloader before anything else, we can use it to do a few -// simple checks and initialisations -PHPExcel_Shared_ZipStreamWrapper::register(); +// As we always try to run the autoloader before anything else, we can use it to do a few +// simple checks and initialisations +//PHPExcel_Shared_ZipStreamWrapper::register(); // check mbstring.func_overload if (ini_get('mbstring.func_overload') & 2) { - throw new Exception('Multibyte function overloading in PHP must be disabled for string functions (2).'); + throw new PHPExcel_Exception('Multibyte function overloading in PHP must be disabled for string functions (2).'); } PHPExcel_Shared_String::buildCharacterSets(); @@ -39,47 +39,47 @@ PHPExcel_Shared_String::buildCharacterSets(); /** * PHPExcel_Autoloader * - * @category PHPExcel - * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @category PHPExcel + * @package PHPExcel + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Autoloader { - /** - * Register the Autoloader with SPL - * - */ - public static function Register() { - if (function_exists('__autoload')) { - // Register any existing autoloader function with SPL, so we don't get any clashes - spl_autoload_register('__autoload'); - } - // Register ourselves with SPL - return spl_autoload_register(array('PHPExcel_Autoloader', 'Load')); - } // function Register() + /** + * Register the Autoloader with SPL + * + */ + public static function Register() { + if (function_exists('__autoload')) { + // Register any existing autoloader function with SPL, so we don't get any clashes + spl_autoload_register('__autoload'); + } + // Register ourselves with SPL + return spl_autoload_register(array('PHPExcel_Autoloader', 'Load')); + } // function Register() - /** - * Autoload a class identified by name - * - * @param string $pClassName Name of the object to load - */ - public static function Load($pClassName){ - if ((class_exists($pClassName,FALSE)) || (strpos($pClassName, 'PHPExcel') !== 0)) { - // Either already loaded, or not a PHPExcel class request - return FALSE; - } + /** + * Autoload a class identified by name + * + * @param string $pClassName Name of the object to load + */ + public static function Load($pClassName){ + if ((class_exists($pClassName,FALSE)) || (strpos($pClassName, 'PHPExcel') !== 0)) { + // Either already loaded, or not a PHPExcel class request + return FALSE; + } - $pClassFilePath = PHPEXCEL_ROOT . - str_replace('_',DIRECTORY_SEPARATOR,$pClassName) . - '.php'; + $pClassFilePath = PHPEXCEL_ROOT . + str_replace('_',DIRECTORY_SEPARATOR,$pClassName) . + '.php'; - if ((file_exists($pClassFilePath) === false) || (is_readable($pClassFilePath) === false)) { - // Can't load - return FALSE; - } + if ((file_exists($pClassFilePath) === FALSE) || (is_readable($pClassFilePath) === FALSE)) { + // Can't load + return FALSE; + } - require($pClassFilePath); - } // function Load() + require($pClassFilePath); + } // function Load() -} \ No newline at end of file +} diff --git a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/APC.php b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/APC.php index 9dab5581480..0fbf8874c5e 100644 --- a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/APC.php +++ b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/APC.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.8.0, 2014-03-02 */ @@ -31,250 +31,265 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_CachedObjectStorage_APC extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache { - /** - * Prefix used to uniquely identify cache data for this worksheet - * - * @access private - * @var string - */ - private $_cachePrefix = null; + /** + * Prefix used to uniquely identify cache data for this worksheet + * + * @access private + * @var string + */ + private $_cachePrefix = null; - /** - * Cache timeout - * - * @access private - * @var integer - */ - private $_cacheTime = 600; + /** + * Cache timeout + * + * @access private + * @var integer + */ + private $_cacheTime = 600; /** * Store cell data in cache for the current cell object if it's "dirty", * and the 'nullify' the current cell object * - * @access private - * @return void - * @throws Exception + * @access private + * @return void + * @throws PHPExcel_Exception */ - private function _storeData() { - if ($this->_currentCellIsDirty) { - $this->_currentObject->detach(); + protected function _storeData() { + if ($this->_currentCellIsDirty && !empty($this->_currentObjectID)) { + $this->_currentObject->detach(); - if (!apc_store($this->_cachePrefix.$this->_currentObjectID.'.cache',serialize($this->_currentObject),$this->_cacheTime)) { - $this->__destruct(); - throw new Exception('Failed to store cell '.$this->_currentObjectID.' in APC'); - } - $this->_currentCellIsDirty = false; - } - $this->_currentObjectID = $this->_currentObject = null; - } // function _storeData() + if (!apc_store($this->_cachePrefix.$this->_currentObjectID.'.cache',serialize($this->_currentObject),$this->_cacheTime)) { + $this->__destruct(); + throw new PHPExcel_Exception('Failed to store cell '.$this->_currentObjectID.' in APC'); + } + $this->_currentCellIsDirty = false; + } + $this->_currentObjectID = $this->_currentObject = null; + } // function _storeData() /** * Add or Update a cell in cache identified by coordinate address * - * @access public - * @param string $pCoord Coordinate address of the cell to update - * @param PHPExcel_Cell $cell Cell to update - * @return void - * @throws Exception + * @access public + * @param string $pCoord Coordinate address of the cell to update + * @param PHPExcel_Cell $cell Cell to update + * @return void + * @throws PHPExcel_Exception */ - public function addCacheData($pCoord, PHPExcel_Cell $cell) { - if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { - $this->_storeData(); - } - $this->_cellCache[$pCoord] = true; + public function addCacheData($pCoord, PHPExcel_Cell $cell) { + if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { + $this->_storeData(); + } + $this->_cellCache[$pCoord] = true; - $this->_currentObjectID = $pCoord; - $this->_currentObject = $cell; - $this->_currentCellIsDirty = true; + $this->_currentObjectID = $pCoord; + $this->_currentObject = $cell; + $this->_currentCellIsDirty = true; - return $cell; - } // function addCacheData() + return $cell; + } // function addCacheData() - /** - * Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell? - * - * @access public - * @param string $pCoord Coordinate address of the cell to check - * @return void - * @return boolean - */ - public function isDataSet($pCoord) { - // Check if the requested entry is the current object, or exists in the cache - if (parent::isDataSet($pCoord)) { - if ($this->_currentObjectID == $pCoord) { - return true; - } - // Check if the requested entry still exists in apc - $success = apc_fetch($this->_cachePrefix.$pCoord.'.cache'); - if ($success === false) { - // Entry no longer exists in APC, so clear it from the cache array - parent::deleteCacheData($pCoord); - throw new Exception('Cell entry '.$pCoord.' no longer exists in APC'); - } - return true; - } - return false; - } // function isDataSet() + /** + * Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell? + * + * @access public + * @param string $pCoord Coordinate address of the cell to check + * @return void + * @return boolean + */ + public function isDataSet($pCoord) { + // Check if the requested entry is the current object, or exists in the cache + if (parent::isDataSet($pCoord)) { + if ($this->_currentObjectID == $pCoord) { + return true; + } + // Check if the requested entry still exists in apc + $success = apc_fetch($this->_cachePrefix.$pCoord.'.cache'); + if ($success === FALSE) { + // Entry no longer exists in APC, so clear it from the cache array + parent::deleteCacheData($pCoord); + throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in APC cache'); + } + return true; + } + return false; + } // function isDataSet() /** * Get cell at a specific coordinate * - * @access public - * @param string $pCoord Coordinate of the cell - * @throws Exception - * @return PHPExcel_Cell Cell that was found, or null if not found + * @access public + * @param string $pCoord Coordinate of the cell + * @throws PHPExcel_Exception + * @return PHPExcel_Cell Cell that was found, or null if not found */ - public function getCacheData($pCoord) { - if ($pCoord === $this->_currentObjectID) { - return $this->_currentObject; - } - $this->_storeData(); + public function getCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return $this->_currentObject; + } + $this->_storeData(); - // Check if the entry that has been requested actually exists - if (parent::isDataSet($pCoord)) { - $obj = apc_fetch($this->_cachePrefix.$pCoord.'.cache'); - if ($obj === false) { - // Entry no longer exists in APC, so clear it from the cache array - parent::deleteCacheData($pCoord); - throw new Exception('Cell entry '.$pCoord.' no longer exists in APC'); - } - } else { - // Return null if requested entry doesn't exist in cache - return null; + // Check if the entry that has been requested actually exists + if (parent::isDataSet($pCoord)) { + $obj = apc_fetch($this->_cachePrefix.$pCoord.'.cache'); + if ($obj === FALSE) { + // Entry no longer exists in APC, so clear it from the cache array + parent::deleteCacheData($pCoord); + throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in APC cache'); + } + } else { + // Return null if requested entry doesn't exist in cache + return null; + } + + // Set current entry to the requested entry + $this->_currentObjectID = $pCoord; + $this->_currentObject = unserialize($obj); + // Re-attach this as the cell's parent + $this->_currentObject->attach($this); + + // Return requested entry + return $this->_currentObject; + } // function getCacheData() + + + /** + * Get a list of all cell addresses currently held in cache + * + * @return array of string + */ + public function getCellList() { + if ($this->_currentObjectID !== null) { + $this->_storeData(); } - // Set current entry to the requested entry - $this->_currentObjectID = $pCoord; - $this->_currentObject = unserialize($obj); - // Re-attach the parent worksheet - $this->_currentObject->attach($this->_parent); - - // Return requested entry - return $this->_currentObject; - } // function getCacheData() + return parent::getCellList(); + } /** * Delete a cell in cache identified by coordinate address * - * @access public - * @param string $pCoord Coordinate address of the cell to delete - * @throws Exception + * @access public + * @param string $pCoord Coordinate address of the cell to delete + * @throws PHPExcel_Exception */ - public function deleteCacheData($pCoord) { - // Delete the entry from APC - apc_delete($this->_cachePrefix.$pCoord.'.cache'); + public function deleteCacheData($pCoord) { + // Delete the entry from APC + apc_delete($this->_cachePrefix.$pCoord.'.cache'); - // Delete the entry from our cell address array - parent::deleteCacheData($pCoord); - } // function deleteCacheData() + // Delete the entry from our cell address array + parent::deleteCacheData($pCoord); + } // function deleteCacheData() - /** - * Clone the cell collection - * - * @access public - * @param PHPExcel_Worksheet $parent The new worksheet - * @return void - */ - public function copyCellCollection(PHPExcel_Worksheet $parent) { - parent::copyCellCollection($parent); - // Get a new id for the new file name - $baseUnique = $this->_getUniqueID(); - $newCachePrefix = substr(md5($baseUnique),0,8).'.'; - $cacheList = $this->getCellList(); - foreach($cacheList as $cellID) { - if ($cellID != $this->_currentObjectID) { - $obj = apc_fetch($this->_cachePrefix.$cellID.'.cache'); - if ($obj === false) { - // Entry no longer exists in APC, so clear it from the cache array - parent::deleteCacheData($cellID); - throw new Exception('Cell entry '.$cellID.' no longer exists in APC'); - } - if (!apc_store($newCachePrefix.$cellID.'.cache',$obj,$this->_cacheTime)) { - $this->__destruct(); - throw new Exception('Failed to store cell '.$cellID.' in APC'); - } - } - } - $this->_cachePrefix = $newCachePrefix; - } // function copyCellCollection() + /** + * Clone the cell collection + * + * @access public + * @param PHPExcel_Worksheet $parent The new worksheet + * @throws PHPExcel_Exception + * @return void + */ + public function copyCellCollection(PHPExcel_Worksheet $parent) { + parent::copyCellCollection($parent); + // Get a new id for the new file name + $baseUnique = $this->_getUniqueID(); + $newCachePrefix = substr(md5($baseUnique),0,8).'.'; + $cacheList = $this->getCellList(); + foreach($cacheList as $cellID) { + if ($cellID != $this->_currentObjectID) { + $obj = apc_fetch($this->_cachePrefix.$cellID.'.cache'); + if ($obj === FALSE) { + // Entry no longer exists in APC, so clear it from the cache array + parent::deleteCacheData($cellID); + throw new PHPExcel_Exception('Cell entry '.$cellID.' no longer exists in APC'); + } + if (!apc_store($newCachePrefix.$cellID.'.cache',$obj,$this->_cacheTime)) { + $this->__destruct(); + throw new PHPExcel_Exception('Failed to store cell '.$cellID.' in APC'); + } + } + } + $this->_cachePrefix = $newCachePrefix; + } // function copyCellCollection() - /** - * Clear the cell collection and disconnect from our parent - * - * @return void - */ - public function unsetWorksheetCells() { - if ($this->_currentObject !== NULL) { - $this->_currentObject->detach(); - $this->_currentObject = $this->_currentObjectID = null; - } + /** + * Clear the cell collection and disconnect from our parent + * + * @return void + */ + public function unsetWorksheetCells() { + if ($this->_currentObject !== NULL) { + $this->_currentObject->detach(); + $this->_currentObject = $this->_currentObjectID = null; + } - // Flush the APC cache - $this->__destruct(); + // Flush the APC cache + $this->__destruct(); - $this->_cellCache = array(); + $this->_cellCache = array(); - // detach ourself from the worksheet, so that it can then delete this object successfully - $this->_parent = null; - } // function unsetWorksheetCells() + // detach ourself from the worksheet, so that it can then delete this object successfully + $this->_parent = null; + } // function unsetWorksheetCells() - /** - * Initialise this new cell collection - * - * @param PHPExcel_Worksheet $parent The worksheet for this cell collection - * @param array of mixed $arguments Additional initialisation arguments - */ - public function __construct(PHPExcel_Worksheet $parent, $arguments) { - $cacheTime = (isset($arguments['cacheTime'])) ? $arguments['cacheTime'] : 600; + /** + * Initialise this new cell collection + * + * @param PHPExcel_Worksheet $parent The worksheet for this cell collection + * @param array of mixed $arguments Additional initialisation arguments + */ + public function __construct(PHPExcel_Worksheet $parent, $arguments) { + $cacheTime = (isset($arguments['cacheTime'])) ? $arguments['cacheTime'] : 600; - if ($this->_cachePrefix === NULL) { - $baseUnique = $this->_getUniqueID(); - $this->_cachePrefix = substr(md5($baseUnique),0,8).'.'; - $this->_cacheTime = $cacheTime; + if ($this->_cachePrefix === NULL) { + $baseUnique = $this->_getUniqueID(); + $this->_cachePrefix = substr(md5($baseUnique),0,8).'.'; + $this->_cacheTime = $cacheTime; - parent::__construct($parent); - } - } // function __construct() + parent::__construct($parent); + } + } // function __construct() - /** - * Destroy this cell collection - */ - public function __destruct() { - $cacheList = $this->getCellList(); - foreach($cacheList as $cellID) { - apc_delete($this->_cachePrefix.$cellID.'.cache'); - } - } // function __destruct() + /** + * Destroy this cell collection + */ + public function __destruct() { + $cacheList = $this->getCellList(); + foreach($cacheList as $cellID) { + apc_delete($this->_cachePrefix.$cellID.'.cache'); + } + } // function __destruct() - /** - * Identify whether the caching method is currently available - * Some methods are dependent on the availability of certain extensions being enabled in the PHP build - * - * @return boolean - */ - public static function cacheMethodIsAvailable() { - if (!function_exists('apc_store')) { - return false; - } - if (apc_sma_info() === false) { - return false; - } + /** + * Identify whether the caching method is currently available + * Some methods are dependent on the availability of certain extensions being enabled in the PHP build + * + * @return boolean + */ + public static function cacheMethodIsAvailable() { + if (!function_exists('apc_store')) { + return FALSE; + } + if (apc_sma_info() === FALSE) { + return FALSE; + } - return true; - } + return TRUE; + } } diff --git a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/CacheBase.php b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/CacheBase.php index d2eea08bb97..84a0416c3b6 100644 --- a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/CacheBase.php +++ b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/CacheBase.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ abstract class PHPExcel_CachedObjectStorage_CacheBase { @@ -86,6 +86,16 @@ abstract class PHPExcel_CachedObjectStorage_CacheBase { } // function __construct() + /** + * Return the parent worksheet for this cell collection + * + * @return PHPExcel_Worksheet + */ + public function getParent() + { + return $this->_parent; + } + /** * Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell? * @@ -101,12 +111,33 @@ abstract class PHPExcel_CachedObjectStorage_CacheBase { } // function isDataSet() + /** + * Move a cell object from one address to another + * + * @param string $fromAddress Current address of the cell to move + * @param string $toAddress Destination address of the cell to move + * @return boolean + */ + public function moveCell($fromAddress, $toAddress) { + if ($fromAddress === $this->_currentObjectID) { + $this->_currentObjectID = $toAddress; + } + $this->_currentCellIsDirty = true; + if (isset($this->_cellCache[$fromAddress])) { + $this->_cellCache[$toAddress] = &$this->_cellCache[$fromAddress]; + unset($this->_cellCache[$fromAddress]); + } + + return TRUE; + } // function moveCell() + + /** * Add or Update a cell in cache * * @param PHPExcel_Cell $cell Cell to update * @return void - * @throws Exception + * @throws PHPExcel_Exception */ public function updateCacheData(PHPExcel_Cell $cell) { return $this->addCacheData($cell->getCoordinate(),$cell); @@ -117,7 +148,7 @@ abstract class PHPExcel_CachedObjectStorage_CacheBase { * Delete a cell in cache identified by coordinate address * * @param string $pCoord Coordinate address of the cell to delete - * @throws Exception + * @throws PHPExcel_Exception */ public function deleteCacheData($pCoord) { if ($pCoord === $this->_currentObjectID) { @@ -151,7 +182,7 @@ abstract class PHPExcel_CachedObjectStorage_CacheBase { public function getSortedCellList() { $sortKeys = array(); foreach ($this->getCellList() as $coord) { - list($column,$row) = sscanf($coord,'%[A-Z]%d'); + sscanf($coord,'%[A-Z]%d', $column, $row); $sortKeys[sprintf('%09d%3s',$row,$column)] = $coord; } ksort($sortKeys); @@ -172,7 +203,7 @@ abstract class PHPExcel_CachedObjectStorage_CacheBase { $col = array('A' => '1A'); $row = array(1); foreach ($this->getCellList() as $coord) { - list($c,$r) = sscanf($coord,'%[A-Z]%d'); + sscanf($coord,'%[A-Z]%d', $c, $r); $row[$r] = $r; $col[$c] = strlen($c).$c; } @@ -188,26 +219,87 @@ abstract class PHPExcel_CachedObjectStorage_CacheBase { } + /** + * Return the cell address of the currently active cell object + * + * @return string + */ + public function getCurrentAddress() + { + return $this->_currentObjectID; + } + + /** + * Return the column address of the currently active cell object + * + * @return string + */ + public function getCurrentColumn() + { + sscanf($this->_currentObjectID, '%[A-Z]%d', $column, $row); + return $column; + } + + /** + * Return the row address of the currently active cell object + * + * @return string + */ + public function getCurrentRow() + { + sscanf($this->_currentObjectID, '%[A-Z]%d', $column, $row); + return $row; + } + /** * Get highest worksheet column * - * @return string Highest column name + * @param string $row Return the highest column for the specified row, + * or the highest column of any row if no row number is passed + * @return string Highest column name */ - public function getHighestColumn() + public function getHighestColumn($row = null) { - $colRow = $this->getHighestRowAndColumn(); - return $colRow['column']; - } + if ($row == null) { + $colRow = $this->getHighestRowAndColumn(); + return $colRow['column']; + } + + $columnList = array(1); + foreach ($this->getCellList() as $coord) { + sscanf($coord,'%[A-Z]%d', $c, $r); + if ($r != $row) { + continue; + } + $columnList[] = PHPExcel_Cell::columnIndexFromString($c); + } + return PHPExcel_Cell::stringFromColumnIndex(max($columnList) - 1); + } /** * Get highest worksheet row * - * @return int Highest row number + * @param string $column Return the highest row for the specified column, + * or the highest row of any column if no column letter is passed + * @return int Highest row number */ - public function getHighestRow() + public function getHighestRow($column = null) { - $colRow = $this->getHighestRowAndColumn(); - return $colRow['row']; + if ($column == null) { + $colRow = $this->getHighestRowAndColumn(); + return $colRow['row']; + } + + $rowList = array(0); + foreach ($this->getCellList() as $coord) { + sscanf($coord,'%[A-Z]%d', $c, $r); + if ($c != $column) { + continue; + } + $rowList[] = $r; + } + + return max($rowList); } @@ -232,9 +324,12 @@ abstract class PHPExcel_CachedObjectStorage_CacheBase { * @return void */ public function copyCellCollection(PHPExcel_Worksheet $parent) { + $this->_currentCellIsDirty; + $this->_storeData(); + $this->_parent = $parent; if (($this->_currentObject !== NULL) && (is_object($this->_currentObject))) { - $this->_currentObject->attach($parent); + $this->_currentObject->attach($this); } } // function copyCellCollection() diff --git a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/DiscISAM.php b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/DiscISAM.php index 805dc063ace..492abea8526 100644 --- a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/DiscISAM.php +++ b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/DiscISAM.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_CachedObjectStorage_DiscISAM extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache { @@ -40,14 +40,14 @@ class PHPExcel_CachedObjectStorage_DiscISAM extends PHPExcel_CachedObjectStorage * * @var string */ - private $_fileName = null; + private $_fileName = NULL; /** * File handle for this cache file * * @var resource */ - private $_fileHandle = null; + private $_fileHandle = NULL; /** * Directory/Folder where the cache file is located @@ -62,10 +62,10 @@ class PHPExcel_CachedObjectStorage_DiscISAM extends PHPExcel_CachedObjectStorage * and the 'nullify' the current cell object * * @return void - * @throws Exception + * @throws PHPExcel_Exception */ - private function _storeData() { - if ($this->_currentCellIsDirty) { + protected function _storeData() { + if ($this->_currentCellIsDirty && !empty($this->_currentObjectID)) { $this->_currentObject->detach(); fseek($this->_fileHandle,0,SEEK_END); @@ -86,7 +86,7 @@ class PHPExcel_CachedObjectStorage_DiscISAM extends PHPExcel_CachedObjectStorage * @param string $pCoord Coordinate address of the cell to update * @param PHPExcel_Cell $cell Cell to update * @return void - * @throws Exception + * @throws PHPExcel_Exception */ public function addCacheData($pCoord, PHPExcel_Cell $cell) { if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { @@ -105,7 +105,7 @@ class PHPExcel_CachedObjectStorage_DiscISAM extends PHPExcel_CachedObjectStorage * Get cell at a specific coordinate * * @param string $pCoord Coordinate of the cell - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Cell Cell that was found, or null if not found */ public function getCacheData($pCoord) { @@ -124,14 +124,28 @@ class PHPExcel_CachedObjectStorage_DiscISAM extends PHPExcel_CachedObjectStorage $this->_currentObjectID = $pCoord; fseek($this->_fileHandle,$this->_cellCache[$pCoord]['ptr']); $this->_currentObject = unserialize(fread($this->_fileHandle,$this->_cellCache[$pCoord]['sz'])); - // Re-attach the parent worksheet - $this->_currentObject->attach($this->_parent); + // Re-attach this as the cell's parent + $this->_currentObject->attach($this); // Return requested entry return $this->_currentObject; } // function getCacheData() + /** + * Get a list of all cell addresses currently held in cache + * + * @return array of string + */ + public function getCellList() { + if ($this->_currentObjectID !== null) { + $this->_storeData(); + } + + return parent::getCellList(); + } + + /** * Clone the cell collection * diff --git a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/ICache.php b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/ICache.php index 56f621a597b..c3f2c14d74b 100644 --- a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/ICache.php +++ b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/ICache.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ interface PHPExcel_CachedObjectStorage_ICache { @@ -41,7 +41,7 @@ interface PHPExcel_CachedObjectStorage_ICache * @param string $pCoord Coordinate address of the cell to update * @param PHPExcel_Cell $cell Cell to update * @return void - * @throws Exception + * @throws PHPExcel_Exception */ public function addCacheData($pCoord, PHPExcel_Cell $cell); @@ -50,7 +50,7 @@ interface PHPExcel_CachedObjectStorage_ICache * * @param PHPExcel_Cell $cell Cell to update * @return void - * @throws Exception + * @throws PHPExcel_Exception */ public function updateCacheData(PHPExcel_Cell $cell); @@ -59,7 +59,7 @@ interface PHPExcel_CachedObjectStorage_ICache * * @param string $pCoord Coordinate address of the cell to retrieve * @return PHPExcel_Cell Cell that was found, or null if not found - * @throws Exception + * @throws PHPExcel_Exception */ public function getCacheData($pCoord); @@ -67,7 +67,7 @@ interface PHPExcel_CachedObjectStorage_ICache * Delete a cell in cache identified by coordinate address * * @param string $pCoord Coordinate address of the cell to delete - * @throws Exception + * @throws PHPExcel_Exception */ public function deleteCacheData($pCoord); diff --git a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/Igbinary.php b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/Igbinary.php index fc2f1129917..c3056de1fb6 100644 --- a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/Igbinary.php +++ b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/Igbinary.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_CachedObjectStorage_Igbinary extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache { @@ -40,10 +40,10 @@ class PHPExcel_CachedObjectStorage_Igbinary extends PHPExcel_CachedObjectStorage * and the 'nullify' the current cell object * * @return void - * @throws Exception + * @throws PHPExcel_Exception */ - private function _storeData() { - if ($this->_currentCellIsDirty) { + protected function _storeData() { + if ($this->_currentCellIsDirty && !empty($this->_currentObjectID)) { $this->_currentObject->detach(); $this->_cellCache[$this->_currentObjectID] = igbinary_serialize($this->_currentObject); @@ -59,7 +59,7 @@ class PHPExcel_CachedObjectStorage_Igbinary extends PHPExcel_CachedObjectStorage * @param string $pCoord Coordinate address of the cell to update * @param PHPExcel_Cell $cell Cell to update * @return void - * @throws Exception + * @throws PHPExcel_Exception */ public function addCacheData($pCoord, PHPExcel_Cell $cell) { if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { @@ -78,7 +78,7 @@ class PHPExcel_CachedObjectStorage_Igbinary extends PHPExcel_CachedObjectStorage * Get cell at a specific coordinate * * @param string $pCoord Coordinate of the cell - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Cell Cell that was found, or null if not found */ public function getCacheData($pCoord) { @@ -96,14 +96,28 @@ class PHPExcel_CachedObjectStorage_Igbinary extends PHPExcel_CachedObjectStorage // Set current entry to the requested entry $this->_currentObjectID = $pCoord; $this->_currentObject = igbinary_unserialize($this->_cellCache[$pCoord]); - // Re-attach the parent worksheet - $this->_currentObject->attach($this->_parent); + // Re-attach this as the cell's parent + $this->_currentObject->attach($this); // Return requested entry return $this->_currentObject; } // function getCacheData() + /** + * Get a list of all cell addresses currently held in cache + * + * @return array of string + */ + public function getCellList() { + if ($this->_currentObjectID !== null) { + $this->_storeData(); + } + + return parent::getCellList(); + } + + /** * Clear the cell collection and disconnect from our parent * diff --git a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/Memcache.php b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/Memcache.php index 23d6957281f..9061a31a1d1 100644 --- a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/Memcache.php +++ b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/Memcache.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_CachedObjectStorage_Memcache extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache { @@ -62,17 +62,17 @@ class PHPExcel_CachedObjectStorage_Memcache extends PHPExcel_CachedObjectStorage * and the 'nullify' the current cell object * * @return void - * @throws Exception + * @throws PHPExcel_Exception */ - private function _storeData() { - if ($this->_currentCellIsDirty) { + protected function _storeData() { + if ($this->_currentCellIsDirty && !empty($this->_currentObjectID)) { $this->_currentObject->detach(); $obj = serialize($this->_currentObject); if (!$this->_memcache->replace($this->_cachePrefix.$this->_currentObjectID.'.cache',$obj,NULL,$this->_cacheTime)) { if (!$this->_memcache->add($this->_cachePrefix.$this->_currentObjectID.'.cache',$obj,NULL,$this->_cacheTime)) { $this->__destruct(); - throw new Exception('Failed to store cell '.$this->_currentObjectID.' in MemCache'); + throw new PHPExcel_Exception('Failed to store cell '.$this->_currentObjectID.' in MemCache'); } } $this->_currentCellIsDirty = false; @@ -87,7 +87,7 @@ class PHPExcel_CachedObjectStorage_Memcache extends PHPExcel_CachedObjectStorage * @param string $pCoord Coordinate address of the cell to update * @param PHPExcel_Cell $cell Cell to update * @return void - * @throws Exception + * @throws PHPExcel_Exception */ public function addCacheData($pCoord, PHPExcel_Cell $cell) { if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { @@ -121,7 +121,7 @@ class PHPExcel_CachedObjectStorage_Memcache extends PHPExcel_CachedObjectStorage if ($success === false) { // Entry no longer exists in Memcache, so clear it from the cache array parent::deleteCacheData($pCoord); - throw new Exception('Cell entry '.$pCoord.' no longer exists in MemCache'); + throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in MemCache'); } return true; } @@ -133,7 +133,7 @@ class PHPExcel_CachedObjectStorage_Memcache extends PHPExcel_CachedObjectStorage * Get cell at a specific coordinate * * @param string $pCoord Coordinate of the cell - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Cell Cell that was found, or null if not found */ public function getCacheData($pCoord) { @@ -148,7 +148,7 @@ class PHPExcel_CachedObjectStorage_Memcache extends PHPExcel_CachedObjectStorage if ($obj === false) { // Entry no longer exists in Memcache, so clear it from the cache array parent::deleteCacheData($pCoord); - throw new Exception('Cell entry '.$pCoord.' no longer exists in MemCache'); + throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in MemCache'); } } else { // Return null if requested entry doesn't exist in cache @@ -158,19 +158,33 @@ class PHPExcel_CachedObjectStorage_Memcache extends PHPExcel_CachedObjectStorage // Set current entry to the requested entry $this->_currentObjectID = $pCoord; $this->_currentObject = unserialize($obj); - // Re-attach the parent worksheet - $this->_currentObject->attach($this->_parent); + // Re-attach this as the cell's parent + $this->_currentObject->attach($this); // Return requested entry return $this->_currentObject; } // function getCacheData() + /** + * Get a list of all cell addresses currently held in cache + * + * @return array of string + */ + public function getCellList() { + if ($this->_currentObjectID !== null) { + $this->_storeData(); + } + + return parent::getCellList(); + } + + /** * Delete a cell in cache identified by coordinate address * * @param string $pCoord Coordinate address of the cell to delete - * @throws Exception + * @throws PHPExcel_Exception */ public function deleteCacheData($pCoord) { // Delete the entry from Memcache @@ -199,11 +213,11 @@ class PHPExcel_CachedObjectStorage_Memcache extends PHPExcel_CachedObjectStorage if ($obj === false) { // Entry no longer exists in Memcache, so clear it from the cache array parent::deleteCacheData($cellID); - throw new Exception('Cell entry '.$cellID.' no longer exists in MemCache'); + throw new PHPExcel_Exception('Cell entry '.$cellID.' no longer exists in MemCache'); } if (!$this->_memcache->add($newCachePrefix.$cellID.'.cache',$obj,NULL,$this->_cacheTime)) { $this->__destruct(); - throw new Exception('Failed to store cell '.$cellID.' in MemCache'); + throw new PHPExcel_Exception('Failed to store cell '.$cellID.' in MemCache'); } } } @@ -250,7 +264,7 @@ class PHPExcel_CachedObjectStorage_Memcache extends PHPExcel_CachedObjectStorage // Set a new Memcache object and connect to the Memcache server $this->_memcache = new Memcache(); if (!$this->_memcache->addServer($memcacheServer, $memcachePort, false, 50, 5, 5, true, array($this, 'failureCallback'))) { - throw new Exception('Could not connect to MemCache server at '.$memcacheServer.':'.$memcachePort); + throw new PHPExcel_Exception('Could not connect to MemCache server at '.$memcacheServer.':'.$memcachePort); } $this->_cacheTime = $cacheTime; @@ -264,10 +278,10 @@ class PHPExcel_CachedObjectStorage_Memcache extends PHPExcel_CachedObjectStorage * * @param string $host Memcache server * @param integer $port Memcache port - * @throws Exception + * @throws PHPExcel_Exception */ public function failureCallback($host, $port) { - throw new Exception('memcache '.$host.':'.$port.' failed'); + throw new PHPExcel_Exception('memcache '.$host.':'.$port.' failed'); } diff --git a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/Memory.php b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/Memory.php index 36f42fb6ccf..20cd59f64a3 100644 --- a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/Memory.php +++ b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/Memory.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,20 +31,32 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_CachedObjectStorage_Memory extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache { + /** + * Dummy method callable from CacheBase, but unused by Memory cache + * + * @return void + */ + protected function _storeData() { + } // function _storeData() + /** * Add or Update a cell in cache identified by coordinate address * * @param string $pCoord Coordinate address of the cell to update * @param PHPExcel_Cell $cell Cell to update - * @return void - * @throws Exception + * @return PHPExcel_Cell + * @throws PHPExcel_Exception */ public function addCacheData($pCoord, PHPExcel_Cell $cell) { $this->_cellCache[$pCoord] = $cell; + + // Set current entry to the new/updated entry + $this->_currentObjectID = $pCoord; + return $cell; } // function addCacheData() @@ -53,16 +65,20 @@ class PHPExcel_CachedObjectStorage_Memory extends PHPExcel_CachedObjectStorage_C * Get cell at a specific coordinate * * @param string $pCoord Coordinate of the cell - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Cell Cell that was found, or null if not found */ public function getCacheData($pCoord) { // Check if the entry that has been requested actually exists if (!isset($this->_cellCache[$pCoord])) { + $this->_currentObjectID = NULL; // Return null if requested entry doesn't exist in cache return null; } + // Set current entry to the requested entry + $this->_currentObjectID = $pCoord; + // Return requested entry return $this->_cellCache[$pCoord]; } // function getCacheData() @@ -80,7 +96,7 @@ class PHPExcel_CachedObjectStorage_Memory extends PHPExcel_CachedObjectStorage_C $newCollection = array(); foreach($this->_cellCache as $k => &$cell) { $newCollection[$k] = clone $cell; - $newCollection[$k]->attach($parent); + $newCollection[$k]->attach($this); } $this->_cellCache = $newCollection; diff --git a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/MemoryGZip.php b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/MemoryGZip.php index ee8e95eb2b5..692c1bfcb6a 100644 --- a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/MemoryGZip.php +++ b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/MemoryGZip.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_CachedObjectStorage_MemoryGZip extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache { @@ -40,10 +40,10 @@ class PHPExcel_CachedObjectStorage_MemoryGZip extends PHPExcel_CachedObjectStora * and the 'nullify' the current cell object * * @return void - * @throws Exception + * @throws PHPExcel_Exception */ - private function _storeData() { - if ($this->_currentCellIsDirty) { + protected function _storeData() { + if ($this->_currentCellIsDirty && !empty($this->_currentObjectID)) { $this->_currentObject->detach(); $this->_cellCache[$this->_currentObjectID] = gzdeflate(serialize($this->_currentObject)); @@ -59,7 +59,7 @@ class PHPExcel_CachedObjectStorage_MemoryGZip extends PHPExcel_CachedObjectStora * @param string $pCoord Coordinate address of the cell to update * @param PHPExcel_Cell $cell Cell to update * @return void - * @throws Exception + * @throws PHPExcel_Exception */ public function addCacheData($pCoord, PHPExcel_Cell $cell) { if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { @@ -78,7 +78,7 @@ class PHPExcel_CachedObjectStorage_MemoryGZip extends PHPExcel_CachedObjectStora * Get cell at a specific coordinate * * @param string $pCoord Coordinate of the cell - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Cell Cell that was found, or null if not found */ public function getCacheData($pCoord) { @@ -96,14 +96,28 @@ class PHPExcel_CachedObjectStorage_MemoryGZip extends PHPExcel_CachedObjectStora // Set current entry to the requested entry $this->_currentObjectID = $pCoord; $this->_currentObject = unserialize(gzinflate($this->_cellCache[$pCoord])); - // Re-attach the parent worksheet - $this->_currentObject->attach($this->_parent); + // Re-attach this as the cell's parent + $this->_currentObject->attach($this); // Return requested entry return $this->_currentObject; } // function getCacheData() + /** + * Get a list of all cell addresses currently held in cache + * + * @return array of string + */ + public function getCellList() { + if ($this->_currentObjectID !== null) { + $this->_storeData(); + } + + return parent::getCellList(); + } + + /** * Clear the cell collection and disconnect from our parent * diff --git a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/MemorySerialized.php b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/MemorySerialized.php index d6b09b530e8..fdd021a8dd2 100644 --- a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/MemorySerialized.php +++ b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/MemorySerialized.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_CachedObjectStorage_MemorySerialized extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache { @@ -40,10 +40,10 @@ class PHPExcel_CachedObjectStorage_MemorySerialized extends PHPExcel_CachedObjec * and the 'nullify' the current cell object * * @return void - * @throws Exception + * @throws PHPExcel_Exception */ - private function _storeData() { - if ($this->_currentCellIsDirty) { + protected function _storeData() { + if ($this->_currentCellIsDirty && !empty($this->_currentObjectID)) { $this->_currentObject->detach(); $this->_cellCache[$this->_currentObjectID] = serialize($this->_currentObject); @@ -59,7 +59,7 @@ class PHPExcel_CachedObjectStorage_MemorySerialized extends PHPExcel_CachedObjec * @param string $pCoord Coordinate address of the cell to update * @param PHPExcel_Cell $cell Cell to update * @return void - * @throws Exception + * @throws PHPExcel_Exception */ public function addCacheData($pCoord, PHPExcel_Cell $cell) { if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { @@ -78,7 +78,7 @@ class PHPExcel_CachedObjectStorage_MemorySerialized extends PHPExcel_CachedObjec * Get cell at a specific coordinate * * @param string $pCoord Coordinate of the cell - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Cell Cell that was found, or null if not found */ public function getCacheData($pCoord) { @@ -96,14 +96,28 @@ class PHPExcel_CachedObjectStorage_MemorySerialized extends PHPExcel_CachedObjec // Set current entry to the requested entry $this->_currentObjectID = $pCoord; $this->_currentObject = unserialize($this->_cellCache[$pCoord]); - // Re-attach the parent worksheet - $this->_currentObject->attach($this->_parent); + // Re-attach this as the cell's parent + $this->_currentObject->attach($this); // Return requested entry return $this->_currentObject; } // function getCacheData() + /** + * Get a list of all cell addresses currently held in cache + * + * @return array of string + */ + public function getCellList() { + if ($this->_currentObjectID !== null) { + $this->_storeData(); + } + + return parent::getCellList(); + } + + /** * Clear the cell collection and disconnect from our parent * diff --git a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/PHPTemp.php b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/PHPTemp.php index 8dbbe92e8c2..b00c19bbb4a 100644 --- a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/PHPTemp.php +++ b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/PHPTemp.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_CachedObjectStorage_PHPTemp extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache { @@ -54,10 +54,10 @@ class PHPExcel_CachedObjectStorage_PHPTemp extends PHPExcel_CachedObjectStorage_ * and the 'nullify' the current cell object * * @return void - * @throws Exception + * @throws PHPExcel_Exception */ - private function _storeData() { - if ($this->_currentCellIsDirty) { + protected function _storeData() { + if ($this->_currentCellIsDirty && !empty($this->_currentObjectID)) { $this->_currentObject->detach(); fseek($this->_fileHandle,0,SEEK_END); @@ -78,7 +78,7 @@ class PHPExcel_CachedObjectStorage_PHPTemp extends PHPExcel_CachedObjectStorage_ * @param string $pCoord Coordinate address of the cell to update * @param PHPExcel_Cell $cell Cell to update * @return void - * @throws Exception + * @throws PHPExcel_Exception */ public function addCacheData($pCoord, PHPExcel_Cell $cell) { if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { @@ -97,7 +97,7 @@ class PHPExcel_CachedObjectStorage_PHPTemp extends PHPExcel_CachedObjectStorage_ * Get cell at a specific coordinate * * @param string $pCoord Coordinate of the cell - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Cell Cell that was found, or null if not found */ public function getCacheData($pCoord) { @@ -116,14 +116,28 @@ class PHPExcel_CachedObjectStorage_PHPTemp extends PHPExcel_CachedObjectStorage_ $this->_currentObjectID = $pCoord; fseek($this->_fileHandle,$this->_cellCache[$pCoord]['ptr']); $this->_currentObject = unserialize(fread($this->_fileHandle,$this->_cellCache[$pCoord]['sz'])); - // Re-attach the parent worksheet - $this->_currentObject->attach($this->_parent); + // Re-attach this as the cell's parent + $this->_currentObject->attach($this); // Return requested entry return $this->_currentObject; } // function getCacheData() + /** + * Get a list of all cell addresses currently held in cache + * + * @return array of string + */ + public function getCellList() { + if ($this->_currentObjectID !== null) { + $this->_storeData(); + } + + return parent::getCellList(); + } + + /** * Clone the cell collection * diff --git a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/SQLite.php b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/SQLite.php index e4bf469e0fc..75b99c68a66 100644 --- a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/SQLite.php +++ b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/SQLite.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_CachedObjectStorage_SQLite extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache { @@ -54,14 +54,14 @@ class PHPExcel_CachedObjectStorage_SQLite extends PHPExcel_CachedObjectStorage_C * and the 'nullify' the current cell object * * @return void - * @throws Exception + * @throws PHPExcel_Exception */ - private function _storeData() { - if ($this->_currentCellIsDirty) { + protected function _storeData() { + if ($this->_currentCellIsDirty && !empty($this->_currentObjectID)) { $this->_currentObject->detach(); if (!$this->_DBHandle->queryExec("INSERT OR REPLACE INTO kvp_".$this->_TableName." VALUES('".$this->_currentObjectID."','".sqlite_escape_string(serialize($this->_currentObject))."')")) - throw new Exception(sqlite_error_string($this->_DBHandle->lastError())); + throw new PHPExcel_Exception(sqlite_error_string($this->_DBHandle->lastError())); $this->_currentCellIsDirty = false; } $this->_currentObjectID = $this->_currentObject = null; @@ -74,7 +74,7 @@ class PHPExcel_CachedObjectStorage_SQLite extends PHPExcel_CachedObjectStorage_C * @param string $pCoord Coordinate address of the cell to update * @param PHPExcel_Cell $cell Cell to update * @return void - * @throws Exception + * @throws PHPExcel_Exception */ public function addCacheData($pCoord, PHPExcel_Cell $cell) { if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { @@ -93,7 +93,7 @@ class PHPExcel_CachedObjectStorage_SQLite extends PHPExcel_CachedObjectStorage_C * Get cell at a specific coordinate * * @param string $pCoord Coordinate of the cell - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Cell Cell that was found, or null if not found */ public function getCacheData($pCoord) { @@ -105,7 +105,7 @@ class PHPExcel_CachedObjectStorage_SQLite extends PHPExcel_CachedObjectStorage_C $query = "SELECT value FROM kvp_".$this->_TableName." WHERE id='".$pCoord."'"; $cellResultSet = $this->_DBHandle->query($query,SQLITE_ASSOC); if ($cellResultSet === false) { - throw new Exception(sqlite_error_string($this->_DBHandle->lastError())); + throw new PHPExcel_Exception(sqlite_error_string($this->_DBHandle->lastError())); } elseif ($cellResultSet->numRows() == 0) { // Return null if requested entry doesn't exist in cache return null; @@ -116,8 +116,8 @@ class PHPExcel_CachedObjectStorage_SQLite extends PHPExcel_CachedObjectStorage_C $cellResult = $cellResultSet->fetchSingle(); $this->_currentObject = unserialize($cellResult); - // Re-attach the parent worksheet - $this->_currentObject->attach($this->_parent); + // Re-attach this as the cell's parent + $this->_currentObject->attach($this); // Return requested entry return $this->_currentObject; @@ -139,7 +139,7 @@ class PHPExcel_CachedObjectStorage_SQLite extends PHPExcel_CachedObjectStorage_C $query = "SELECT id FROM kvp_".$this->_TableName." WHERE id='".$pCoord."'"; $cellResultSet = $this->_DBHandle->query($query,SQLITE_ASSOC); if ($cellResultSet === false) { - throw new Exception(sqlite_error_string($this->_DBHandle->lastError())); + throw new PHPExcel_Exception(sqlite_error_string($this->_DBHandle->lastError())); } elseif ($cellResultSet->numRows() == 0) { // Return null if requested entry doesn't exist in cache return false; @@ -152,7 +152,7 @@ class PHPExcel_CachedObjectStorage_SQLite extends PHPExcel_CachedObjectStorage_C * Delete a cell in cache identified by coordinate address * * @param string $pCoord Coordinate address of the cell to delete - * @throws Exception + * @throws PHPExcel_Exception */ public function deleteCacheData($pCoord) { if ($pCoord === $this->_currentObjectID) { @@ -163,22 +163,52 @@ class PHPExcel_CachedObjectStorage_SQLite extends PHPExcel_CachedObjectStorage_C // Check if the requested entry exists in the cache $query = "DELETE FROM kvp_".$this->_TableName." WHERE id='".$pCoord."'"; if (!$this->_DBHandle->queryExec($query)) - throw new Exception(sqlite_error_string($this->_DBHandle->lastError())); + throw new PHPExcel_Exception(sqlite_error_string($this->_DBHandle->lastError())); $this->_currentCellIsDirty = false; } // function deleteCacheData() + /** + * Move a cell object from one address to another + * + * @param string $fromAddress Current address of the cell to move + * @param string $toAddress Destination address of the cell to move + * @return boolean + */ + public function moveCell($fromAddress, $toAddress) { + if ($fromAddress === $this->_currentObjectID) { + $this->_currentObjectID = $toAddress; + } + + $query = "DELETE FROM kvp_".$this->_TableName." WHERE id='".$toAddress."'"; + $result = $this->_DBHandle->exec($query); + if ($result === false) + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); + + $query = "UPDATE kvp_".$this->_TableName." SET id='".$toAddress."' WHERE id='".$fromAddress."'"; + $result = $this->_DBHandle->exec($query); + if ($result === false) + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); + + return TRUE; + } // function moveCell() + + /** * Get a list of all cell addresses currently held in cache * * @return array of string */ public function getCellList() { + if ($this->_currentObjectID !== null) { + $this->_storeData(); + } + $query = "SELECT id FROM kvp_".$this->_TableName; $cellIdsResult = $this->_DBHandle->unbufferedQuery($query,SQLITE_ASSOC); if ($cellIdsResult === false) - throw new Exception(sqlite_error_string($this->_DBHandle->lastError())); + throw new PHPExcel_Exception(sqlite_error_string($this->_DBHandle->lastError())); $cellKeys = array(); foreach($cellIdsResult as $row) { @@ -196,11 +226,14 @@ class PHPExcel_CachedObjectStorage_SQLite extends PHPExcel_CachedObjectStorage_C * @return void */ public function copyCellCollection(PHPExcel_Worksheet $parent) { + $this->_currentCellIsDirty; + $this->_storeData(); + // Get a new id for the new table name $tableName = str_replace('.','_',$this->_getUniqueID()); if (!$this->_DBHandle->queryExec('CREATE TABLE kvp_'.$tableName.' (id VARCHAR(12) PRIMARY KEY, value BLOB) AS SELECT * FROM kvp_'.$this->_TableName)) - throw new Exception(sqlite_error_string($this->_DBHandle->lastError())); + throw new PHPExcel_Exception(sqlite_error_string($this->_DBHandle->lastError())); // Copy the existing cell cache file $this->_TableName = $tableName; @@ -238,9 +271,9 @@ class PHPExcel_CachedObjectStorage_SQLite extends PHPExcel_CachedObjectStorage_C $this->_DBHandle = new SQLiteDatabase($_DBName); if ($this->_DBHandle === false) - throw new Exception(sqlite_error_string($this->_DBHandle->lastError())); + throw new PHPExcel_Exception(sqlite_error_string($this->_DBHandle->lastError())); if (!$this->_DBHandle->queryExec('CREATE TABLE kvp_'.$this->_TableName.' (id VARCHAR(12) PRIMARY KEY, value BLOB)')) - throw new Exception(sqlite_error_string($this->_DBHandle->lastError())); + throw new PHPExcel_Exception(sqlite_error_string($this->_DBHandle->lastError())); } } // function __construct() @@ -249,6 +282,9 @@ class PHPExcel_CachedObjectStorage_SQLite extends PHPExcel_CachedObjectStorage_C * Destroy this cell collection */ public function __destruct() { + if (!is_null($this->_DBHandle)) { + $this->_DBHandle->queryExec('DROP TABLE kvp_'.$this->_TableName); + } $this->_DBHandle = null; } // function __destruct() diff --git a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/SQLite3.php b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/SQLite3.php index ead6e91f87f..bcfe159bda9 100644 --- a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/SQLite3.php +++ b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/SQLite3.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache { @@ -49,23 +49,50 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_ */ private $_DBHandle = null; + /** + * Prepared statement for a SQLite3 select query + * + * @var SQLite3Stmt + */ + private $_selectQuery; + + /** + * Prepared statement for a SQLite3 insert query + * + * @var SQLite3Stmt + */ + private $_insertQuery; + + /** + * Prepared statement for a SQLite3 update query + * + * @var SQLite3Stmt + */ + private $_updateQuery; + + /** + * Prepared statement for a SQLite3 delete query + * + * @var SQLite3Stmt + */ + private $_deleteQuery; + /** * Store cell data in cache for the current cell object if it's "dirty", * and the 'nullify' the current cell object * * @return void - * @throws Exception + * @throws PHPExcel_Exception */ - private function _storeData() { - if ($this->_currentCellIsDirty) { + protected function _storeData() { + if ($this->_currentCellIsDirty && !empty($this->_currentObjectID)) { $this->_currentObject->detach(); - $query = $this->_DBHandle->prepare("INSERT OR REPLACE INTO kvp_".$this->_TableName." VALUES(:id,:data)"); - $query->bindValue('id',$this->_currentObjectID,SQLITE3_TEXT); - $query->bindValue('data',serialize($this->_currentObject),SQLITE3_BLOB); - $result = $query->execute(); + $this->_insertQuery->bindValue('id',$this->_currentObjectID,SQLITE3_TEXT); + $this->_insertQuery->bindValue('data',serialize($this->_currentObject),SQLITE3_BLOB); + $result = $this->_insertQuery->execute(); if ($result === false) - throw new Exception($this->_DBHandle->lastErrorMsg()); + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); $this->_currentCellIsDirty = false; } $this->_currentObjectID = $this->_currentObject = null; @@ -78,7 +105,7 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_ * @param string $pCoord Coordinate address of the cell to update * @param PHPExcel_Cell $cell Cell to update * @return void - * @throws Exception + * @throws PHPExcel_Exception */ public function addCacheData($pCoord, PHPExcel_Cell $cell) { if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { @@ -97,7 +124,7 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_ * Get cell at a specific coordinate * * @param string $pCoord Coordinate of the cell - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Cell Cell that was found, or null if not found */ public function getCacheData($pCoord) { @@ -106,21 +133,23 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_ } $this->_storeData(); - $query = "SELECT value FROM kvp_".$this->_TableName." WHERE id='".$pCoord."'"; - $cellResult = $this->_DBHandle->querySingle($query); - if ($cellResult === false) { - throw new Exception($this->_DBHandle->lastErrorMsg()); - } elseif (is_null($cellResult)) { + $this->_selectQuery->bindValue('id',$pCoord,SQLITE3_TEXT); + $cellResult = $this->_selectQuery->execute(); + if ($cellResult === FALSE) { + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); + } + $cellData = $cellResult->fetchArray(SQLITE3_ASSOC); + if ($cellData === FALSE) { // Return null if requested entry doesn't exist in cache - return null; + return NULL; } // Set current entry to the requested entry $this->_currentObjectID = $pCoord; - $this->_currentObject = unserialize($cellResult); - // Re-attach the parent worksheet - $this->_currentObject->attach($this->_parent); + $this->_currentObject = unserialize($cellData['value']); + // Re-attach this as the cell's parent + $this->_currentObject->attach($this); // Return requested entry return $this->_currentObject; @@ -135,19 +164,18 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_ */ public function isDataSet($pCoord) { if ($pCoord === $this->_currentObjectID) { - return true; + return TRUE; } // Check if the requested entry exists in the cache - $query = "SELECT id FROM kvp_".$this->_TableName." WHERE id='".$pCoord."'"; - $cellResult = $this->_DBHandle->querySingle($query); - if ($cellResult === false) { - throw new Exception($this->_DBHandle->lastErrorMsg()); - } elseif (is_null($cellResult)) { - // Return null if requested entry doesn't exist in cache - return false; + $this->_selectQuery->bindValue('id',$pCoord,SQLITE3_TEXT); + $cellResult = $this->_selectQuery->execute(); + if ($cellResult === FALSE) { + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); } - return true; + $cellData = $cellResult->fetchArray(SQLITE3_ASSOC); + + return ($cellData === FALSE) ? FALSE : TRUE; } // function isDataSet() @@ -155,34 +183,65 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_ * Delete a cell in cache identified by coordinate address * * @param string $pCoord Coordinate address of the cell to delete - * @throws Exception + * @throws PHPExcel_Exception */ public function deleteCacheData($pCoord) { if ($pCoord === $this->_currentObjectID) { $this->_currentObject->detach(); - $this->_currentObjectID = $this->_currentObject = null; + $this->_currentObjectID = $this->_currentObject = NULL; } // Check if the requested entry exists in the cache - $query = "DELETE FROM kvp_".$this->_TableName." WHERE id='".$pCoord."'"; - $result = $this->_DBHandle->exec($query); - if ($result === false) - throw new Exception($this->_DBHandle->lastErrorMsg()); + $this->_deleteQuery->bindValue('id',$pCoord,SQLITE3_TEXT); + $result = $this->_deleteQuery->execute(); + if ($result === FALSE) + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); - $this->_currentCellIsDirty = false; + $this->_currentCellIsDirty = FALSE; } // function deleteCacheData() + /** + * Move a cell object from one address to another + * + * @param string $fromAddress Current address of the cell to move + * @param string $toAddress Destination address of the cell to move + * @return boolean + */ + public function moveCell($fromAddress, $toAddress) { + if ($fromAddress === $this->_currentObjectID) { + $this->_currentObjectID = $toAddress; + } + + $this->_deleteQuery->bindValue('id',$toAddress,SQLITE3_TEXT); + $result = $this->_deleteQuery->execute(); + if ($result === false) + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); + + $this->_updateQuery->bindValue('toid',$toAddress,SQLITE3_TEXT); + $this->_updateQuery->bindValue('fromid',$fromAddress,SQLITE3_TEXT); + $result = $this->_updateQuery->execute(); + if ($result === false) + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); + + return TRUE; + } // function moveCell() + + /** * Get a list of all cell addresses currently held in cache * * @return array of string */ public function getCellList() { + if ($this->_currentObjectID !== null) { + $this->_storeData(); + } + $query = "SELECT id FROM kvp_".$this->_TableName; $cellIdsResult = $this->_DBHandle->query($query); if ($cellIdsResult === false) - throw new Exception($this->_DBHandle->lastErrorMsg()); + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); $cellKeys = array(); while ($row = $cellIdsResult->fetchArray(SQLITE3_ASSOC)) { @@ -200,11 +259,14 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_ * @return void */ public function copyCellCollection(PHPExcel_Worksheet $parent) { + $this->_currentCellIsDirty; + $this->_storeData(); + // Get a new id for the new table name $tableName = str_replace('.','_',$this->_getUniqueID()); if (!$this->_DBHandle->exec('CREATE TABLE kvp_'.$tableName.' (id VARCHAR(12) PRIMARY KEY, value BLOB) AS SELECT * FROM kvp_'.$this->_TableName)) - throw new Exception($this->_DBHandle->lastErrorMsg()); + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); // Copy the existing cell cache file $this->_TableName = $tableName; @@ -242,10 +304,15 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_ $this->_DBHandle = new SQLite3($_DBName); if ($this->_DBHandle === false) - throw new Exception($this->_DBHandle->lastErrorMsg()); + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); if (!$this->_DBHandle->exec('CREATE TABLE kvp_'.$this->_TableName.' (id VARCHAR(12) PRIMARY KEY, value BLOB)')) - throw new Exception($this->_DBHandle->lastErrorMsg()); + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); } + + $this->_selectQuery = $this->_DBHandle->prepare("SELECT value FROM kvp_".$this->_TableName." WHERE id = :id"); + $this->_insertQuery = $this->_DBHandle->prepare("INSERT OR REPLACE INTO kvp_".$this->_TableName." VALUES(:id,:data)"); + $this->_updateQuery = $this->_DBHandle->prepare("UPDATE kvp_".$this->_TableName." SET id=:toId WHERE id=:fromId"); + $this->_deleteQuery = $this->_DBHandle->prepare("DELETE FROM kvp_".$this->_TableName." WHERE id = :id"); } // function __construct() @@ -254,6 +321,7 @@ class PHPExcel_CachedObjectStorage_SQLite3 extends PHPExcel_CachedObjectStorage_ */ public function __destruct() { if (!is_null($this->_DBHandle)) { + $this->_DBHandle->exec('DROP TABLE kvp_'.$this->_TableName); $this->_DBHandle->close(); } $this->_DBHandle = null; diff --git a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/Wincache.php b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/Wincache.php index ba8b0458062..96dca6627fb 100644 --- a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/Wincache.php +++ b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorage/Wincache.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_CachedObjectStorage_Wincache extends PHPExcel_CachedObjectStorage_CacheBase implements PHPExcel_CachedObjectStorage_ICache { @@ -55,22 +55,22 @@ class PHPExcel_CachedObjectStorage_Wincache extends PHPExcel_CachedObjectStorage * and the 'nullify' the current cell object * * @return void - * @throws Exception + * @throws PHPExcel_Exception */ - private function _storeData() { - if ($this->_currentCellIsDirty) { + protected function _storeData() { + if ($this->_currentCellIsDirty && !empty($this->_currentObjectID)) { $this->_currentObject->detach(); $obj = serialize($this->_currentObject); if (wincache_ucache_exists($this->_cachePrefix.$this->_currentObjectID.'.cache')) { if (!wincache_ucache_set($this->_cachePrefix.$this->_currentObjectID.'.cache', $obj, $this->_cacheTime)) { $this->__destruct(); - throw new Exception('Failed to store cell '.$this->_currentObjectID.' in WinCache'); + throw new PHPExcel_Exception('Failed to store cell '.$this->_currentObjectID.' in WinCache'); } } else { if (!wincache_ucache_add($this->_cachePrefix.$this->_currentObjectID.'.cache', $obj, $this->_cacheTime)) { $this->__destruct(); - throw new Exception('Failed to store cell '.$this->_currentObjectID.' in WinCache'); + throw new PHPExcel_Exception('Failed to store cell '.$this->_currentObjectID.' in WinCache'); } } $this->_currentCellIsDirty = false; @@ -86,7 +86,7 @@ class PHPExcel_CachedObjectStorage_Wincache extends PHPExcel_CachedObjectStorage * @param string $pCoord Coordinate address of the cell to update * @param PHPExcel_Cell $cell Cell to update * @return void - * @throws Exception + * @throws PHPExcel_Exception */ public function addCacheData($pCoord, PHPExcel_Cell $cell) { if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { @@ -119,7 +119,7 @@ class PHPExcel_CachedObjectStorage_Wincache extends PHPExcel_CachedObjectStorage if ($success === false) { // Entry no longer exists in Wincache, so clear it from the cache array parent::deleteCacheData($pCoord); - throw new Exception('Cell entry '.$pCoord.' no longer exists in WinCache'); + throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in WinCache'); } return true; } @@ -131,7 +131,7 @@ class PHPExcel_CachedObjectStorage_Wincache extends PHPExcel_CachedObjectStorage * Get cell at a specific coordinate * * @param string $pCoord Coordinate of the cell - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Cell Cell that was found, or null if not found */ public function getCacheData($pCoord) { @@ -148,7 +148,7 @@ class PHPExcel_CachedObjectStorage_Wincache extends PHPExcel_CachedObjectStorage if ($success === false) { // Entry no longer exists in WinCache, so clear it from the cache array parent::deleteCacheData($pCoord); - throw new Exception('Cell entry '.$pCoord.' no longer exists in WinCache'); + throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in WinCache'); } } else { // Return null if requested entry doesn't exist in cache @@ -158,19 +158,33 @@ class PHPExcel_CachedObjectStorage_Wincache extends PHPExcel_CachedObjectStorage // Set current entry to the requested entry $this->_currentObjectID = $pCoord; $this->_currentObject = unserialize($obj); - // Re-attach the parent worksheet - $this->_currentObject->attach($this->_parent); + // Re-attach this as the cell's parent + $this->_currentObject->attach($this); // Return requested entry return $this->_currentObject; } // function getCacheData() + /** + * Get a list of all cell addresses currently held in cache + * + * @return array of string + */ + public function getCellList() { + if ($this->_currentObjectID !== null) { + $this->_storeData(); + } + + return parent::getCellList(); + } + + /** * Delete a cell in cache identified by coordinate address * * @param string $pCoord Coordinate address of the cell to delete - * @throws Exception + * @throws PHPExcel_Exception */ public function deleteCacheData($pCoord) { // Delete the entry from Wincache @@ -200,11 +214,11 @@ class PHPExcel_CachedObjectStorage_Wincache extends PHPExcel_CachedObjectStorage if ($success === false) { // Entry no longer exists in WinCache, so clear it from the cache array parent::deleteCacheData($cellID); - throw new Exception('Cell entry '.$cellID.' no longer exists in Wincache'); + throw new PHPExcel_Exception('Cell entry '.$cellID.' no longer exists in Wincache'); } if (!wincache_ucache_add($newCachePrefix.$cellID.'.cache', $obj, $this->_cacheTime)) { $this->__destruct(); - throw new Exception('Failed to store cell '.$cellID.' in Wincache'); + throw new PHPExcel_Exception('Failed to store cell '.$cellID.' in Wincache'); } } } diff --git a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorageFactory.php b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorageFactory.php index 51019f7bdc5..6c3ec15cf2f 100644 --- a/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorageFactory.php +++ b/htdocs/includes/phpexcel/PHPExcel/CachedObjectStorageFactory.php @@ -3,7 +3,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,220 +20,232 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * @category PHPExcel - * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @package PHPExcel_CachedObjectStorage + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.8.0, 2014-03-02 */ /** * PHPExcel_CachedObjectStorageFactory * - * @category PHPExcel - * @package PHPExcel_CachedObjectStorage - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @category PHPExcel + * @package PHPExcel_CachedObjectStorage + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_CachedObjectStorageFactory { - const cache_in_memory = 'Memory'; - const cache_in_memory_gzip = 'MemoryGZip'; - const cache_in_memory_serialized = 'MemorySerialized'; - const cache_igbinary = 'Igbinary'; - const cache_to_discISAM = 'DiscISAM'; - const cache_to_apc = 'APC'; - const cache_to_memcache = 'Memcache'; - const cache_to_phpTemp = 'PHPTemp'; - const cache_to_wincache = 'Wincache'; - const cache_to_sqlite = 'SQLite'; - const cache_to_sqlite3 = 'SQLite3'; + const cache_in_memory = 'Memory'; + const cache_in_memory_gzip = 'MemoryGZip'; + const cache_in_memory_serialized = 'MemorySerialized'; + const cache_igbinary = 'Igbinary'; + const cache_to_discISAM = 'DiscISAM'; + const cache_to_apc = 'APC'; + const cache_to_memcache = 'Memcache'; + const cache_to_phpTemp = 'PHPTemp'; + const cache_to_wincache = 'Wincache'; + const cache_to_sqlite = 'SQLite'; + const cache_to_sqlite3 = 'SQLite3'; - /** - * Name of the method used for cell cacheing - * - * @var string - */ - private static $_cacheStorageMethod = NULL; + /** + * Name of the method used for cell cacheing + * + * @var string + */ + private static $_cacheStorageMethod = NULL; - /** - * Name of the class used for cell cacheing - * - * @var string - */ - private static $_cacheStorageClass = NULL; + /** + * Name of the class used for cell cacheing + * + * @var string + */ + private static $_cacheStorageClass = NULL; - /** - * List of all possible cache storage methods - * - * @var string[] - */ - private static $_storageMethods = array( - self::cache_in_memory, - self::cache_in_memory_gzip, - self::cache_in_memory_serialized, - self::cache_igbinary, - self::cache_to_phpTemp, - self::cache_to_discISAM, - self::cache_to_apc, - self::cache_to_memcache, - self::cache_to_wincache, - self::cache_to_sqlite, - self::cache_to_sqlite3, - ); + /** + * List of all possible cache storage methods + * + * @var string[] + */ + private static $_storageMethods = array( + self::cache_in_memory, + self::cache_in_memory_gzip, + self::cache_in_memory_serialized, + self::cache_igbinary, + self::cache_to_phpTemp, + self::cache_to_discISAM, + self::cache_to_apc, + self::cache_to_memcache, + self::cache_to_wincache, + self::cache_to_sqlite, + self::cache_to_sqlite3, + ); - /** - * Default arguments for each cache storage method - * - * @var array of mixed array - */ - private static $_storageMethodDefaultParameters = array( - self::cache_in_memory => array( - ), - self::cache_in_memory_gzip => array( - ), - self::cache_in_memory_serialized => array( - ), - self::cache_igbinary => array( - ), - self::cache_to_phpTemp => array( 'memoryCacheSize' => '1MB' - ), - self::cache_to_discISAM => array( 'dir' => NULL - ), - self::cache_to_apc => array( 'cacheTime' => 600 - ), - self::cache_to_memcache => array( 'memcacheServer' => 'localhost', - 'memcachePort' => 11211, - 'cacheTime' => 600 - ), - self::cache_to_wincache => array( 'cacheTime' => 600 - ), - self::cache_to_sqlite => array( - ), - self::cache_to_sqlite3 => array( - ), - ); + /** + * Default arguments for each cache storage method + * + * @var array of mixed array + */ + private static $_storageMethodDefaultParameters = array( + self::cache_in_memory => array( + ), + self::cache_in_memory_gzip => array( + ), + self::cache_in_memory_serialized => array( + ), + self::cache_igbinary => array( + ), + self::cache_to_phpTemp => array( 'memoryCacheSize' => '1MB' + ), + self::cache_to_discISAM => array( 'dir' => NULL + ), + self::cache_to_apc => array( 'cacheTime' => 600 + ), + self::cache_to_memcache => array( 'memcacheServer' => 'localhost', + 'memcachePort' => 11211, + 'cacheTime' => 600 + ), + self::cache_to_wincache => array( 'cacheTime' => 600 + ), + self::cache_to_sqlite => array( + ), + self::cache_to_sqlite3 => array( + ), + ); - /** - * Arguments for the active cache storage method - * - * @var array of mixed array - */ - private static $_storageMethodParameters = array(); + /** + * Arguments for the active cache storage method + * + * @var array of mixed array + */ + private static $_storageMethodParameters = array(); - /** - * Return the current cache storage method - * - * @return string|NULL - **/ - public static function getCacheStorageMethod() + /** + * Return the current cache storage method + * + * @return string|NULL + **/ + public static function getCacheStorageMethod() + { + return self::$_cacheStorageMethod; + } // function getCacheStorageMethod() + + + /** + * Return the current cache storage class + * + * @return PHPExcel_CachedObjectStorage_ICache|NULL + **/ + public static function getCacheStorageClass() + { + return self::$_cacheStorageClass; + } // function getCacheStorageClass() + + + /** + * Return the list of all possible cache storage methods + * + * @return string[] + **/ + public static function getAllCacheStorageMethods() + { + return self::$_storageMethods; + } // function getCacheStorageMethods() + + + /** + * Return the list of all available cache storage methods + * + * @return string[] + **/ + public static function getCacheStorageMethods() + { + $activeMethods = array(); + foreach(self::$_storageMethods as $storageMethod) { + $cacheStorageClass = 'PHPExcel_CachedObjectStorage_' . $storageMethod; + if (call_user_func(array($cacheStorageClass, 'cacheMethodIsAvailable'))) { + $activeMethods[] = $storageMethod; + } + } + return $activeMethods; + } // function getCacheStorageMethods() + + + /** + * Identify the cache storage method to use + * + * @param string $method Name of the method to use for cell cacheing + * @param array of mixed $arguments Additional arguments to pass to the cell caching class + * when instantiating + * @return boolean + **/ + public static function initialize($method = self::cache_in_memory, $arguments = array()) + { + if (!in_array($method,self::$_storageMethods)) { + return FALSE; + } + + $cacheStorageClass = 'PHPExcel_CachedObjectStorage_'.$method; + if (!call_user_func(array( $cacheStorageClass, + 'cacheMethodIsAvailable'))) { + return FALSE; + } + + self::$_storageMethodParameters[$method] = self::$_storageMethodDefaultParameters[$method]; + foreach($arguments as $k => $v) { + if (array_key_exists($k, self::$_storageMethodParameters[$method])) { + self::$_storageMethodParameters[$method][$k] = $v; + } + } + + if (self::$_cacheStorageMethod === NULL) { + self::$_cacheStorageClass = 'PHPExcel_CachedObjectStorage_' . $method; + self::$_cacheStorageMethod = $method; + } + return TRUE; + } // function initialize() + + + /** + * Initialise the cache storage + * + * @param PHPExcel_Worksheet $parent Enable cell caching for this worksheet + * @return PHPExcel_CachedObjectStorage_ICache + **/ + public static function getInstance(PHPExcel_Worksheet $parent) + { + $cacheMethodIsAvailable = TRUE; + if (self::$_cacheStorageMethod === NULL) { + $cacheMethodIsAvailable = self::initialize(); + } + + if ($cacheMethodIsAvailable) { + $instance = new self::$_cacheStorageClass( $parent, + self::$_storageMethodParameters[self::$_cacheStorageMethod] + ); + if ($instance !== NULL) { + return $instance; + } + } + + return FALSE; + } // function getInstance() + + + /** + * Clear the cache storage + * + **/ + public static function finalize() { - return self::$_cacheStorageMethod; - } // function getCacheStorageMethod() + self::$_cacheStorageMethod = NULL; + self::$_cacheStorageClass = NULL; + self::$_storageMethodParameters = array(); + } - - /** - * Return the current cache storage class - * - * @return PHPExcel_CachedObjectStorage_ICache|NULL - **/ - public static function getCacheStorageClass() - { - return self::$_cacheStorageClass; - } // function getCacheStorageClass() - - - /** - * Return the list of all possible cache storage methods - * - * @return string[] - **/ - public static function getAllCacheStorageMethods() - { - return self::$_storageMethods; - } // function getCacheStorageMethods() - - - /** - * Return the list of all available cache storage methods - * - * @return string[] - **/ - public static function getCacheStorageMethods() - { - $activeMethods = array(); - foreach(self::$_storageMethods as $storageMethod) { - $cacheStorageClass = 'PHPExcel_CachedObjectStorage_' . $storageMethod; - if (call_user_func(array($cacheStorageClass, 'cacheMethodIsAvailable'))) { - $activeMethods[] = $storageMethod; - } - } - return $activeMethods; - } // function getCacheStorageMethods() - - - /** - * Identify the cache storage method to use - * - * @param string $method Name of the method to use for cell cacheing - * @param array of mixed $arguments Additional arguments to pass to the cell caching class - * when instantiating - * @return boolean - **/ - public static function initialize($method = self::cache_in_memory, $arguments = array()) - { - if (!in_array($method,self::$_storageMethods)) { - return FALSE; - } - - $cacheStorageClass = 'PHPExcel_CachedObjectStorage_'.$method; - if (!call_user_func(array( $cacheStorageClass, - 'cacheMethodIsAvailable'))) { - return FALSE; - } - - self::$_storageMethodParameters[$method] = self::$_storageMethodDefaultParameters[$method]; - foreach($arguments as $k => $v) { - if (isset(self::$_storageMethodParameters[$method][$k])) { - self::$_storageMethodParameters[$method][$k] = $v; - } - } - - if (self::$_cacheStorageMethod === NULL) { - self::$_cacheStorageClass = 'PHPExcel_CachedObjectStorage_' . $method; - self::$_cacheStorageMethod = $method; - } - return TRUE; - } // function initialize() - - - /** - * Initialise the cache storage - * - * @param PHPExcel_Worksheet $parent Enable cell caching for this worksheet - * @return PHPExcel_CachedObjectStorage_ICache - **/ - public static function getInstance(PHPExcel_Worksheet $parent) - { - $cacheMethodIsAvailable = TRUE; - if (self::$_cacheStorageMethod === NULL) { - $cacheMethodIsAvailable = self::initialize(); - } - - if ($cacheMethodIsAvailable) { - $instance = new self::$_cacheStorageClass( $parent, - self::$_storageMethodParameters[self::$_cacheStorageMethod] - ); - if ($instance !== NULL) { - return $instance; - } - } - - return FALSE; - } // function getInstance() - -} \ No newline at end of file +} diff --git a/htdocs/includes/phpexcel/PHPExcel/CalcEngine/CyclicReferenceStack.php b/htdocs/includes/phpexcel/PHPExcel/CalcEngine/CyclicReferenceStack.php new file mode 100644 index 00000000000..02591935a4b --- /dev/null +++ b/htdocs/includes/phpexcel/PHPExcel/CalcEngine/CyclicReferenceStack.php @@ -0,0 +1,98 @@ +_stack); + } + + /** + * Push a new entry onto the stack + * + * @param mixed $value + */ + public function push($value) { + $this->_stack[] = $value; + } // function push() + + /** + * Pop the last entry from the stack + * + * @return mixed + */ + public function pop() { + return array_pop($this->_stack); + } // function pop() + + /** + * Test to see if a specified entry exists on the stack + * + * @param mixed $value The value to test + */ + public function onStack($value) { + return in_array($value, $this->_stack); + } + + /** + * Clear the stack + */ + public function clear() { + $this->_stack = array(); + } // function push() + + /** + * Return an array of all entries on the stack + * + * @return mixed[] + */ + public function showStack() { + return $this->_stack; + } + +} // class PHPExcel_CalcEngine_CyclicReferenceStack diff --git a/htdocs/includes/phpexcel/PHPExcel/CalcEngine/Logger.php b/htdocs/includes/phpexcel/PHPExcel/CalcEngine/Logger.php new file mode 100644 index 00000000000..2048df3e515 --- /dev/null +++ b/htdocs/includes/phpexcel/PHPExcel/CalcEngine/Logger.php @@ -0,0 +1,153 @@ +_cellStack = $stack; + } + + /** + * Enable/Disable Calculation engine logging + * + * @param boolean $pValue + */ + public function setWriteDebugLog($pValue = FALSE) { + $this->_writeDebugLog = $pValue; + } + + /** + * Return whether calculation engine logging is enabled or disabled + * + * @return boolean + */ + public function getWriteDebugLog() { + return $this->_writeDebugLog; + } + + /** + * Enable/Disable echoing of debug log information + * + * @param boolean $pValue + */ + public function setEchoDebugLog($pValue = FALSE) { + $this->_echoDebugLog = $pValue; + } + + /** + * Return whether echoing of debug log information is enabled or disabled + * + * @return boolean + */ + public function getEchoDebugLog() { + return $this->_echoDebugLog; + } + + /** + * Write an entry to the calculation engine debug log + */ + public function writeDebugLog() { + // Only write the debug log if logging is enabled + if ($this->_writeDebugLog) { + $message = implode(func_get_args()); + $cellReference = implode(' -> ', $this->_cellStack->showStack()); + if ($this->_echoDebugLog) { + echo $cellReference, + ($this->_cellStack->count() > 0 ? ' => ' : ''), + $message, + PHP_EOL; + } + $this->_debugLog[] = $cellReference . + ($this->_cellStack->count() > 0 ? ' => ' : '') . + $message; + } + } // function _writeDebug() + + /** + * Clear the calculation engine debug log + */ + public function clearLog() { + $this->_debugLog = array(); + } // function flushLogger() + + /** + * Return the calculation engine debug log + * + * @return string[] + */ + public function getLog() { + return $this->_debugLog; + } // function flushLogger() + +} // class PHPExcel_CalcEngine_Logger + diff --git a/htdocs/includes/phpexcel/PHPExcel/Calculation.php b/htdocs/includes/phpexcel/PHPExcel/Calculation.php index 65d4f3d1027..b609b0d8921 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Calculation.php +++ b/htdocs/includes/phpexcel/PHPExcel/Calculation.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -53,11 +53,11 @@ if (!defined('CALCULATION_REGEXP_CELLREF')) { /** - * PHPExcel_Calculation (Singleton) + * PHPExcel_Calculation (Multiton) * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation { @@ -96,13 +96,29 @@ class PHPExcel_Calculation { private static $_instance; + /** + * Instance of the workbook this Calculation Engine is using + * + * @access private + * @var PHPExcel + */ + private $_workbook; + + /** + * List of instances of the calculation engine that we've instantiated for individual workbooks + * + * @access private + * @var PHPExcel_Calculation[] + */ + private static $_workbookSets; + /** * Calculation cache * * @access private * @var array */ - private static $_calculationCache = array (); + private $_calculationCache = array (); /** @@ -111,16 +127,7 @@ class PHPExcel_Calculation { * @access private * @var boolean */ - private static $_calculationCacheEnabled = true; - - - /** - * Calculation cache expiration time - * - * @access private - * @var float - */ - private static $_calculationCacheExpirationTime = 15; + private $_calculationCacheEnabled = TRUE; /** @@ -130,10 +137,10 @@ class PHPExcel_Calculation { * @access private * @var array */ - private static $_operators = array('+' => true, '-' => true, '*' => true, '/' => true, - '^' => true, '&' => true, '%' => false, '~' => false, - '>' => true, '<' => true, '=' => true, '>=' => true, - '<=' => true, '<>' => true, '|' => true, ':' => true + private static $_operators = array('+' => TRUE, '-' => TRUE, '*' => TRUE, '/' => TRUE, + '^' => TRUE, '&' => TRUE, '%' => FALSE, '~' => FALSE, + '>' => TRUE, '<' => TRUE, '=' => TRUE, '>=' => TRUE, + '<=' => TRUE, '<>' => TRUE, '|' => TRUE, ':' => TRUE ); @@ -143,12 +150,21 @@ class PHPExcel_Calculation { * @access private * @var array */ - private static $_binaryOperators = array('+' => true, '-' => true, '*' => true, '/' => true, - '^' => true, '&' => true, '>' => true, '<' => true, - '=' => true, '>=' => true, '<=' => true, '<>' => true, - '|' => true, ':' => true + private static $_binaryOperators = array('+' => TRUE, '-' => TRUE, '*' => TRUE, '/' => TRUE, + '^' => TRUE, '&' => TRUE, '>' => TRUE, '<' => TRUE, + '=' => TRUE, '>=' => TRUE, '<=' => TRUE, '<>' => TRUE, + '|' => TRUE, ':' => TRUE ); + /** + * The debug log generated by the calculation engine + * + * @access private + * @var PHPExcel_CalcEngine_Logger + * + */ + private $debugLog; + /** * Flag to determine how formula errors should be handled * If true, then a user error will be triggered @@ -158,7 +174,7 @@ class PHPExcel_Calculation { * @var boolean * */ - public $suppressFormulaErrors = false; + public $suppressFormulaErrors = FALSE; /** * Error message for any error that was raised/thrown by the calculation engine @@ -167,31 +183,7 @@ class PHPExcel_Calculation { * @var string * */ - public $formulaError = null; - - /** - * Flag to determine whether a debug log should be generated by the calculation engine - * If true, then a debug log will be generated - * If false, then a debug log will not be generated - * - * @access public - * @var boolean - * - */ - public $writeDebugLog = false; - - /** - * Flag to determine whether a debug log should be echoed by the calculation engine - * If true, then a debug log will be echoed - * If false, then a debug log will not be echoed - * A debug log can only be echoed if it is generated - * - * @access public - * @var boolean - * - */ - public $echoDebugLog = false; - + public $formulaError = NULL; /** * An array of the nested cell references accessed by the calculation engine, used for the debug log @@ -200,39 +192,85 @@ class PHPExcel_Calculation { * @var array of string * */ - private $debugLogStack = array(); + private $_cyclicReferenceStack; /** - * The debug log generated by the calculation engine + * Current iteration counter for cyclic formulae + * If the value is 0 (or less) then cyclic formulae will throw an exception, + * otherwise they will iterate to the limit defined here before returning a result * - * @access public - * @var array of string + * @var integer * */ - public $debugLog = array(); private $_cyclicFormulaCount = 0; + private $_cyclicFormulaCell = ''; + + /** + * Number of iterations for cyclic formulae + * + * @var integer + * + */ public $cyclicFormulaCount = 0; - - private $_savedPrecision = 12; + /** + * Precision used for calculations + * + * @var integer + * + */ + private $_savedPrecision = 14; + /** + * The current locale setting + * + * @var string + * + */ private static $_localeLanguage = 'en_us'; // US English (default locale) + + /** + * List of available locale settings + * Note that this is read for the locale subdirectory only when requested + * + * @var string[] + * + */ private static $_validLocaleLanguages = array( 'en' // English (default language) ); + /** + * Locale-specific argument separator for function arguments + * + * @var string + * + */ private static $_localeArgumentSeparator = ','; private static $_localeFunctions = array(); + + /** + * Locale-specific translations for Excel constants (True, False and Null) + * + * @var string[] + * + */ public static $_localeBoolean = array( 'TRUE' => 'TRUE', 'FALSE' => 'FALSE', 'NULL' => 'NULL' ); - // Constant conversion from text name/value to actual (datatyped) value - private static $_ExcelConstants = array('TRUE' => true, - 'FALSE' => false, - 'NULL' => null + /** + * Excel constant string translations to their PHP equivalents + * Constant conversion from text name/value to actual (datatyped) value + * + * @var string[] + * + */ + private static $_ExcelConstants = array('TRUE' => TRUE, + 'FALSE' => FALSE, + 'NULL' => NULL ); // PHPExcel functions @@ -404,7 +442,7 @@ class PHPExcel_Calculation { 'COLUMN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, 'functionCall' => 'PHPExcel_Calculation_LookupRef::COLUMN', 'argumentCount' => '-1', - 'passByReference' => array(true) + 'passByReference' => array(TRUE) ), 'COLUMNS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, 'functionCall' => 'PHPExcel_Calculation_LookupRef::COLUMNS', @@ -803,7 +841,7 @@ class PHPExcel_Calculation { 'argumentCount' => '1,2' ), 'HLOOKUP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, - 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'functionCall' => 'PHPExcel_Calculation_LookupRef::HLOOKUP', 'argumentCount' => '3,4' ), 'HOUR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, @@ -813,7 +851,7 @@ class PHPExcel_Calculation { 'HYPERLINK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, 'functionCall' => 'PHPExcel_Calculation_LookupRef::HYPERLINK', 'argumentCount' => '1,2', - 'passCellReference'=> true + 'passCellReference'=> TRUE ), 'HYPGEOMDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, 'functionCall' => 'PHPExcel_Calculation_Statistical::HYPGEOMDIST', @@ -902,7 +940,7 @@ class PHPExcel_Calculation { 'INDIRECT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, 'functionCall' => 'PHPExcel_Calculation_LookupRef::INDIRECT', 'argumentCount' => '1,2', - 'passCellReference'=> true + 'passCellReference'=> TRUE ), 'INFO' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', @@ -1219,8 +1257,8 @@ class PHPExcel_Calculation { 'OFFSET' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, 'functionCall' => 'PHPExcel_Calculation_LookupRef::OFFSET', 'argumentCount' => '3,5', - 'passCellReference'=> true, - 'passByReference' => array(true) + 'passCellReference'=> TRUE, + 'passByReference' => array(TRUE) ), 'OR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL, 'functionCall' => 'PHPExcel_Calculation_Logical::LOGICAL_OR', @@ -1365,7 +1403,7 @@ class PHPExcel_Calculation { 'ROW' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, 'functionCall' => 'PHPExcel_Calculation_LookupRef::ROW', 'argumentCount' => '-1', - 'passByReference' => array(true) + 'passByReference' => array(TRUE) ), 'ROWS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, 'functionCall' => 'PHPExcel_Calculation_LookupRef::ROWS', @@ -1680,20 +1718,20 @@ class PHPExcel_Calculation { - private function __construct() { - $localeFileDirectory = PHPEXCEL_ROOT.'PHPExcel/locale/'; - foreach (glob($localeFileDirectory.'/*',GLOB_ONLYDIR) as $filename) { - $filename = substr($filename,strlen($localeFileDirectory)+1); - if ($filename != 'en') { - self::$_validLocaleLanguages[] = $filename; - } - } - - $setPrecision = (PHP_INT_SIZE == 4) ? 12 : 16; + private function __construct(PHPExcel $workbook = NULL) { + $setPrecision = (PHP_INT_SIZE == 4) ? 14 : 16; $this->_savedPrecision = ini_get('precision'); if ($this->_savedPrecision < $setPrecision) { ini_set('precision',$setPrecision); } + + if ($workbook !== NULL) { + self::$_workbookSets[$workbook->getID()] = $this; + } + + $this->_workbook = $workbook; + $this->_cyclicReferenceStack = new PHPExcel_CalcEngine_CyclicReferenceStack(); + $this->_debugLog = new PHPExcel_CalcEngine_Logger($this->_cyclicReferenceStack); } // function __construct() @@ -1703,13 +1741,32 @@ class PHPExcel_Calculation { } } + private static function _loadLocales() { + $localeFileDirectory = PHPEXCEL_ROOT.'PHPExcel/locale/'; + foreach (glob($localeFileDirectory.'/*',GLOB_ONLYDIR) as $filename) { + $filename = substr($filename,strlen($localeFileDirectory)+1); + if ($filename != 'en') { + self::$_validLocaleLanguages[] = $filename; + } + } + } + /** * Get an instance of this class * * @access public + * @param PHPExcel $workbook Injected workbook for working with a PHPExcel object, + * or NULL to create a standalone claculation engine * @return PHPExcel_Calculation */ - public static function getInstance() { + public static function getInstance(PHPExcel $workbook = NULL) { + if ($workbook !== NULL) { + if (isset(self::$_workbookSets[$workbook->getID()])) { + return self::$_workbookSets[$workbook->getID()]; + } + return new PHPExcel_Calculation($workbook); + } + if (!isset(self::$_instance) || (self::$_instance === NULL)) { self::$_instance = new PHPExcel_Calculation(); } @@ -1717,6 +1774,19 @@ class PHPExcel_Calculation { return self::$_instance; } // function getInstance() + /** + * Unset an instance of this class + * + * @access public + * @param PHPExcel $workbook Injected workbook identifying the instance to unset + */ + public static function unsetInstance(PHPExcel $workbook = NULL) { + if ($workbook !== NULL) { + if (isset(self::$_workbookSets[$workbook->getID()])) { + unset(self::$_workbookSets[$workbook->getID()]); + } + } + } /** * Flush the calculation cache for any existing instance of this class @@ -1725,21 +1795,29 @@ class PHPExcel_Calculation { * @access public * @return null */ - public static function flushInstance() { - if (isset(self::$_instance) && (self::$_instance !== NULL)) { - self::$_instance->clearCalculationCache(); - } + public function flushInstance() { + $this->clearCalculationCache(); } // function flushInstance() + /** + * Get the debuglog for this claculation engine instance + * + * @access public + * @return PHPExcel_CalcEngine_Logger + */ + public function getDebugLog() { + return $this->_debugLog; + } + /** * __clone implementation. Cloning should not be allowed in a Singleton! * * @access public - * @throws Exception + * @throws PHPExcel_Calculation_Exception */ public final function __clone() { - throw new Exception ('Cloning a Singleton is not allowed!'); + throw new PHPExcel_Calculation_Exception ('Cloning the calculation engine is not allowed!'); } // function __clone() @@ -1775,10 +1853,10 @@ class PHPExcel_Calculation { ($returnType == self::RETURN_ARRAY_AS_ERROR) || ($returnType == self::RETURN_ARRAY_AS_ARRAY)) { self::$returnArrayAsType = $returnType; - return true; + return TRUE; } - return false; - } // function setExcelCalendar() + return FALSE; + } // function setArrayReturnType() /** @@ -1789,7 +1867,7 @@ class PHPExcel_Calculation { */ public static function getArrayReturnType() { return self::$returnArrayAsType; - } // function getExcelCalendar() + } // function getArrayReturnType() /** @@ -1799,18 +1877,17 @@ class PHPExcel_Calculation { * @return boolean */ public function getCalculationCacheEnabled() { - return self::$_calculationCacheEnabled; + return $this->_calculationCacheEnabled; } // function getCalculationCacheEnabled() - /** * Enable/disable calculation cache * * @access public * @param boolean $pValue */ - public function setCalculationCacheEnabled($pValue = true) { - self::$_calculationCacheEnabled = $pValue; + public function setCalculationCacheEnabled($pValue = TRUE) { + $this->_calculationCacheEnabled = $pValue; $this->clearCalculationCache(); } // function setCalculationCacheEnabled() @@ -1819,7 +1896,7 @@ class PHPExcel_Calculation { * Enable calculation cache */ public function enableCalculationCache() { - $this->setCalculationCacheEnabled(true); + $this->setCalculationCacheEnabled(TRUE); } // function enableCalculationCache() @@ -1827,7 +1904,7 @@ class PHPExcel_Calculation { * Disable calculation cache */ public function disableCalculationCache() { - $this->setCalculationCacheEnabled(false); + $this->setCalculationCacheEnabled(FALSE); } // function disableCalculationCache() @@ -1835,30 +1912,32 @@ class PHPExcel_Calculation { * Clear calculation cache */ public function clearCalculationCache() { - self::$_calculationCache = array(); + $this->_calculationCache = array(); } // function clearCalculationCache() + /** + * Clear calculation cache for a specified worksheet + * + * @param string $worksheetName + */ + public function clearCalculationCacheForWorksheet($worksheetName) { + if (isset($this->_calculationCache[$worksheetName])) { + unset($this->_calculationCache[$worksheetName]); + } + } // function clearCalculationCacheForWorksheet() /** - * Get calculation cache expiration time + * Rename calculation cache for a specified worksheet * - * @return float + * @param string $fromWorksheetName + * @param string $toWorksheetName */ - public function getCalculationCacheExpirationTime() { - return self::$_calculationCacheExpirationTime; - } // getCalculationCacheExpirationTime() - - - /** - * Set calculation cache expiration time - * - * @param float $pValue - */ - public function setCalculationCacheExpirationTime($pValue = 15) { - self::$_calculationCacheExpirationTime = $pValue; - } // function setCalculationCacheExpirationTime() - - + public function renameCalculationCacheForWorksheet($fromWorksheetName, $toWorksheetName) { + if (isset($this->_calculationCache[$fromWorksheetName])) { + $this->_calculationCache[$toWorksheetName] = &$this->_calculationCache[$fromWorksheetName]; + unset($this->_calculationCache[$fromWorksheetName]); + } + } // function renameCalculationCacheForWorksheet() /** @@ -1874,15 +1953,19 @@ class PHPExcel_Calculation { /** * Set the locale code * + * @param string $locale The locale to use for formula translation * @return boolean */ - public function setLocale($locale='en_us') { + public function setLocale($locale = 'en_us') { // Identify our locale and language $language = $locale = strtolower($locale); - if (strpos($locale,'_') !== false) { + if (strpos($locale,'_') !== FALSE) { list($language) = explode('_',$locale); } + if (count(self::$_validLocaleLanguages) == 1) + self::_loadLocales(); + // Test whether we have any language data for this language (any locale) if (in_array($language,self::$_validLocaleLanguages)) { // initialise language/locale settings @@ -1897,14 +1980,14 @@ class PHPExcel_Calculation { // If there isn't a locale specific function file, look for a language specific function file $functionNamesFile = PHPEXCEL_ROOT . 'PHPExcel'.DIRECTORY_SEPARATOR.'locale'.DIRECTORY_SEPARATOR.$language.DIRECTORY_SEPARATOR.'functions'; if (!file_exists($functionNamesFile)) { - return false; + return FALSE; } } // Retrieve the list of locale or language specific function names $localeFunctions = file($functionNamesFile,FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); foreach ($localeFunctions as $localeFunction) { list($localeFunction) = explode('##',$localeFunction); // Strip out comments - if (strpos($localeFunction,'=') !== false) { + if (strpos($localeFunction,'=') !== FALSE) { list($fName,$lfName) = explode('=',$localeFunction); $fName = trim($fName); $lfName = trim($lfName); @@ -1925,7 +2008,7 @@ class PHPExcel_Calculation { $localeSettings = file($configFile,FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); foreach ($localeSettings as $localeSetting) { list($localeSetting) = explode('##',$localeSetting); // Strip out comments - if (strpos($localeSetting,'=') !== false) { + if (strpos($localeSetting,'=') !== FALSE) { list($settingName,$settingValue) = explode('=',$localeSetting); $settingName = strtoupper(trim($settingName)); switch ($settingName) { @@ -1939,11 +2022,11 @@ class PHPExcel_Calculation { } self::$functionReplaceFromExcel = self::$functionReplaceToExcel = - self::$functionReplaceFromLocale = self::$functionReplaceToLocale = null; + self::$functionReplaceFromLocale = self::$functionReplaceToLocale = NULL; self::$_localeLanguage = $locale; - return true; + return TRUE; } - return false; + return FALSE; } // function setLocale() @@ -1953,9 +2036,9 @@ class PHPExcel_Calculation { for ($i = 0; $i < $strlen; ++$i) { $chr = mb_substr($formula,$i,1); switch ($chr) { - case '{' : $inBraces = true; + case '{' : $inBraces = TRUE; break; - case '}' : $inBraces = false; + case '}' : $inBraces = FALSE; break; case $fromSeparator : if (!$inBraces) { @@ -1969,13 +2052,13 @@ class PHPExcel_Calculation { private static function _translateFormula($from,$to,$formula,$fromSeparator,$toSeparator) { // Convert any Excel function names to the required language if (self::$_localeLanguage !== 'en_us') { - $inBraces = false; + $inBraces = FALSE; // If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators - if (strpos($formula,'"') !== false) { + if (strpos($formula,'"') !== FALSE) { // So instead we skip replacing in any quoted strings by only replacing in every other array element after we've exploded // the formula $temp = explode('"',$formula); - $i = false; + $i = FALSE; foreach($temp as &$value) { // Only count/replace in alternating array entries if ($i = !$i) { @@ -1996,8 +2079,8 @@ class PHPExcel_Calculation { return $formula; } - private static $functionReplaceFromExcel = null; - private static $functionReplaceToLocale = null; + private static $functionReplaceFromExcel = NULL; + private static $functionReplaceToLocale = NULL; public function _translateFormulaToLocale($formula) { if (self::$functionReplaceFromExcel === NULL) { @@ -2025,8 +2108,8 @@ class PHPExcel_Calculation { } // function _translateFormulaToLocale() - private static $functionReplaceFromLocale = null; - private static $functionReplaceToExcel = null; + private static $functionReplaceFromLocale = NULL; + private static $functionReplaceToExcel = NULL; public function _translateFormulaToEnglish($formula) { if (self::$functionReplaceFromLocale === NULL) { @@ -2120,13 +2203,13 @@ class PHPExcel_Calculation { * @access public * @param PHPExcel_Cell $pCell Cell to calculate * @return mixed - * @throws Exception + * @throws PHPExcel_Calculation_Exception */ - public function calculate(PHPExcel_Cell $pCell = null) { + public function calculate(PHPExcel_Cell $pCell = NULL) { try { return $this->calculateCellValue($pCell); - } catch (Exception $e) { - throw(new Exception($e->getMessage())); + } catch (PHPExcel_Exception $e) { + throw new PHPExcel_Calculation_Exception($e->getMessage()); } } // function calculate() @@ -2138,35 +2221,33 @@ class PHPExcel_Calculation { * @param PHPExcel_Cell $pCell Cell to calculate * @param Boolean $resetLog Flag indicating whether the debug log should be reset or not * @return mixed - * @throws Exception + * @throws PHPExcel_Calculation_Exception */ - public function calculateCellValue(PHPExcel_Cell $pCell = null, $resetLog = true) { - if ($resetLog) { - // Initialise the logging settings if requested - $this->formulaError = null; - $this->debugLog = $this->debugLogStack = array(); - $this->_cyclicFormulaCount = 1; - - $returnArrayAsType = self::$returnArrayAsType; - self::$returnArrayAsType = self::RETURN_ARRAY_AS_ARRAY; - } - - // Read the formula from the cell + public function calculateCellValue(PHPExcel_Cell $pCell = NULL, $resetLog = TRUE) { if ($pCell === NULL) { return NULL; } + $returnArrayAsType = self::$returnArrayAsType; if ($resetLog) { - self::$returnArrayAsType = $returnArrayAsType; + // Initialise the logging settings if requested + $this->formulaError = null; + $this->_debugLog->clearLog(); + $this->_cyclicReferenceStack->clear(); + $this->_cyclicFormulaCount = 1; + + self::$returnArrayAsType = self::RETURN_ARRAY_AS_ARRAY; } + // Execute the calculation for the cell formula try { $result = self::_unwrapResult($this->_calculateFormulaValue($pCell->getValue(), $pCell->getCoordinate(), $pCell)); - } catch (Exception $e) { - throw(new Exception($e->getMessage())); + } catch (PHPExcel_Exception $e) { + throw new PHPExcel_Calculation_Exception($e->getMessage()); } if ((is_array($result)) && (self::$returnArrayAsType != self::RETURN_ARRAY_AS_ARRAY)) { + self::$returnArrayAsType = $returnArrayAsType; $testResult = PHPExcel_Calculation_Functions::flattenArray($result); if (self::$returnArrayAsType == self::RETURN_ARRAY_AS_ERROR) { return PHPExcel_Calculation_Functions::VALUE(); @@ -2187,6 +2268,8 @@ class PHPExcel_Calculation { } $result = array_shift($testResult); } + self::$returnArrayAsType = $returnArrayAsType; + if ($result === NULL) { return 0; @@ -2202,7 +2285,7 @@ class PHPExcel_Calculation { * * @param string $formula Formula to parse * @return array - * @throws Exception + * @throws PHPExcel_Calculation_Exception */ public function parseFormula($formula) { // Basic validation that this is indeed a formula @@ -2220,33 +2303,57 @@ class PHPExcel_Calculation { /** * Calculate the value of a formula * - * @param string $formula Formula to parse + * @param string $formula Formula to parse + * @param string $cellID Address of the cell to calculate + * @param PHPExcel_Cell $pCell Cell to calculate * @return mixed - * @throws Exception + * @throws PHPExcel_Calculation_Exception */ - public function calculateFormula($formula, $cellID=null, PHPExcel_Cell $pCell = null) { + public function calculateFormula($formula, $cellID=NULL, PHPExcel_Cell $pCell = NULL) { // Initialise the logging settings $this->formulaError = null; - $this->debugLog = $this->debugLogStack = array(); + $this->_debugLog->clearLog(); + $this->_cyclicReferenceStack->clear(); // Disable calculation cacheing because it only applies to cell calculations, not straight formulae // But don't actually flush any cache $resetCache = $this->getCalculationCacheEnabled(); - self::$_calculationCacheEnabled = false; + $this->_calculationCacheEnabled = FALSE; // Execute the calculation try { $result = self::_unwrapResult($this->_calculateFormulaValue($formula, $cellID, $pCell)); - } catch (Exception $e) { - throw(new Exception($e->getMessage())); + } catch (PHPExcel_Exception $e) { + throw new PHPExcel_Calculation_Exception($e->getMessage()); } // Reset calculation cacheing to its previous state - self::$_calculationCacheEnabled = $resetCache; + $this->_calculationCacheEnabled = $resetCache; return $result; } // function calculateFormula() + public function getValueFromCache($worksheetName, $cellID, &$cellValue) { + // Is calculation cacheing enabled? + // Is the value present in calculation cache? +//echo 'Test cache for ',$worksheetName,'!',$cellID,PHP_EOL; + $this->_debugLog->writeDebugLog('Testing cache value for cell ', $worksheetName, '!', $cellID); + if (($this->_calculationCacheEnabled) && (isset($this->_calculationCache[$worksheetName][$cellID]))) { +//echo 'Retrieve from cache',PHP_EOL; + $this->_debugLog->writeDebugLog('Retrieving value for cell ', $worksheetName, '!', $cellID, ' from cache'); + // Return the cached result + $cellValue = $this->_calculationCache[$worksheetName][$cellID]; + return TRUE; + } + return FALSE; + } + + public function saveValueToCache($worksheetName, $cellID, $cellValue) { + if ($this->_calculationCacheEnabled) { + $this->_calculationCache[$worksheetName][$cellID] = $cellValue; + } + } + /** * Parse a cell formula and calculate its value * @@ -2254,57 +2361,26 @@ class PHPExcel_Calculation { * @param string $cellID The ID (e.g. A3) of the cell that we are calculating * @param PHPExcel_Cell $pCell Cell to calculate * @return mixed - * @throws Exception + * @throws PHPExcel_Calculation_Exception */ public function _calculateFormulaValue($formula, $cellID=null, PHPExcel_Cell $pCell = null) { -// echo ''.$cellID.'
'; $cellValue = ''; // Basic validation that this is indeed a formula - // We simply return the "cell value" (formula) if not + // We simply return the cell value if not $formula = trim($formula); if ($formula{0} != '=') return self::_wrapResult($formula); $formula = ltrim(substr($formula,1)); if (!isset($formula{0})) return self::_wrapResult($formula); - $wsTitle = "\x00Wrk"; - if ($pCell !== NULL) { - $pCellParent = $pCell->getParent(); - if ($pCellParent !== NULL) { - $wsTitle = $pCellParent->getTitle(); - } - } - // Is calculation cacheing enabled? - if ($cellID !== NULL) { - if (self::$_calculationCacheEnabled) { - // Is the value present in calculation cache? -// echo 'Testing cache value
'; - if (isset(self::$_calculationCache[$wsTitle][$cellID])) { -// echo 'Value is in cache
'; - $this->_writeDebug('Testing cache value for cell '.$cellID); - // Is cache still valid? - if ((microtime(true) - self::$_calculationCache[$wsTitle][$cellID]['time']) < self::$_calculationCacheExpirationTime) { -// echo 'Cache time is still valid
'; - $this->_writeDebug('Retrieving value for '.$cellID.' from cache'); - // Return the cached result - $returnValue = self::$_calculationCache[$wsTitle][$cellID]['data']; -// echo 'Retrieving data value of '.$returnValue.' for '.$cellID.' from cache
'; - if (is_array($returnValue)) { - $returnValue = PHPExcel_Calculation_Functions::flattenArray($returnValue); - return array_shift($returnValue); - } - return $returnValue; - } else { -// echo 'Cache has expired
'; - $this->_writeDebug('Cache value for '.$cellID.' has expired'); - // Clear the cache if it's no longer valid - unset(self::$_calculationCache[$wsTitle][$cellID]); - } - } - } + $pCellParent = ($pCell !== NULL) ? $pCell->getWorksheet() : NULL; + $wsTitle = ($pCellParent !== NULL) ? $pCellParent->getTitle() : "\x00Wrk"; + + if (($cellID !== NULL) && ($this->getValueFromCache($wsTitle, $cellID, $cellValue))) { + return $cellValue; } - if ((in_array($wsTitle.'!'.$cellID,$this->debugLogStack)) && ($wsTitle != "\x00Wrk")) { + if (($wsTitle{0} !== "\x00") && ($this->_cyclicReferenceStack->onStack($wsTitle.'!'.$cellID))) { if ($this->cyclicFormulaCount <= 0) { return $this->_raiseFormulaError('Cyclic Reference in Formula'); } elseif (($this->_cyclicFormulaCount >= $this->cyclicFormulaCount) && @@ -2322,17 +2398,15 @@ class PHPExcel_Calculation { } } } - $this->debugLogStack[] = $wsTitle.'!'.$cellID; + // Parse the formula onto the token stack and calculate the value + $this->_cyclicReferenceStack->push($wsTitle.'!'.$cellID); $cellValue = $this->_processTokenStack($this->_parseFormula($formula, $pCell), $cellID, $pCell); - array_pop($this->debugLogStack); + $this->_cyclicReferenceStack->pop(); // Save to calculation cache if ($cellID !== NULL) { - if (self::$_calculationCacheEnabled) { - self::$_calculationCache[$wsTitle][$cellID]['time'] = microtime(true); - self::$_calculationCache[$wsTitle][$cellID]['data'] = $cellValue; - } + $this->saveValueToCache($wsTitle, $cellID, $cellValue); } // Return the calculated value @@ -2407,11 +2481,20 @@ class PHPExcel_Calculation { /** * Ensure that paired matrix operands are both matrices of the same size * - * @param mixed &$matrix1 First matrix operand - * @param mixed &$matrix2 Second matrix operand + * @param mixed &$matrix1 First matrix operand + * @param mixed &$matrix2 Second matrix operand + * @param integer $matrix1Rows Row size of first matrix operand + * @param integer $matrix1Columns Column size of first matrix operand + * @param integer $matrix2Rows Row size of second matrix operand + * @param integer $matrix2Columns Column size of second matrix operand */ private static function _resizeMatricesShrink(&$matrix1,&$matrix2,$matrix1Rows,$matrix1Columns,$matrix2Rows,$matrix2Columns) { if (($matrix2Columns < $matrix1Columns) || ($matrix2Rows < $matrix1Rows)) { + if ($matrix2Rows < $matrix1Rows) { + for ($i = $matrix2Rows; $i < $matrix1Rows; ++$i) { + unset($matrix1[$i]); + } + } if ($matrix2Columns < $matrix1Columns) { for ($i = 0; $i < $matrix1Rows; ++$i) { for ($j = $matrix2Columns; $j < $matrix1Columns; ++$j) { @@ -2419,14 +2502,14 @@ class PHPExcel_Calculation { } } } - if ($matrix2Rows < $matrix1Rows) { - for ($i = $matrix2Rows; $i < $matrix1Rows; ++$i) { - unset($matrix1[$i]); - } - } } if (($matrix1Columns < $matrix2Columns) || ($matrix1Rows < $matrix2Rows)) { + if ($matrix1Rows < $matrix2Rows) { + for ($i = $matrix1Rows; $i < $matrix2Rows; ++$i) { + unset($matrix2[$i]); + } + } if ($matrix1Columns < $matrix2Columns) { for ($i = 0; $i < $matrix2Rows; ++$i) { for ($j = $matrix1Columns; $j < $matrix2Columns; ++$j) { @@ -2434,11 +2517,6 @@ class PHPExcel_Calculation { } } } - if ($matrix1Rows < $matrix2Rows) { - for ($i = $matrix1Rows; $i < $matrix2Rows; ++$i) { - unset($matrix2[$i]); - } - } } } // function _resizeMatricesShrink() @@ -2448,6 +2526,10 @@ class PHPExcel_Calculation { * * @param mixed &$matrix1 First matrix operand * @param mixed &$matrix2 Second matrix operand + * @param integer $matrix1Rows Row size of first matrix operand + * @param integer $matrix1Columns Column size of first matrix operand + * @param integer $matrix2Rows Row size of second matrix operand + * @param integer $matrix2Columns Column size of second matrix operand */ private static function _resizeMatricesExtend(&$matrix1,&$matrix2,$matrix1Rows,$matrix1Columns,$matrix2Rows,$matrix2Columns) { if (($matrix2Columns < $matrix1Columns) || ($matrix2Rows < $matrix1Rows)) { @@ -2493,7 +2575,7 @@ class PHPExcel_Calculation { * @return mixed */ private function _showValue($value) { - if ($this->writeDebugLog) { + if ($this->_debugLog->getWriteDebugLog()) { $testArray = PHPExcel_Calculation_Functions::flattenArray($value); if (count($testArray) == 1) { $value = array_pop($testArray); @@ -2528,7 +2610,7 @@ class PHPExcel_Calculation { * @return mixed */ private function _showTypeDetails($value) { - if ($this->writeDebugLog) { + if ($this->_debugLog->getWriteDebugLog()) { $testArray = PHPExcel_Calculation_Functions::flattenArray($value); if (count($testArray) == 1) { $value = array_pop($testArray); @@ -2563,15 +2645,15 @@ class PHPExcel_Calculation { static $matrixReplaceTo = array('MKMATRIX(MKMATRIX(','),MKMATRIX(','))'); // Convert any Excel matrix references to the MKMATRIX() function - if (strpos($formula,'{') !== false) { + if (strpos($formula,'{') !== FALSE) { // If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators - if (strpos($formula,'"') !== false) { + if (strpos($formula,'"') !== FALSE) { // So instead we skip replacing in any quoted strings by only replacing in every other array element after we've exploded // the formula $temp = explode('"',$formula); // Open and Closed counts used for trapping mismatched braces in the formula $openCount = $closeCount = 0; - $i = false; + $i = FALSE; foreach($temp as &$value) { // Only count/replace in alternating array entries if ($i = !$i) { @@ -2614,49 +2696,52 @@ class PHPExcel_Calculation { } // function _mkMatrix() + // Binary Operators + // These operators always work on two values + // Array key is the operator, the value indicates whether this is a left or right associative operator + private static $_operatorAssociativity = array( + '^' => 0, // Exponentiation + '*' => 0, '/' => 0, // Multiplication and Division + '+' => 0, '-' => 0, // Addition and Subtraction + '&' => 0, // Concatenation + '|' => 0, ':' => 0, // Intersect and Range + '>' => 0, '<' => 0, '=' => 0, '>=' => 0, '<=' => 0, '<>' => 0 // Comparison + ); + + // Comparison (Boolean) Operators + // These operators work on two values, but always return a boolean result + private static $_comparisonOperators = array('>' => TRUE, '<' => TRUE, '=' => TRUE, '>=' => TRUE, '<=' => TRUE, '<>' => TRUE); + + // Operator Precedence + // This list includes all valid operators, whether binary (including boolean) or unary (such as %) + // Array key is the operator, the value is its precedence + private static $_operatorPrecedence = array( + ':' => 8, // Range + '|' => 7, // Intersect + '~' => 6, // Negation + '%' => 5, // Percentage + '^' => 4, // Exponentiation + '*' => 3, '/' => 3, // Multiplication and Division + '+' => 2, '-' => 2, // Addition and Subtraction + '&' => 1, // Concatenation + '>' => 0, '<' => 0, '=' => 0, '>=' => 0, '<=' => 0, '<>' => 0 // Comparison + ); + // Convert infix to postfix notation - private function _parseFormula($formula, PHPExcel_Cell $pCell = null) { - if (($formula = self::_convertMatrixReferences(trim($formula))) === false) { + private function _parseFormula($formula, PHPExcel_Cell $pCell = NULL) { + if (($formula = self::_convertMatrixReferences(trim($formula))) === FALSE) { return FALSE; } // If we're using cell caching, then $pCell may well be flushed back to the cache (which detaches the parent worksheet), // so we store the parent worksheet so that we can re-attach it when necessary - $pCellParent = ($pCell !== NULL) ? $pCell->getParent() : NULL; - - // Binary Operators - // These operators always work on two values - // Array key is the operator, the value indicates whether this is a left or right associative operator - $operatorAssociativity = array('^' => 0, // Exponentiation - '*' => 0, '/' => 0, // Multiplication and Division - '+' => 0, '-' => 0, // Addition and Subtraction - '&' => 0, // Concatenation - '|' => 0, ':' => 0, // Intersect and Range - '>' => 0, '<' => 0, '=' => 0, '>=' => 0, '<=' => 0, '<>' => 0 // Comparison - ); - // Comparison (Boolean) Operators - // These operators work on two values, but always return a boolean result - $comparisonOperators = array('>' => true, '<' => true, '=' => true, '>=' => true, '<=' => true, '<>' => true); - - // Operator Precedence - // This list includes all valid operators, whether binary (including boolean) or unary (such as %) - // Array key is the operator, the value is its precedence - $operatorPrecedence = array(':' => 8, // Range - '|' => 7, // Intersect - '~' => 6, // Negation - '%' => 5, // Percentage - '^' => 4, // Exponentiation - '*' => 3, '/' => 3, // Multiplication and Division - '+' => 2, '-' => 2, // Addition and Subtraction - '&' => 1, // Concatenation - '>' => 0, '<' => 0, '=' => 0, '>=' => 0, '<=' => 0, '<>' => 0 // Comparison - ); + $pCellParent = ($pCell !== NULL) ? $pCell->getWorksheet() : NULL; $regexpMatchString = '/^('.self::CALCULATION_REGEXP_FUNCTION. + '|'.self::CALCULATION_REGEXP_CELLREF. '|'.self::CALCULATION_REGEXP_NUMBER. '|'.self::CALCULATION_REGEXP_STRING. '|'.self::CALCULATION_REGEXP_OPENBRACE. - '|'.self::CALCULATION_REGEXP_CELLREF. '|'.self::CALCULATION_REGEXP_NAMEDRANGE. '|'.self::CALCULATION_REGEXP_ERROR. ')/si'; @@ -2665,55 +2750,55 @@ class PHPExcel_Calculation { $index = 0; $stack = new PHPExcel_Calculation_Token_Stack; $output = array(); - $expectingOperator = false; // We use this test in syntax-checking the expression to determine when a + $expectingOperator = FALSE; // We use this test in syntax-checking the expression to determine when a // - is a negation or + is a positive operator rather than an operation - $expectingOperand = false; // We use this test in syntax-checking the expression to determine whether an operand + $expectingOperand = FALSE; // We use this test in syntax-checking the expression to determine whether an operand // should be null in a function call // The guts of the lexical parser // Loop through the formula extracting each operator and operand in turn - while(true) { -// echo 'Assessing Expression '.substr($formula, $index).'
'; + while(TRUE) { +//echo 'Assessing Expression '.substr($formula, $index),PHP_EOL; $opCharacter = $formula{$index}; // Get the first character of the value at the current index position -// echo 'Initial character of expression block is '.$opCharacter.'
'; - if ((isset($comparisonOperators[$opCharacter])) && (strlen($formula) > $index) && (isset($comparisonOperators[$formula{$index+1}]))) { +//echo 'Initial character of expression block is '.$opCharacter,PHP_EOL; + if ((isset(self::$_comparisonOperators[$opCharacter])) && (strlen($formula) > $index) && (isset(self::$_comparisonOperators[$formula{$index+1}]))) { $opCharacter .= $formula{++$index}; -// echo 'Initial character of expression block is comparison operator '.$opCharacter.'
'; +//echo 'Initial character of expression block is comparison operator '.$opCharacter.PHP_EOL; } // Find out if we're currently at the beginning of a number, variable, cell reference, function, parenthesis or operand $isOperandOrFunction = preg_match($regexpMatchString, substr($formula, $index), $match); -// echo '$isOperandOrFunction is '.(($isOperandOrFunction) ? 'True' : 'False').'
'; -// var_dump($match); +//echo '$isOperandOrFunction is '.(($isOperandOrFunction) ? 'True' : 'False').PHP_EOL; +//var_dump($match); if ($opCharacter == '-' && !$expectingOperator) { // Is it a negation instead of a minus? -// echo 'Element is a Negation operator
'; +//echo 'Element is a Negation operator',PHP_EOL; $stack->push('Unary Operator','~'); // Put a negation on the stack ++$index; // and drop the negation symbol } elseif ($opCharacter == '%' && $expectingOperator) { -// echo 'Element is a Percentage operator
'; +//echo 'Element is a Percentage operator',PHP_EOL; $stack->push('Unary Operator','%'); // Put a percentage on the stack ++$index; } elseif ($opCharacter == '+' && !$expectingOperator) { // Positive (unary plus rather than binary operator plus) can be discarded? -// echo 'Element is a Positive number, not Plus operator
'; +//echo 'Element is a Positive number, not Plus operator',PHP_EOL; ++$index; // Drop the redundant plus symbol } elseif ((($opCharacter == '~') || ($opCharacter == '|')) && (!$isOperandOrFunction)) { // We have to explicitly deny a tilde or pipe, because they are legal return $this->_raiseFormulaError("Formula Error: Illegal character '~'"); // on the stack but not in the input expression } elseif ((isset(self::$_operators[$opCharacter]) or $isOperandOrFunction) && $expectingOperator) { // Are we putting an operator on the stack? -// echo 'Element with value '.$opCharacter.' is an Operator
'; +//echo 'Element with value '.$opCharacter.' is an Operator',PHP_EOL; while($stack->count() > 0 && ($o2 = $stack->last()) && isset(self::$_operators[$o2['value']]) && - @($operatorAssociativity[$opCharacter] ? $operatorPrecedence[$opCharacter] < $operatorPrecedence[$o2['value']] : $operatorPrecedence[$opCharacter] <= $operatorPrecedence[$o2['value']])) { + @(self::$_operatorAssociativity[$opCharacter] ? self::$_operatorPrecedence[$opCharacter] < self::$_operatorPrecedence[$o2['value']] : self::$_operatorPrecedence[$opCharacter] <= self::$_operatorPrecedence[$o2['value']])) { $output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output } $stack->push('Binary Operator',$opCharacter); // Finally put our current operator onto the stack ++$index; - $expectingOperator = false; + $expectingOperator = FALSE; } elseif ($opCharacter == ')' && $expectingOperator) { // Are we expecting to close a parenthesis? -// echo 'Element is a Closing bracket
'; - $expectingOperand = false; +//echo 'Element is a Closing bracket',PHP_EOL; + $expectingOperand = FALSE; while (($o2 = $stack->pop()) && $o2['value'] != '(') { // Pop off the stack back to the last ( if ($o2 === NULL) return $this->_raiseFormulaError('Formula Error: Unexpected closing brace ")"'); else $output[] = $o2; @@ -2721,65 +2806,65 @@ class PHPExcel_Calculation { $d = $stack->last(2); if (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $d['value'], $matches)) { // Did this parenthesis just close a function? $functionName = $matches[1]; // Get the function name -// echo 'Closed Function is '.$functionName.'
'; +//echo 'Closed Function is '.$functionName,PHP_EOL; $d = $stack->pop(); $argumentCount = $d['value']; // See how many arguments there were (argument count is the next value stored on the stack) -// if ($argumentCount == 0) { -// echo 'With no arguments
'; -// } elseif ($argumentCount == 1) { -// echo 'With 1 argument
'; -// } else { -// echo 'With '.$argumentCount.' arguments
'; -// } +//if ($argumentCount == 0) { +// echo 'With no arguments',PHP_EOL; +//} elseif ($argumentCount == 1) { +// echo 'With 1 argument',PHP_EOL; +//} else { +// echo 'With '.$argumentCount.' arguments',PHP_EOL; +//} $output[] = $d; // Dump the argument count on the output $output[] = $stack->pop(); // Pop the function and push onto the output if (isset(self::$_controlFunctions[$functionName])) { -// echo 'Built-in function '.$functionName.'
'; +//echo 'Built-in function '.$functionName,PHP_EOL; $expectedArgumentCount = self::$_controlFunctions[$functionName]['argumentCount']; $functionCall = self::$_controlFunctions[$functionName]['functionCall']; } elseif (isset(self::$_PHPExcelFunctions[$functionName])) { -// echo 'PHPExcel function '.$functionName.'
'; +//echo 'PHPExcel function '.$functionName,PHP_EOL; $expectedArgumentCount = self::$_PHPExcelFunctions[$functionName]['argumentCount']; $functionCall = self::$_PHPExcelFunctions[$functionName]['functionCall']; } else { // did we somehow push a non-function on the stack? this should never happen return $this->_raiseFormulaError("Formula Error: Internal error, non-function on stack"); } // Check the argument count - $argumentCountError = false; + $argumentCountError = FALSE; if (is_numeric($expectedArgumentCount)) { if ($expectedArgumentCount < 0) { -// echo '$expectedArgumentCount is between 0 and '.abs($expectedArgumentCount).'
'; +//echo '$expectedArgumentCount is between 0 and '.abs($expectedArgumentCount),PHP_EOL; if ($argumentCount > abs($expectedArgumentCount)) { - $argumentCountError = true; + $argumentCountError = TRUE; $expectedArgumentCountString = 'no more than '.abs($expectedArgumentCount); } } else { -// echo '$expectedArgumentCount is numeric '.$expectedArgumentCount.'
'; +//echo '$expectedArgumentCount is numeric '.$expectedArgumentCount,PHP_EOL; if ($argumentCount != $expectedArgumentCount) { - $argumentCountError = true; + $argumentCountError = TRUE; $expectedArgumentCountString = $expectedArgumentCount; } } } elseif ($expectedArgumentCount != '*') { $isOperandOrFunction = preg_match('/(\d*)([-+,])(\d*)/',$expectedArgumentCount,$argMatch); -// print_r($argMatch); -// echo '
'; +//print_r($argMatch); +//echo PHP_EOL; switch ($argMatch[2]) { case '+' : if ($argumentCount < $argMatch[1]) { - $argumentCountError = true; + $argumentCountError = TRUE; $expectedArgumentCountString = $argMatch[1].' or more '; } break; case '-' : if (($argumentCount < $argMatch[1]) || ($argumentCount > $argMatch[3])) { - $argumentCountError = true; + $argumentCountError = TRUE; $expectedArgumentCountString = 'between '.$argMatch[1].' and '.$argMatch[3]; } break; case ',' : if (($argumentCount != $argMatch[1]) && ($argumentCount != $argMatch[3])) { - $argumentCountError = true; + $argumentCountError = TRUE; $expectedArgumentCountString = 'either '.$argMatch[1].' or '.$argMatch[3]; } break; @@ -2792,7 +2877,7 @@ class PHPExcel_Calculation { ++$index; } elseif ($opCharacter == ',') { // Is this the separator for function arguments? -// echo 'Element is a Function argument separator
'; +//echo 'Element is a Function argument separator',PHP_EOL; while (($o2 = $stack->pop()) && $o2['value'] != '(') { // Pop off the stack back to the last ( if ($o2 === NULL) return $this->_raiseFormulaError("Formula Error: Unexpected ,"); else $output[] = $o2; // pop the argument expression stuff and push onto the output @@ -2800,7 +2885,7 @@ class PHPExcel_Calculation { // If we've a comma when we're expecting an operand, then what we actually have is a null operand; // so push a null onto the stack if (($expectingOperand) || (!$expectingOperator)) { - $output[] = array('type' => 'NULL Value', 'value' => self::$_ExcelConstants['NULL'], 'reference' => null); + $output[] = array('type' => 'NULL Value', 'value' => self::$_ExcelConstants['NULL'], 'reference' => NULL); } // make sure there was a function $d = $stack->last(2); @@ -2809,8 +2894,8 @@ class PHPExcel_Calculation { $d = $stack->pop(); $stack->push($d['type'],++$d['value'],$d['reference']); // increment the argument count $stack->push('Brace', '('); // put the ( back on, we'll need to pop back to it again - $expectingOperator = false; - $expectingOperand = true; + $expectingOperator = FALSE; + $expectingOperand = TRUE; ++$index; } elseif ($opCharacter == '(' && !$expectingOperator) { @@ -2819,8 +2904,8 @@ class PHPExcel_Calculation { ++$index; } elseif ($isOperandOrFunction && !$expectingOperator) { // do we now have a function/variable/number? - $expectingOperator = true; - $expectingOperand = false; + $expectingOperator = TRUE; + $expectingOperand = FALSE; $val = $match[1]; $length = strlen($val); // echo 'Element with value '.$val.' is an Operand, Variable, Constant, String, Number, Cell Reference or Function
'; @@ -2833,14 +2918,14 @@ class PHPExcel_Calculation { $ax = preg_match('/^\s*(\s*\))/i', substr($formula, $index+$length), $amatch); if ($ax) { $stack->push('Operand Count for Function '.strtoupper($val).')', 0); - $expectingOperator = true; + $expectingOperator = TRUE; } else { $stack->push('Operand Count for Function '.strtoupper($val).')', 1); - $expectingOperator = false; + $expectingOperator = FALSE; } $stack->push('Brace', '('); } else { // it's a var w/ implicit multiplication - $output[] = array('type' => 'Value', 'value' => $matches[1], 'reference' => null); + $output[] = array('type' => 'Value', 'value' => $matches[1], 'reference' => NULL); } } elseif (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'$/i', $val, $matches)) { // echo 'Element '.$val.' is a Cell reference
'; @@ -2865,7 +2950,7 @@ class PHPExcel_Calculation { } $output[] = array('type' => 'Cell Reference', 'value' => $val, 'reference' => $val); -// $expectingOperator = false; +// $expectingOperator = FALSE; } else { // it's a variable, constant, string, number or boolean // echo 'Element is a Variable, Constant, String, Number or Boolean
'; // If the last entry on the stack was a : operator, then we may have a row or column range reference @@ -2873,12 +2958,12 @@ class PHPExcel_Calculation { if ($testPrevOp['value'] == ':') { $startRowColRef = $output[count($output)-1]['value']; $rangeWS1 = ''; - if (strpos('!',$startRowColRef) !== false) { + if (strpos('!',$startRowColRef) !== FALSE) { list($rangeWS1,$startRowColRef) = explode('!',$startRowColRef); } if ($rangeWS1 != '') $rangeWS1 .= '!'; $rangeWS2 = $rangeWS1; - if (strpos('!',$val) !== false) { + if (strpos('!',$val) !== FALSE) { list($rangeWS2,$val) = explode('!',$val); } if ($rangeWS2 != '') $rangeWS2 .= '!'; @@ -2897,14 +2982,14 @@ class PHPExcel_Calculation { } } - $localeConstant = false; + $localeConstant = FALSE; if ($opCharacter == '"') { // echo 'Element is a String
'; // UnEscape any quotes within the string $val = self::_wrapResult(str_replace('""','"',self::_unwrapResult($val))); } elseif (is_numeric($val)) { // echo 'Element is a Number
'; - if ((strpos($val,'.') !== false) || (stripos($val,'e') !== false) || ($val > PHP_INT_MAX) || ($val < -PHP_INT_MAX)) { + if ((strpos($val,'.') !== FALSE) || (stripos($val,'e') !== FALSE) || ($val > PHP_INT_MAX) || ($val < -PHP_INT_MAX)) { // echo 'Casting '.$val.' to float
'; $val = (float) $val; } else { @@ -2915,11 +3000,11 @@ class PHPExcel_Calculation { $excelConstant = trim(strtoupper($val)); // echo 'Element '.$excelConstant.' is an Excel Constant
'; $val = self::$_ExcelConstants[$excelConstant]; - } elseif (($localeConstant = array_search(trim(strtoupper($val)), self::$_localeBoolean)) !== false) { + } elseif (($localeConstant = array_search(trim(strtoupper($val)), self::$_localeBoolean)) !== FALSE) { // echo 'Element '.$localeConstant.' is an Excel Constant
'; $val = self::$_ExcelConstants[$localeConstant]; } - $details = array('type' => 'Value', 'value' => $val, 'reference' => null); + $details = array('type' => 'Value', 'value' => $val, 'reference' => NULL); if ($localeConstant) { $details['localeValue'] = $localeConstant; } $output[] = $details; } @@ -2929,9 +3014,9 @@ class PHPExcel_Calculation { ++$index; } elseif ($opCharacter == ')') { // miscellaneous error checking if ($expectingOperand) { - $output[] = array('type' => 'NULL Value', 'value' => self::$_ExcelConstants['NULL'], 'reference' => null); - $expectingOperand = false; - $expectingOperator = true; + $output[] = array('type' => 'NULL Value', 'value' => self::$_ExcelConstants['NULL'], 'reference' => NULL); + $expectingOperand = FALSE; + $expectingOperator = TRUE; } else { return $this->_raiseFormulaError("Formula Error: Unexpected ')'"); } @@ -2967,17 +3052,17 @@ class PHPExcel_Calculation { while($stack->count() > 0 && ($o2 = $stack->last()) && isset(self::$_operators[$o2['value']]) && - @($operatorAssociativity[$opCharacter] ? $operatorPrecedence[$opCharacter] < $operatorPrecedence[$o2['value']] : $operatorPrecedence[$opCharacter] <= $operatorPrecedence[$o2['value']])) { + @(self::$_operatorAssociativity[$opCharacter] ? self::$_operatorPrecedence[$opCharacter] < self::$_operatorPrecedence[$o2['value']] : self::$_operatorPrecedence[$opCharacter] <= self::$_operatorPrecedence[$o2['value']])) { $output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output } $stack->push('Binary Operator','|'); // Put an Intersect Operator on the stack - $expectingOperator = false; + $expectingOperator = FALSE; } } } while (($op = $stack->pop()) !== NULL) { // pop everything off the stack and push onto output - if ((is_array($opCharacter) && $opCharacter['value'] == '(') || ($opCharacter === '(')) + if ((is_array($op) && $op['value'] == '(') || ($op === '(')) return $this->_raiseFormulaError("Formula Error: Expecting ')'"); // if there are any opening braces on the stack, then braces were unbalanced $output[] = $op; } @@ -3001,11 +3086,12 @@ class PHPExcel_Calculation { } // evaluate postfix notation - private function _processTokenStack($tokens, $cellID = null, PHPExcel_Cell $pCell = null) { - if ($tokens == false) return false; + private function _processTokenStack($tokens, $cellID = NULL, PHPExcel_Cell $pCell = NULL) { + if ($tokens == FALSE) return FALSE; - // If we're using cell caching, then $pCell may well be flushed back to the cache (which detaches the parent worksheet), - // so we store the parent worksheet so that we can re-attach it when necessary + // If we're using cell caching, then $pCell may well be flushed back to the cache (which detaches the parent cell collection), + // so we store the parent cell collection so that we can re-attach it when necessary + $pCellWorksheet = ($pCell !== NULL) ? $pCell->getWorksheet() : NULL; $pCellParent = ($pCell !== NULL) ? $pCell->getParent() : null; $stack = new PHPExcel_Calculation_Token_Stack; @@ -3027,9 +3113,9 @@ class PHPExcel_Calculation { // Log what we're doing if ($token == ':') { - $this->_writeDebug('Evaluating Range '.$this->_showValue($operand1Data['reference']).$token.$this->_showValue($operand2Data['reference'])); + $this->_debugLog->writeDebugLog('Evaluating Range ', $this->_showValue($operand1Data['reference']), ' ', $token, ' ', $this->_showValue($operand2Data['reference'])); } else { - $this->_writeDebug('Evaluating '.$this->_showValue($operand1).' '.$token.' '.$this->_showValue($operand2)); + $this->_debugLog->writeDebugLog('Evaluating ', $this->_showValue($operand1), ' ', $token, ' ', $this->_showValue($operand2)); } // Process the operation in the appropriate manner @@ -3046,12 +3132,12 @@ class PHPExcel_Calculation { // Binary Operators case ':' : // Range $sheet1 = $sheet2 = ''; - if (strpos($operand1Data['reference'],'!') !== false) { + if (strpos($operand1Data['reference'],'!') !== FALSE) { list($sheet1,$operand1Data['reference']) = explode('!',$operand1Data['reference']); } else { - $sheet1 = ($pCellParent !== NULL) ? $pCellParent->getTitle() : ''; + $sheet1 = ($pCellParent !== NULL) ? $pCellWorksheet->getTitle() : ''; } - if (strpos($operand2Data['reference'],'!') !== false) { + if (strpos($operand2Data['reference'],'!') !== FALSE) { list($sheet2,$operand2Data['reference']) = explode('!',$operand2Data['reference']); } else { $sheet2 = $sheet1; @@ -3085,13 +3171,13 @@ class PHPExcel_Calculation { } $cellRef = PHPExcel_Cell::stringFromColumnIndex(min($oCol)).min($oRow).':'.PHPExcel_Cell::stringFromColumnIndex(max($oCol)).max($oRow); if ($pCellParent !== NULL) { - $cellValue = $this->extractCellRange($cellRef, $pCellParent->getParent()->getSheetByName($sheet1), false); + $cellValue = $this->extractCellRange($cellRef, $this->_workbook->getSheetByName($sheet1), FALSE); } else { return $this->_raiseFormulaError('Unable to access Cell Reference'); } $stack->push('Cell Reference',$cellValue,$cellRef); } else { - $stack->push('Error',PHPExcel_Calculation_Functions::REF(),null); + $stack->push('Error',PHPExcel_Calculation_Functions::REF(),NULL); } break; @@ -3129,14 +3215,14 @@ class PHPExcel_Calculation { // Perform the required operation against the operand 1 matrix, passing in operand 2 $matrixResult = $matrix->concat($operand2); $result = $matrixResult->getArray(); - } catch (Exception $ex) { - $this->_writeDebug('JAMA Matrix Exception: '.$ex->getMessage()); + } catch (PHPExcel_Exception $ex) { + $this->_debugLog->writeDebugLog('JAMA Matrix Exception: ', $ex->getMessage()); $result = '#VALUE!'; } } else { $result = '"'.str_replace('""','"',self::_unwrapResult($operand1,'"').self::_unwrapResult($operand2,'"')).'"'; } - $this->_writeDebug('Evaluation Result is '.$this->_showTypeDetails($result)); + $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($result)); $stack->push('Value',$result); break; case '|' : // Intersect @@ -3150,7 +3236,7 @@ class PHPExcel_Calculation { } } $cellRef = PHPExcel_Cell::stringFromColumnIndex(min($oCol)).min($oRow).':'.PHPExcel_Cell::stringFromColumnIndex(max($oCol)).max($oRow); - $this->_writeDebug('Evaluation Result is '.$this->_showTypeDetails($cellIntersect)); + $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($cellIntersect)); $stack->push('Value',$cellIntersect,$cellRef); break; } @@ -3162,11 +3248,11 @@ class PHPExcel_Calculation { $arg = $arg['value']; if ($token === '~') { // echo 'Token is a negation operator
'; - $this->_writeDebug('Evaluating Negation of '.$this->_showValue($arg)); + $this->_debugLog->writeDebugLog('Evaluating Negation of ', $this->_showValue($arg)); $multiplier = -1; } else { // echo 'Token is a percentile operator
'; - $this->_writeDebug('Evaluating Percentile of '.$this->_showValue($arg)); + $this->_debugLog->writeDebugLog('Evaluating Percentile of ', $this->_showValue($arg)); $multiplier = 0.01; } if (is_array($arg)) { @@ -3175,18 +3261,18 @@ class PHPExcel_Calculation { $matrix1 = new PHPExcel_Shared_JAMA_Matrix($arg); $matrixResult = $matrix1->arrayTimesEquals($multiplier); $result = $matrixResult->getArray(); - } catch (Exception $ex) { - $this->_writeDebug('JAMA Matrix Exception: '.$ex->getMessage()); + } catch (PHPExcel_Exception $ex) { + $this->_debugLog->writeDebugLog('JAMA Matrix Exception: ', $ex->getMessage()); $result = '#VALUE!'; } - $this->_writeDebug('Evaluation Result is '.$this->_showTypeDetails($result)); + $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($result)); $stack->push('Value',$result); } else { $this->_executeNumericBinaryOperation($cellID,$multiplier,$arg,'*','arrayTimesEquals',$stack); } } elseif (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'$/i', $token, $matches)) { - $cellRef = null; + $cellRef = NULL; // echo 'Element '.$token.' is a Cell reference
'; if (isset($matches[8])) { // echo 'Reference is a Range of cells
'; @@ -3197,29 +3283,29 @@ class PHPExcel_Calculation { $cellRef = $matches[6].$matches[7].':'.$matches[9].$matches[10]; if ($matches[2] > '') { $matches[2] = trim($matches[2],"\"'"); - if ((strpos($matches[2],'[') !== false) || (strpos($matches[2],']') !== false)) { + if ((strpos($matches[2],'[') !== FALSE) || (strpos($matches[2],']') !== FALSE)) { // It's a Reference to an external workbook (not currently supported) return $this->_raiseFormulaError('Unable to access External Workbook'); } $matches[2] = trim($matches[2],"\"'"); // echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'
'; - $this->_writeDebug('Evaluating Cell Range '.$cellRef.' in worksheet '.$matches[2]); + $this->_debugLog->writeDebugLog('Evaluating Cell Range ', $cellRef, ' in worksheet ', $matches[2]); if ($pCellParent !== NULL) { - $cellValue = $this->extractCellRange($cellRef, $pCellParent->getParent()->getSheetByName($matches[2]), false); + $cellValue = $this->extractCellRange($cellRef, $this->_workbook->getSheetByName($matches[2]), FALSE); } else { return $this->_raiseFormulaError('Unable to access Cell Reference'); } - $this->_writeDebug('Evaluation Result for cells '.$cellRef.' in worksheet '.$matches[2].' is '.$this->_showTypeDetails($cellValue)); + $this->_debugLog->writeDebugLog('Evaluation Result for cells ', $cellRef, ' in worksheet ', $matches[2], ' is ', $this->_showTypeDetails($cellValue)); // $cellRef = $matches[2].'!'.$cellRef; } else { // echo '$cellRef='.$cellRef.' in current worksheet
'; - $this->_writeDebug('Evaluating Cell Range '.$cellRef.' in current worksheet'); + $this->_debugLog->writeDebugLog('Evaluating Cell Range ', $cellRef, ' in current worksheet'); if ($pCellParent !== NULL) { - $cellValue = $this->extractCellRange($cellRef, $pCellParent, false); + $cellValue = $this->extractCellRange($cellRef, $pCellWorksheet, FALSE); } else { return $this->_raiseFormulaError('Unable to access Cell Reference'); } - $this->_writeDebug('Evaluation Result for cells '.$cellRef.' is '.$this->_showTypeDetails($cellValue)); + $this->_debugLog->writeDebugLog('Evaluation Result for cells ', $cellRef, ' is ', $this->_showTypeDetails($cellValue)); } } } else { @@ -3231,34 +3317,35 @@ class PHPExcel_Calculation { $cellRef = $matches[6].$matches[7]; if ($matches[2] > '') { $matches[2] = trim($matches[2],"\"'"); - if ((strpos($matches[2],'[') !== false) || (strpos($matches[2],']') !== false)) { + if ((strpos($matches[2],'[') !== FALSE) || (strpos($matches[2],']') !== FALSE)) { // It's a Reference to an external workbook (not currently supported) return $this->_raiseFormulaError('Unable to access External Workbook'); } // echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'
'; - $this->_writeDebug('Evaluating Cell '.$cellRef.' in worksheet '.$matches[2]); + $this->_debugLog->writeDebugLog('Evaluating Cell ', $cellRef, ' in worksheet ', $matches[2]); if ($pCellParent !== NULL) { - if ($pCellParent->getParent()->getSheetByName($matches[2])->cellExists($cellRef)) { - $cellValue = $this->extractCellRange($cellRef, $pCellParent->getParent()->getSheetByName($matches[2]), false); + $cellSheet = $this->_workbook->getSheetByName($matches[2]); + if ($cellSheet && $cellSheet->cellExists($cellRef)) { + $cellValue = $this->extractCellRange($cellRef, $this->_workbook->getSheetByName($matches[2]), FALSE); $pCell->attach($pCellParent); } else { - $cellValue = null; + $cellValue = NULL; } } else { return $this->_raiseFormulaError('Unable to access Cell Reference'); } - $this->_writeDebug('Evaluation Result for cell '.$cellRef.' in worksheet '.$matches[2].' is '.$this->_showTypeDetails($cellValue)); + $this->_debugLog->writeDebugLog('Evaluation Result for cell ', $cellRef, ' in worksheet ', $matches[2], ' is ', $this->_showTypeDetails($cellValue)); // $cellRef = $matches[2].'!'.$cellRef; } else { // echo '$cellRef='.$cellRef.' in current worksheet
'; - $this->_writeDebug('Evaluating Cell '.$cellRef.' in current worksheet'); - if ($pCellParent->cellExists($cellRef)) { - $cellValue = $this->extractCellRange($cellRef, $pCellParent, false); + $this->_debugLog->writeDebugLog('Evaluating Cell ', $cellRef, ' in current worksheet'); + if ($pCellParent->isDataSet($cellRef)) { + $cellValue = $this->extractCellRange($cellRef, $pCellWorksheet, FALSE); $pCell->attach($pCellParent); } else { - $cellValue = null; + $cellValue = NULL; } - $this->_writeDebug('Evaluation Result for cell '.$cellRef.' is '.$this->_showTypeDetails($cellValue)); + $this->_debugLog->writeDebugLog('Evaluation Result for cell ', $cellRef, ' is ', $this->_showTypeDetails($cellValue)); } } } @@ -3271,7 +3358,7 @@ class PHPExcel_Calculation { $argCount = $stack->pop(); $argCount = $argCount['value']; if ($functionName != 'MKMATRIX') { - $this->_writeDebug('Evaluating Function '.self::_localeFunc($functionName).'() with '.(($argCount == 0) ? 'no' : $argCount).' argument'.(($argCount == 1) ? '' : 's')); + $this->_debugLog->writeDebugLog('Evaluating Function ', self::_localeFunc($functionName), '() with ', (($argCount == 0) ? 'no' : $argCount), ' argument', (($argCount == 1) ? '' : 's')); } if ((isset(self::$_PHPExcelFunctions[$functionName])) || (isset(self::$_controlFunctions[$functionName]))) { // function if (isset(self::$_PHPExcelFunctions[$functionName])) { @@ -3314,30 +3401,30 @@ class PHPExcel_Calculation { // print_r($args); // echo '
'; if ($functionName != 'MKMATRIX') { - if ($this->writeDebugLog) { + if ($this->_debugLog->getWriteDebugLog()) { krsort($argArrayVals); - $this->_writeDebug('Evaluating '. self::_localeFunc($functionName).'( '.implode(self::$_localeArgumentSeparator.' ',PHPExcel_Calculation_Functions::flattenArray($argArrayVals)).' )'); + $this->_debugLog->writeDebugLog('Evaluating ', self::_localeFunc($functionName), '( ', implode(self::$_localeArgumentSeparator.' ',PHPExcel_Calculation_Functions::flattenArray($argArrayVals)), ' )'); } } // Process each argument in turn, building the return value as an array // if (($argCount == 1) && (is_array($args[1])) && ($functionName != 'MKMATRIX')) { // $operand1 = $args[1]; -// $this->_writeDebug('Argument is a matrix: '.$this->_showValue($operand1)); +// $this->_debugLog->writeDebugLog('Argument is a matrix: ', $this->_showValue($operand1)); // $result = array(); // $row = 0; // foreach($operand1 as $args) { // if (is_array($args)) { // foreach($args as $arg) { -// $this->_writeDebug('Evaluating '.self::_localeFunc($functionName).'( '.$this->_showValue($arg).' )'); +// $this->_debugLog->writeDebugLog('Evaluating ', self::_localeFunc($functionName), '( ', $this->_showValue($arg), ' )'); // $r = call_user_func_array($functionCall,$arg); -// $this->_writeDebug('Evaluation Result for '.self::_localeFunc($functionName).'() function call is '.$this->_showTypeDetails($r)); +// $this->_debugLog->writeDebugLog('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($r)); // $result[$row][] = $r; // } // ++$row; // } else { -// $this->_writeDebug('Evaluating '.self::_localeFunc($functionName).'( '.$this->_showValue($args).' )'); +// $this->_debugLog->writeDebugLog('Evaluating ', self::_localeFunc($functionName), '( ', $this->_showValue($args), ' )'); // $r = call_user_func_array($functionCall,$args); -// $this->_writeDebug('Evaluation Result for '.self::_localeFunc($functionName).'() function call is '.$this->_showTypeDetails($r)); +// $this->_debugLog->writeDebugLog('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($r)); // $result[] = $r; // } // } @@ -3346,7 +3433,7 @@ class PHPExcel_Calculation { if ($passCellReference) { $args[] = $pCell; } - if (strpos($functionCall,'::') !== false) { + if (strpos($functionCall,'::') !== FALSE) { $result = call_user_func_array(explode('::',$functionCall),$args); } else { foreach($args as &$arg) { @@ -3357,7 +3444,7 @@ class PHPExcel_Calculation { } // } if ($functionName != 'MKMATRIX') { - $this->_writeDebug('Evaluation Result for '.self::_localeFunc($functionName).'() function call is '.$this->_showTypeDetails($result)); + $this->_debugLog->writeDebugLog('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($result)); } $stack->push('Value',self::_wrapResult($result)); } @@ -3368,7 +3455,7 @@ class PHPExcel_Calculation { $excelConstant = strtoupper($token); // echo 'Token is a PHPExcel constant: '.$excelConstant.'
'; $stack->push('Constant Value',self::$_ExcelConstants[$excelConstant]); - $this->_writeDebug('Evaluating Constant '.$excelConstant.' as '.$this->_showTypeDetails(self::$_ExcelConstants[$excelConstant])); + $this->_debugLog->writeDebugLog('Evaluating Constant ', $excelConstant, ' as ', $this->_showTypeDetails(self::$_ExcelConstants[$excelConstant])); } elseif ((is_numeric($token)) || ($token === NULL) || (is_bool($token)) || ($token == '') || ($token{0} == '"') || ($token{0} == '#')) { // echo 'Token is a number, boolean, string, null or an Excel error
'; $stack->push('Value',$token); @@ -3377,10 +3464,10 @@ class PHPExcel_Calculation { // echo 'Token is a named range
'; $namedRange = $matches[6]; // echo 'Named Range is '.$namedRange.'
'; - $this->_writeDebug('Evaluating Named Range '.$namedRange); - $cellValue = $this->extractNamedRange($namedRange, ((null !== $pCell) ? $pCellParent : null), false); + $this->_debugLog->writeDebugLog('Evaluating Named Range ', $namedRange); + $cellValue = $this->extractNamedRange($namedRange, ((NULL !== $pCell) ? $pCellWorksheet : NULL), FALSE); $pCell->attach($pCellParent); - $this->_writeDebug('Evaluation Result for named range '.$namedRange.' is '.$this->_showTypeDetails($cellValue)); + $this->_debugLog->writeDebugLog('Evaluation Result for named range ', $namedRange, ' is ', $this->_showTypeDetails($cellValue)); $stack->push('Named Range',$cellValue,$namedRange); } else { return $this->_raiseFormulaError("undefined variable '$token'"); @@ -3399,7 +3486,14 @@ class PHPExcel_Calculation { } // function _processTokenStack() - private function _validateBinaryOperand($cellID,&$operand,&$stack) { + private function _validateBinaryOperand($cellID, &$operand, &$stack) { + if (is_array($operand)) { + if ((count($operand, COUNT_RECURSIVE) - count($operand)) == 1) { + do { + $operand = array_pop($operand); + } while (is_array($operand)); + } + } // Numbers, matrices and booleans can pass straight through, as they're already valid if (is_string($operand)) { // We only need special validations for the operand if it is a string @@ -3410,36 +3504,36 @@ class PHPExcel_Calculation { // If not a numeric, test to see if the value is an Excel error, and so can't be used in normal binary operations if ($operand > '' && $operand{0} == '#') { $stack->push('Value', $operand); - $this->_writeDebug('Evaluation Result is '.$this->_showTypeDetails($operand)); - return false; + $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($operand)); + return FALSE; } elseif (!PHPExcel_Shared_String::convertToNumberIfFraction($operand)) { // If not a numeric or a fraction, then it's a text string, and so can't be used in mathematical binary operations $stack->push('Value', '#VALUE!'); - $this->_writeDebug('Evaluation Result is a '.$this->_showTypeDetails('#VALUE!')); - return false; + $this->_debugLog->writeDebugLog('Evaluation Result is a ', $this->_showTypeDetails('#VALUE!')); + return FALSE; } } } // return a true if the value of the operand is one that we can use in normal binary operations - return true; + return TRUE; } // function _validateBinaryOperand() - private function _executeBinaryComparisonOperation($cellID,$operand1,$operand2,$operation,&$stack,$recursingArrays=false) { + private function _executeBinaryComparisonOperation($cellID, $operand1, $operand2, $operation, &$stack, $recursingArrays=FALSE) { // If we're dealing with matrix operations, we want a matrix result if ((is_array($operand1)) || (is_array($operand2))) { $result = array(); if ((is_array($operand1)) && (!is_array($operand2))) { foreach($operand1 as $x => $operandData) { - $this->_writeDebug('Evaluating Comparison '.$this->_showValue($operandData).' '.$operation.' '.$this->_showValue($operand2)); + $this->_debugLog->writeDebugLog('Evaluating Comparison ', $this->_showValue($operandData), ' ', $operation, ' ', $this->_showValue($operand2)); $this->_executeBinaryComparisonOperation($cellID,$operandData,$operand2,$operation,$stack); $r = $stack->pop(); $result[$x] = $r['value']; } } elseif ((!is_array($operand1)) && (is_array($operand2))) { foreach($operand2 as $x => $operandData) { - $this->_writeDebug('Evaluating Comparison '.$this->_showValue($operand1).' '.$operation.' '.$this->_showValue($operandData)); + $this->_debugLog->writeDebugLog('Evaluating Comparison ', $this->_showValue($operand1), ' ', $operation, ' ', $this->_showValue($operandData)); $this->_executeBinaryComparisonOperation($cellID,$operand1,$operandData,$operation,$stack); $r = $stack->pop(); $result[$x] = $r['value']; @@ -3447,32 +3541,54 @@ class PHPExcel_Calculation { } else { if (!$recursingArrays) { self::_checkMatrixOperands($operand1,$operand2,2); } foreach($operand1 as $x => $operandData) { - $this->_writeDebug('Evaluating Comparison '.$this->_showValue($operandData).' '.$operation.' '.$this->_showValue($operand2[$x])); - $this->_executeBinaryComparisonOperation($cellID,$operandData,$operand2[$x],$operation,$stack,true); + $this->_debugLog->writeDebugLog('Evaluating Comparison ', $this->_showValue($operandData), ' ', $operation, ' ', $this->_showValue($operand2[$x])); + $this->_executeBinaryComparisonOperation($cellID,$operandData,$operand2[$x],$operation,$stack,TRUE); $r = $stack->pop(); $result[$x] = $r['value']; } } // Log the result details - $this->_writeDebug('Comparison Evaluation Result is '.$this->_showTypeDetails($result)); + $this->_debugLog->writeDebugLog('Comparison Evaluation Result is ', $this->_showTypeDetails($result)); // And push the result onto the stack $stack->push('Array',$result); - return true; + return TRUE; } // Simple validate the two operands if they are string values if (is_string($operand1) && $operand1 > '' && $operand1{0} == '"') { $operand1 = self::_unwrapResult($operand1); } if (is_string($operand2) && $operand2 > '' && $operand2{0} == '"') { $operand2 = self::_unwrapResult($operand2); } + // Use case insensitive comparaison if not OpenOffice mode + if (PHPExcel_Calculation_Functions::getCompatibilityMode() != PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) + { + if (is_string($operand1)) { + $operand1 = strtoupper($operand1); + } + + if (is_string($operand2)) { + $operand2 = strtoupper($operand2); + } + } + + $useLowercaseFirstComparison = is_string($operand1) && is_string($operand2) && PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE; + // execute the necessary operation switch ($operation) { // Greater than case '>': - $result = ($operand1 > $operand2); + if ($useLowercaseFirstComparison) { + $result = $this->strcmpLowercaseFirst($operand1, $operand2) > 0; + } else { + $result = ($operand1 > $operand2); + } break; // Less than case '<': - $result = ($operand1 < $operand2); + if ($useLowercaseFirstComparison) { + $result = $this->strcmpLowercaseFirst($operand1, $operand2) < 0; + } else { + $result = ($operand1 < $operand2); + } break; // Equality case '=': @@ -3480,11 +3596,19 @@ class PHPExcel_Calculation { break; // Greater than or equal case '>=': - $result = ($operand1 >= $operand2); + if ($useLowercaseFirstComparison) { + $result = $this->strcmpLowercaseFirst($operand1, $operand2) >= 0; + } else { + $result = ($operand1 >= $operand2); + } break; // Less than or equal case '<=': - $result = ($operand1 <= $operand2); + if ($useLowercaseFirstComparison) { + $result = $this->strcmpLowercaseFirst($operand1, $operand2) <= 0; + } else { + $result = ($operand1 <= $operand2); + } break; // Inequality case '<>': @@ -3493,109 +3617,102 @@ class PHPExcel_Calculation { } // Log the result details - $this->_writeDebug('Evaluation Result is '.$this->_showTypeDetails($result)); + $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($result)); // And push the result onto the stack $stack->push('Value',$result); - return true; + return TRUE; } // function _executeBinaryComparisonOperation() + /** + * Compare two strings in the same way as strcmp() except that lowercase come before uppercase letters + * @param string $str1 + * @param string $str2 + * @return integer + */ + private function strcmpLowercaseFirst($str1, $str2) + { + $from = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + $to = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $inversedStr1 = strtr($str1, $from, $to); + $inversedStr2 = strtr($str2, $from, $to); + + return strcmp($inversedStr1, $inversedStr2); + } private function _executeNumericBinaryOperation($cellID,$operand1,$operand2,$operation,$matrixFunction,&$stack) { // Validate the two operands - if (!$this->_validateBinaryOperand($cellID,$operand1,$stack)) return false; - if (!$this->_validateBinaryOperand($cellID,$operand2,$stack)) return false; + if (!$this->_validateBinaryOperand($cellID,$operand1,$stack)) return FALSE; + if (!$this->_validateBinaryOperand($cellID,$operand2,$stack)) return FALSE; - $executeMatrixOperation = false; // If either of the operands is a matrix, we need to treat them both as matrices // (converting the other operand to a matrix if need be); then perform the required // matrix operation if ((is_array($operand1)) || (is_array($operand2))) { - // Ensure that both operands are arrays/matrices - $executeMatrixOperation = true; - $mSize = array(); - list($mSize[],$mSize[],$mSize[],$mSize[]) = self::_checkMatrixOperands($operand1,$operand2,2); + // Ensure that both operands are arrays/matrices of the same size + self::_checkMatrixOperands($operand1, $operand2, 2); - // But if they're both single cell matrices, then we can treat them as simple values - if (array_sum($mSize) == 4) { - $executeMatrixOperation = false; - $operand1 = $operand1[0][0]; - $operand2 = $operand2[0][0]; - } - } - - if ($executeMatrixOperation) { try { // Convert operand 1 from a PHP array to a matrix $matrix = new PHPExcel_Shared_JAMA_Matrix($operand1); // Perform the required operation against the operand 1 matrix, passing in operand 2 $matrixResult = $matrix->$matrixFunction($operand2); $result = $matrixResult->getArray(); - } catch (Exception $ex) { - $this->_writeDebug('JAMA Matrix Exception: '.$ex->getMessage()); + } catch (PHPExcel_Exception $ex) { + $this->_debugLog->writeDebugLog('JAMA Matrix Exception: ', $ex->getMessage()); $result = '#VALUE!'; } } else { if ((PHPExcel_Calculation_Functions::getCompatibilityMode() != PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) && - ((is_string($operand1) && !is_numeric($operand1)) || (is_string($operand2) && !is_numeric($operand2)))) { + ((is_string($operand1) && !is_numeric($operand1) && strlen($operand1)>0) || + (is_string($operand2) && !is_numeric($operand2) && strlen($operand2)>0))) { $result = PHPExcel_Calculation_Functions::VALUE(); } else { // If we're dealing with non-matrix operations, execute the necessary operation switch ($operation) { // Addition case '+': - $result = $operand1+$operand2; + $result = $operand1 + $operand2; break; // Subtraction case '-': - $result = $operand1-$operand2; + $result = $operand1 - $operand2; break; // Multiplication case '*': - $result = $operand1*$operand2; + $result = $operand1 * $operand2; break; // Division case '/': if ($operand2 == 0) { // Trap for Divide by Zero error $stack->push('Value','#DIV/0!'); - $this->_writeDebug('Evaluation Result is '.$this->_showTypeDetails('#DIV/0!')); - return false; + $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails('#DIV/0!')); + return FALSE; } else { - $result = $operand1/$operand2; + $result = $operand1 / $operand2; } break; // Power case '^': - $result = pow($operand1,$operand2); + $result = pow($operand1, $operand2); break; } } } // Log the result details - $this->_writeDebug('Evaluation Result is '.$this->_showTypeDetails($result)); + $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($result)); // And push the result onto the stack $stack->push('Value',$result); - return true; + return TRUE; } // function _executeNumericBinaryOperation() - private function _writeDebug($message) { - // Only write the debug log if logging is enabled - if ($this->writeDebugLog) { - if ($this->echoDebugLog) { - echo implode(' -> ',$this->debugLogStack).' -> '.$message,'
'; - } - $this->debugLog[] = implode(' -> ',$this->debugLogStack).' -> '.$message; - } - } // function _writeDebug() - - // trigger an error, but nicely, if need be protected function _raiseFormulaError($errorMessage) { $this->formulaError = $errorMessage; - $this->debugLogStack = array(); - if (!$this->suppressFormulaErrors) throw new Exception($errorMessage); + $this->_cyclicReferenceStack->clear(); + if (!$this->suppressFormulaErrors) throw new PHPExcel_Calculation_Exception($errorMessage); trigger_error($errorMessage, E_USER_ERROR); } // function _raiseFormulaError() @@ -3603,49 +3720,51 @@ class PHPExcel_Calculation { /** * Extract range values * - * @param string &$pRange String based range representation + * @param string &$pRange String based range representation * @param PHPExcel_Worksheet $pSheet Worksheet + * @param boolean $resetLog Flag indicating whether calculation log should be reset or not * @return mixed Array of values in range if range contains more than one element. Otherwise, a single value is returned. - * @throws Exception + * @throws PHPExcel_Calculation_Exception */ - public function extractCellRange(&$pRange = 'A1', PHPExcel_Worksheet $pSheet = null, $resetLog=true) { + public function extractCellRange(&$pRange = 'A1', PHPExcel_Worksheet $pSheet = NULL, $resetLog = TRUE) { // Return value $returnValue = array (); -// echo 'extractCellRange('.$pRange.')
'; +// echo 'extractCellRange('.$pRange.')',PHP_EOL; if ($pSheet !== NULL) { -// echo 'Passed sheet name is '.$pSheet->getTitle().'
'; -// echo 'Range reference is '.$pRange.'
'; + $pSheetName = $pSheet->getTitle(); +// echo 'Passed sheet name is '.$pSheetName.PHP_EOL; +// echo 'Range reference is '.$pRange.PHP_EOL; if (strpos ($pRange, '!') !== false) { -// echo '$pRange reference includes sheet reference
'; - $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pRange, true); - $pSheet = $pSheet->getParent()->getSheetByName($worksheetReference[0]); -// echo 'New sheet name is '.$pSheet->getTitle().'
'; - $pRange = $worksheetReference[1]; -// echo 'Adjusted Range reference is '.$pRange.'
'; +// echo '$pRange reference includes sheet reference',PHP_EOL; + list($pSheetName,$pRange) = PHPExcel_Worksheet::extractSheetTitle($pRange, true); +// echo 'New sheet name is '.$pSheetName,PHP_EOL; +// echo 'Adjusted Range reference is '.$pRange,PHP_EOL; + $pSheet = $this->_workbook->getSheetByName($pSheetName); } // Extract range $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($pRange); - $pRange = $pSheet->getTitle().'!'.$pRange; + $pRange = $pSheetName.'!'.$pRange; if (!isset($aReferences[1])) { // Single cell in range - list($currentCol,$currentRow) = sscanf($aReferences[0],'%[A-Z]%d'); + sscanf($aReferences[0],'%[A-Z]%d', $currentCol, $currentRow); + $cellValue = NULL; if ($pSheet->cellExists($aReferences[0])) { $returnValue[$currentRow][$currentCol] = $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog); } else { - $returnValue[$currentRow][$currentCol] = null; + $returnValue[$currentRow][$currentCol] = NULL; } } else { // Extract cell data for all cells in the range foreach ($aReferences as $reference) { // Extract range - list($currentCol,$currentRow) = sscanf($reference,'%[A-Z]%d'); - + sscanf($reference,'%[A-Z]%d', $currentCol, $currentRow); + $cellValue = NULL; if ($pSheet->cellExists($reference)) { $returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog); } else { - $returnValue[$currentRow][$currentCol] = null; + $returnValue[$currentRow][$currentCol] = NULL; } } } @@ -3662,23 +3781,24 @@ class PHPExcel_Calculation { * @param string &$pRange String based range representation * @param PHPExcel_Worksheet $pSheet Worksheet * @return mixed Array of values in range if range contains more than one element. Otherwise, a single value is returned. - * @throws Exception + * @param boolean $resetLog Flag indicating whether calculation log should be reset or not + * @throws PHPExcel_Calculation_Exception */ - public function extractNamedRange(&$pRange = 'A1', PHPExcel_Worksheet $pSheet = null, $resetLog=true) { + public function extractNamedRange(&$pRange = 'A1', PHPExcel_Worksheet $pSheet = NULL, $resetLog = TRUE) { // Return value $returnValue = array (); // echo 'extractNamedRange('.$pRange.')
'; if ($pSheet !== NULL) { -// echo 'Current sheet name is '.$pSheet->getTitle().'
'; + $pSheetName = $pSheet->getTitle(); +// echo 'Current sheet name is '.$pSheetName.'
'; // echo 'Range reference is '.$pRange.'
'; if (strpos ($pRange, '!') !== false) { -// echo '$pRange reference includes sheet reference
'; - $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pRange, true); - $pSheet = $pSheet->getParent()->getSheetByName($worksheetReference[0]); -// echo 'New sheet name is '.$pSheet->getTitle().'
'; - $pRange = $worksheetReference[1]; -// echo 'Adjusted Range reference is '.$pRange.'
'; +// echo '$pRange reference includes sheet reference',PHP_EOL; + list($pSheetName,$pRange) = PHPExcel_Worksheet::extractSheetTitle($pRange, true); +// echo 'New sheet name is '.$pSheetName,PHP_EOL; +// echo 'Adjusted Range reference is '.$pRange,PHP_EOL; + $pSheet = $this->_workbook->getSheetByName($pSheetName); } // Named range? @@ -3713,10 +3833,11 @@ class PHPExcel_Calculation { if (!isset($aReferences[1])) { // Single cell (or single column or row) in range list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($aReferences[0]); + $cellValue = NULL; if ($pSheet->cellExists($aReferences[0])) { $returnValue[$currentRow][$currentCol] = $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog); } else { - $returnValue[$currentRow][$currentCol] = null; + $returnValue[$currentRow][$currentCol] = NULL; } } else { // Extract cell data for all cells in the range @@ -3724,10 +3845,11 @@ class PHPExcel_Calculation { // Extract range list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($reference); // echo 'NAMED RANGE: $currentCol='.$currentCol.' $currentRow='.$currentRow.'
'; + $cellValue = NULL; if ($pSheet->cellExists($reference)) { $returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog); } else { - $returnValue[$currentRow][$currentCol] = null; + $returnValue[$currentRow][$currentCol] = NULL; } } } @@ -3751,7 +3873,7 @@ class PHPExcel_Calculation { if (isset(self::$_PHPExcelFunctions[$pFunction])) { return (self::$_PHPExcelFunctions[$pFunction]['functionCall'] != 'PHPExcel_Calculation_Functions::DUMMY'); } else { - return false; + return FALSE; } } // function isImplemented() diff --git a/htdocs/includes/phpexcel/PHPExcel/Calculation/Database.php b/htdocs/includes/phpexcel/PHPExcel/Calculation/Database.php index 4a6c8f72c9a..c3e86d761cb 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Calculation/Database.php +++ b/htdocs/includes/phpexcel/PHPExcel/Calculation/Database.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -41,7 +41,7 @@ if (!defined('PHPEXCEL_ROOT')) { * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_Database { diff --git a/htdocs/includes/phpexcel/PHPExcel/Calculation/DateTime.php b/htdocs/includes/phpexcel/PHPExcel/Calculation/DateTime.php index 3b5dc45aaaa..debd1315073 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Calculation/DateTime.php +++ b/htdocs/includes/phpexcel/PHPExcel/Calculation/DateTime.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -41,7 +41,7 @@ if (!defined('PHPEXCEL_ROOT')) { * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_DateTime { @@ -56,6 +56,18 @@ class PHPExcel_Calculation_DateTime { } // function _isLeapYear() + /** + * Return the number of days between two dates based on a 360 day calendar + * + * @param integer $startDay Day of month of the start date + * @param integer $startMonth Month of the start date + * @param integer $startYear Year of the start date + * @param integer $endDay Day of month of the start date + * @param integer $endMonth Month of the start date + * @param integer $endYear Year of the start date + * @param boolean $methodUS Whether to use the US method or the European method of calculation + * @return integer Number of days between the start date and the end date + */ private static function _dateDiff360($startDay, $startMonth, $startYear, $endDay, $endMonth, $endYear, $methodUS) { if ($startDay == 31) { --$startDay; @@ -92,7 +104,7 @@ class PHPExcel_Calculation_DateTime { (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC)) { return PHPExcel_Calculation_Functions::VALUE(); } - if ((is_object($dateValue)) && ($dateValue instanceof PHPExcel_Shared_Date::$dateTimeObjectType)) { + if ((is_object($dateValue)) && ($dateValue instanceof DateTime)) { $dateValue = PHPExcel_Shared_Date::PHPToExcel($dateValue); } else { $saveReturnDateType = PHPExcel_Calculation_Functions::getReturnDateType(); @@ -238,6 +250,10 @@ class PHPExcel_Calculation_DateTime { * Excel Function: * DATE(year,month,day) * + * PHPExcel is a lot more forgiving than MS Excel when passing non numeric values to this function. + * A Month name or abbreviation (English only at this point) such as 'January' or 'Jan' will still be accepted, + * as will a day value with a suffix (e.g. '21st' rather than simply 21); again only English language. + * * @access public * @category Date/Time Functions * @param integer $year The value of the year argument can include one to four digits. @@ -278,6 +294,14 @@ class PHPExcel_Calculation_DateTime { $month = PHPExcel_Calculation_Functions::flattenSingleValue($month); $day = PHPExcel_Calculation_Functions::flattenSingleValue($day); + if (($month !== NULL) && (!is_numeric($month))) { + $month = PHPExcel_Shared_Date::monthStringToNumber($month); + } + + if (($day !== NULL) && (!is_numeric($day))) { + $day = PHPExcel_Shared_Date::dayStringToNumber($day); + } + $year = ($year !== NULL) ? PHPExcel_Shared_String::testStringAsNumeric($year) : 0; $month = ($month !== NULL) ? PHPExcel_Shared_String::testStringAsNumeric($month) : 0; $day = ($day !== NULL) ? PHPExcel_Shared_String::testStringAsNumeric($day) : 0; @@ -720,6 +744,10 @@ class PHPExcel_Calculation_DateTime { return PHPExcel_Calculation_Functions::VALUE(); } + if (!is_bool($method)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + // Execute function $PHPStartDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($startDate); $startDay = $PHPStartDateObject->format('j'); diff --git a/htdocs/includes/phpexcel/PHPExcel/Calculation/Engineering.php b/htdocs/includes/phpexcel/PHPExcel/Calculation/Engineering.php index cfaffafbab5..7e32aa87081 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Calculation/Engineering.php +++ b/htdocs/includes/phpexcel/PHPExcel/Calculation/Engineering.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -45,7 +45,7 @@ define('EULER', 2.71828182845904523536); * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_Engineering { @@ -741,8 +741,6 @@ class PHPExcel_Calculation_Engineering { /** - * _cleanComplex - * * Cleans the leading characters in a complex number string * * @param string $complexNumber The complex number to clean @@ -756,20 +754,25 @@ class PHPExcel_Calculation_Engineering { return $complexNumber; } - - private static function _nbrConversionFormat($xVal,$places) { + /** + * Formats a number base string value with leading zeroes + * + * @param string $xVal The "number" to pad + * @param integer $places The length that we want to pad this value + * @return string The padded "number" + */ + private static function _nbrConversionFormat($xVal, $places) { if (!is_null($places)) { if (strlen($xVal) <= $places) { - return substr(str_pad($xVal,$places,'0',STR_PAD_LEFT),-10); + return substr(str_pad($xVal, $places, '0', STR_PAD_LEFT), -10); } else { return PHPExcel_Calculation_Functions::NaN(); } } - return substr($xVal,-10); + return substr($xVal, -10); } // function _nbrConversionFormat() - /** * BESSELI * @@ -1932,7 +1935,7 @@ class PHPExcel_Calculation_Engineering { /** * IMLOG2 * - * Returns the common logarithm (base 10) of a complex number in x + yi or x + yj text format. + * Returns the base-2 logarithm of a complex number in x + yi or x + yj text format. * * Excel Function: * IMLOG2(complexNumber) @@ -2356,7 +2359,6 @@ class PHPExcel_Calculation_Engineering { * Returns an array of units of measure, for a specified conversion group, or for all groups * * @param string $group The group whose units of measure you want to retrieve - * * @return array */ public static function getConversionGroupUnits($group = NULL) { @@ -2373,6 +2375,7 @@ class PHPExcel_Calculation_Engineering { /** * getConversionGroupUnitDetails * + * @param string $group The group whose units of measure you want to retrieve * @return array */ public static function getConversionGroupUnitDetails($group = NULL) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Calculation/Exception.php b/htdocs/includes/phpexcel/PHPExcel/Calculation/Exception.php index 31aa287a2a4..037f7884af1 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Calculation/Exception.php +++ b/htdocs/includes/phpexcel/PHPExcel/Calculation/Exception.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,9 +31,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Calculation_Exception extends Exception { +class PHPExcel_Calculation_Exception extends PHPExcel_Exception { /** * Error handler callback * diff --git a/htdocs/includes/phpexcel/PHPExcel/Calculation/ExceptionHandler.php b/htdocs/includes/phpexcel/PHPExcel/Calculation/ExceptionHandler.php index 8b89a8fd6f7..389f6477834 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Calculation/ExceptionHandler.php +++ b/htdocs/includes/phpexcel/PHPExcel/Calculation/ExceptionHandler.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_ExceptionHandler { /** diff --git a/htdocs/includes/phpexcel/PHPExcel/Calculation/Financial.php b/htdocs/includes/phpexcel/PHPExcel/Calculation/Financial.php index 8534258e863..525b172109a 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Calculation/Financial.php +++ b/htdocs/includes/phpexcel/PHPExcel/Calculation/Financial.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -48,7 +48,7 @@ define('FINANCIAL_PRECISION', 1.0e-08); * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_Financial { @@ -1206,13 +1206,22 @@ class PHPExcel_Calculation_Financial { /** * FVSCHEDULE * + * Returns the future value of an initial principal after applying a series of compound interest rates. + * Use FVSCHEDULE to calculate the future value of an investment with a variable or adjustable rate. + * + * Excel Function: + * FVSCHEDULE(principal,schedule) + * + * @param float $principal The present value. + * @param float[] $schedule An array of interest rates to apply. + * @return float */ public static function FVSCHEDULE($principal, $schedule) { $principal = PHPExcel_Calculation_Functions::flattenSingleValue($principal); $schedule = PHPExcel_Calculation_Functions::flattenArray($schedule); - foreach($schedule as $n) { - $principal *= 1 + $n; + foreach($schedule as $rate) { + $principal *= 1 + $rate; } return $principal; @@ -1227,13 +1236,13 @@ class PHPExcel_Calculation_Financial { * Excel Function: * INTRATE(settlement,maturity,investment,redemption[,basis]) * - * @param mixed settlement The security's settlement date. + * @param mixed $settlement The security's settlement date. * The security settlement date is the date after the issue date when the security is traded to the buyer. - * @param mixed maturity The security's maturity date. + * @param mixed $maturity The security's maturity date. * The maturity date is the date when the security expires. - * @param integer investment The amount invested in the security. - * @param integer redemption The amount to be received at maturity. - * @param integer basis The type of day count to use. + * @param integer $investment The amount invested in the security. + * @param integer $redemption The amount to be received at maturity. + * @param integer $basis The type of day count to use. * 0 or omitted US (NASD) 30/360 * 1 Actual/actual * 2 Actual/360 @@ -1273,6 +1282,9 @@ class PHPExcel_Calculation_Financial { * * Returns the interest payment for a given period for an investment based on periodic, constant payments and a constant interest rate. * + * Excel Function: + * IPMT(rate,per,nper,pv[,fv][,type]) + * * @param float $rate Interest rate per period * @param int $per Period for which we want to find the interest * @param int $nper Number of periods @@ -1302,7 +1314,25 @@ class PHPExcel_Calculation_Financial { return $interestAndPrincipal[0]; } // function IPMT() - + /** + * IRR + * + * Returns the internal rate of return for a series of cash flows represented by the numbers in values. + * These cash flows do not have to be even, as they would be for an annuity. However, the cash flows must occur + * at regular intervals, such as monthly or annually. The internal rate of return is the interest rate received + * for an investment consisting of payments (negative values) and income (positive values) that occur at regular + * periods. + * + * Excel Function: + * IRR(values[,guess]) + * + * @param float[] $values An array or a reference to cells that contain numbers for which you want + * to calculate the internal rate of return. + * Values must contain at least one positive value and one negative value to + * calculate the internal rate of return. + * @param float $guess A number that you guess is close to the result of IRR + * @return float + */ public static function IRR($values, $guess = 0.1) { if (!is_array($values)) return PHPExcel_Calculation_Functions::VALUE(); $values = PHPExcel_Calculation_Functions::flattenArray($values); @@ -1336,28 +1366,30 @@ class PHPExcel_Calculation_Financial { $dx *= 0.5; $x_mid = $rtb + $dx; $f_mid = self::NPV($x_mid, $values); - if ($f_mid <= 0.0) $rtb = $x_mid; - if ((abs($f_mid) < FINANCIAL_PRECISION) || (abs($dx) < FINANCIAL_PRECISION)) return $x_mid; + if ($f_mid <= 0.0) + $rtb = $x_mid; + if ((abs($f_mid) < FINANCIAL_PRECISION) || (abs($dx) < FINANCIAL_PRECISION)) + return $x_mid; } return PHPExcel_Calculation_Functions::VALUE(); } // function IRR() /** - * ISPMT + * ISPMT * - * Returns the interest payment for an investment based on an interest rate and a constant payment schedule. + * Returns the interest payment for an investment based on an interest rate and a constant payment schedule. * - * Excel Function: - * =ISPMT(interest_rate, period, number_payments, PV) + * Excel Function: + * =ISPMT(interest_rate, period, number_payments, PV) * - * interest_rate is the interest rate for the investment + * interest_rate is the interest rate for the investment * - * period is the period to calculate the interest rate. It must be betweeen 1 and number_payments. + * period is the period to calculate the interest rate. It must be betweeen 1 and number_payments. * - * number_payments is the number of payments for the annuity + * number_payments is the number of payments for the annuity * - * PV is the loan amount or present value of the payments + * PV is the loan amount or present value of the payments */ public static function ISPMT() { // Return value @@ -1384,6 +1416,22 @@ class PHPExcel_Calculation_Financial { } // function ISPMT() + /** + * MIRR + * + * Returns the modified internal rate of return for a series of periodic cash flows. MIRR considers both + * the cost of the investment and the interest received on reinvestment of cash. + * + * Excel Function: + * MIRR(values,finance_rate, reinvestment_rate) + * + * @param float[] $values An array or a reference to cells that contain a series of payments and + * income occurring at regular intervals. + * Payments are negative value, income is positive values. + * @param float $finance_rate The interest rate you pay on the money used in the cash flows + * @param float $reinvestment_rate The interest rate you receive on the cash flows as you reinvest them + * @return float + */ public static function MIRR($values, $finance_rate, $reinvestment_rate) { if (!is_array($values)) return PHPExcel_Calculation_Functions::VALUE(); $values = PHPExcel_Calculation_Functions::flattenArray($values); @@ -1475,14 +1523,11 @@ class PHPExcel_Calculation_Financial { } } // function NPER() - /** * NPV * * Returns the Net Present Value of a cash flow series given a discount rate. * - * @param float Discount interest rate - * @param array Cash flow series * @return float */ public static function NPV() { @@ -1505,7 +1550,6 @@ class PHPExcel_Calculation_Financial { return $returnValue; } // function NPV() - /** * PMT * diff --git a/htdocs/includes/phpexcel/PHPExcel/Calculation/FormulaParser.php b/htdocs/includes/phpexcel/PHPExcel/Calculation/FormulaParser.php index 7318a5b74b4..754a638d4ca 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Calculation/FormulaParser.php +++ b/htdocs/includes/phpexcel/PHPExcel/Calculation/FormulaParser.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -54,7 +54,7 @@ PARTLY BASED ON: * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_FormulaParser { /* Character constants */ @@ -93,13 +93,13 @@ class PHPExcel_Calculation_FormulaParser { * Create a new PHPExcel_Calculation_FormulaParser * * @param string $pFormula Formula to parse - * @throws Exception + * @throws PHPExcel_Calculation_Exception */ public function __construct($pFormula = '') { // Check parameters if (is_null($pFormula)) { - throw new Exception("Invalid parameter passed: formula"); + throw new PHPExcel_Calculation_Exception("Invalid parameter passed: formula"); } // Initialise values @@ -122,13 +122,13 @@ class PHPExcel_Calculation_FormulaParser { * * @param int $pId Token id * @return string - * @throws Exception + * @throws PHPExcel_Calculation_Exception */ public function getToken($pId = 0) { if (isset($this->_tokens[$pId])) { return $this->_tokens[$pId]; } else { - throw new Exception("Token with id $pId does not exist."); + throw new PHPExcel_Calculation_Exception("Token with id $pId does not exist."); } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Calculation/FormulaToken.php b/htdocs/includes/phpexcel/PHPExcel/Calculation/FormulaToken.php index b8a2571aebf..fd5e2e530fd 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Calculation/FormulaToken.php +++ b/htdocs/includes/phpexcel/PHPExcel/Calculation/FormulaToken.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -55,7 +55,7 @@ PARTLY BASED ON: * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_FormulaToken { /* Token types */ diff --git a/htdocs/includes/phpexcel/PHPExcel/Calculation/Function.php b/htdocs/includes/phpexcel/PHPExcel/Calculation/Function.php index 88f8c3b5471..7299834eb69 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Calculation/Function.php +++ b/htdocs/includes/phpexcel/PHPExcel/Calculation/Function.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_Function { /* Function categories */ @@ -74,7 +74,7 @@ class PHPExcel_Calculation_Function { * @param string $pCategory Category (represented by CATEGORY_*) * @param string $pExcelName Excel function name * @param string $pPHPExcelName PHPExcel function mapping - * @throws Exception + * @throws PHPExcel_Calculation_Exception */ public function __construct($pCategory = NULL, $pExcelName = NULL, $pPHPExcelName = NULL) { @@ -84,7 +84,7 @@ class PHPExcel_Calculation_Function { $this->_excelName = $pExcelName; $this->_phpExcelName = $pPHPExcelName; } else { - throw new Exception("Invalid parameters passed."); + throw new PHPExcel_Calculation_Exception("Invalid parameters passed."); } } @@ -101,13 +101,13 @@ class PHPExcel_Calculation_Function { * Set Category (represented by CATEGORY_*) * * @param string $value - * @throws Exception + * @throws PHPExcel_Calculation_Exception */ public function setCategory($value = null) { if (!is_null($value)) { $this->_category = $value; } else { - throw new Exception("Invalid parameter passed."); + throw new PHPExcel_Calculation_Exception("Invalid parameter passed."); } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Calculation/Functions.php b/htdocs/includes/phpexcel/PHPExcel/Calculation/Functions.php index e0a5629559d..71bfa19b6a1 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Calculation/Functions.php +++ b/htdocs/includes/phpexcel/PHPExcel/Calculation/Functions.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -54,7 +54,7 @@ define('PRECISION', 8.88E-016); * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_Functions { @@ -270,7 +270,7 @@ class PHPExcel_Calculation_Functions { * * @access public * @category Error Returns - * @return string #REF! + * @return string #NULL! */ public static function NULL() { return self::$_errorCodes['null']; @@ -308,13 +308,20 @@ class PHPExcel_Calculation_Functions { public static function _ifCondition($condition) { $condition = PHPExcel_Calculation_Functions::flattenSingleValue($condition); + if (!isset($condition{0})) + $condition = '=""'; if (!in_array($condition{0},array('>', '<', '='))) { if (!is_numeric($condition)) { $condition = PHPExcel_Calculation::_wrapResult(strtoupper($condition)); } return '='.$condition; } else { preg_match('/([<>=]+)(.*)/',$condition,$matches); list(,$operator,$operand) = $matches; - if (!is_numeric($operand)) { $operand = PHPExcel_Calculation::_wrapResult(strtoupper($operand)); } + + if (!is_numeric($operand)) { + $operand = str_replace('"', '""', $operand); + $operand = PHPExcel_Calculation::_wrapResult(strtoupper($operand)); + } + return $operator.$operand; } } // function _ifCondition() @@ -489,7 +496,7 @@ class PHPExcel_Calculation_Functions { * @return string Version information */ public static function VERSION() { - return 'PHPExcel 1.7.8, 2012-10-12'; + return 'PHPExcel 1.8.0, 2014-03-02'; } // function VERSION() @@ -687,100 +694,6 @@ if (!function_exists('atanh')) { } // function atanh() } -if (!function_exists('money_format')) { - function money_format($format, $number) { - $regex = array( '/%((?:[\^!\-]|\+|\(|\=.)*)([0-9]+)?(?:#([0-9]+))?', - '(?:\.([0-9]+))?([in%])/' - ); - $regex = implode('', $regex); - if (setlocale(LC_MONETARY, null) == '') { - setlocale(LC_MONETARY, ''); - } - $locale = localeconv(); - $number = floatval($number); - if (!preg_match($regex, $format, $fmatch)) { - trigger_error("No format specified or invalid format", E_USER_WARNING); - return $number; - } - $flags = array( 'fillchar' => preg_match('/\=(.)/', $fmatch[1], $match) ? $match[1] : ' ', - 'nogroup' => preg_match('/\^/', $fmatch[1]) > 0, - 'usesignal' => preg_match('/\+|\(/', $fmatch[1], $match) ? $match[0] : '+', - 'nosimbol' => preg_match('/\!/', $fmatch[1]) > 0, - 'isleft' => preg_match('/\-/', $fmatch[1]) > 0 - ); - $width = trim($fmatch[2]) ? (int)$fmatch[2] : 0; - $left = trim($fmatch[3]) ? (int)$fmatch[3] : 0; - $right = trim($fmatch[4]) ? (int)$fmatch[4] : $locale['int_frac_digits']; - $conversion = $fmatch[5]; - $positive = true; - if ($number < 0) { - $positive = false; - $number *= -1; - } - $letter = $positive ? 'p' : 'n'; - $prefix = $suffix = $cprefix = $csuffix = $signal = ''; - if (!$positive) { - $signal = $locale['negative_sign']; - switch (true) { - case $locale['n_sign_posn'] == 0 || $flags['usesignal'] == '(': - $prefix = '('; - $suffix = ')'; - break; - case $locale['n_sign_posn'] == 1: - $prefix = $signal; - break; - case $locale['n_sign_posn'] == 2: - $suffix = $signal; - break; - case $locale['n_sign_posn'] == 3: - $cprefix = $signal; - break; - case $locale['n_sign_posn'] == 4: - $csuffix = $signal; - break; - } - } - if (!$flags['nosimbol']) { - $currency = $cprefix; - $currency .= ($conversion == 'i' ? $locale['int_curr_symbol'] : $locale['currency_symbol']); - $currency .= $csuffix; - $currency = iconv('ISO-8859-1','UTF-8',$currency); - } else { - $currency = ''; - } - $space = $locale["{$letter}_sep_by_space"] ? ' ' : ''; - - if (!isset($locale['mon_decimal_point']) || empty($locale['mon_decimal_point'])) { - $locale['mon_decimal_point'] = (!isset($locale['decimal_point']) || empty($locale['decimal_point'])) ? - $locale['decimal_point'] : - '.'; - } - - $number = number_format($number, $right, $locale['mon_decimal_point'], $flags['nogroup'] ? '' : $locale['mon_thousands_sep'] ); - $number = explode($locale['mon_decimal_point'], $number); - - $n = strlen($prefix) + strlen($currency); - if ($left > 0 && $left > $n) { - if ($flags['isleft']) { - $number[0] .= str_repeat($flags['fillchar'], $left - $n); - } else { - $number[0] = str_repeat($flags['fillchar'], $left - $n) . $number[0]; - } - } - $number = implode($locale['mon_decimal_point'], $number); - if ($locale["{$letter}_cs_precedes"]) { - $number = $prefix . $currency . $space . $number . $suffix; - } else { - $number = $prefix . $number . $space . $currency . $suffix; - } - if ($width > 0) { - $number = str_pad($number, $width, $flags['fillchar'], $flags['isleft'] ? STR_PAD_RIGHT : STR_PAD_LEFT); - } - $format = str_replace($fmatch[0], $number, $format); - return $format; - } // function money_format() -} - // // Strangely, PHP doesn't have a mb_str_replace multibyte function diff --git a/htdocs/includes/phpexcel/PHPExcel/Calculation/Logical.php b/htdocs/includes/phpexcel/PHPExcel/Calculation/Logical.php index 80f2a2650d9..bb206a14257 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Calculation/Logical.php +++ b/htdocs/includes/phpexcel/PHPExcel/Calculation/Logical.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -41,7 +41,7 @@ if (!defined('PHPEXCEL_ROOT')) { * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_Logical { diff --git a/htdocs/includes/phpexcel/PHPExcel/Calculation/LookupRef.php b/htdocs/includes/phpexcel/PHPExcel/Calculation/LookupRef.php index c8246903f2e..e1285d90409 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Calculation/LookupRef.php +++ b/htdocs/includes/phpexcel/PHPExcel/Calculation/LookupRef.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -41,7 +41,7 @@ if (!defined('PHPEXCEL_ROOT')) { * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_LookupRef { @@ -251,8 +251,9 @@ class PHPExcel_Calculation_LookupRef { * * @access public * @category Logical Functions - * @param string $linkURL Value to check, is also the value returned when no error - * @param string $displayName Value to return when testValue is an error condition + * @param string $linkURL Value to check, is also the value returned when no error + * @param string $displayName Value to return when testValue is an error condition + * @param PHPExcel_Cell $pCell The cell to set the hyperlink in * @return mixed The value of $displayName (or $linkURL if $displayName was blank) */ public static function HYPERLINK($linkURL = '', $displayName = null, PHPExcel_Cell $pCell = null) { @@ -287,13 +288,14 @@ class PHPExcel_Calculation_LookupRef { * * NOTE - INDIRECT() does not yet support the optional a1 parameter introduced in Excel 2010 * - * @param cellAddress An array or array formula, or a reference to a range of cells for which you want the number of rows + * @param cellAddress $cellAddress The cell address of the current cell (containing this formula) + * @param PHPExcel_Cell $pCell The current cell (containing this formula) * @return mixed The cells referenced by cellAddress * * @todo Support for the optional a1 parameter introduced in Excel 2010 * */ - public static function INDIRECT($cellAddress=Null, PHPExcel_Cell $pCell = null) { + public static function INDIRECT($cellAddress = NULL, PHPExcel_Cell $pCell = NULL) { $cellAddress = PHPExcel_Calculation_Functions::flattenSingleValue($cellAddress); if (is_null($cellAddress) || $cellAddress === '') { return PHPExcel_Calculation_Functions::REF(); @@ -307,29 +309,30 @@ class PHPExcel_Calculation_LookupRef { if ((!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $cellAddress1, $matches)) || ((!is_null($cellAddress2)) && (!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $cellAddress2, $matches)))) { - if (!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_NAMEDRANGE.'$/i', $cellAddress1, $matches)) { return PHPExcel_Calculation_Functions::REF(); } - if (strpos($cellAddress,'!') !== false) { - list($sheetName,$cellAddress) = explode('!',$cellAddress); - $pSheet = $pCell->getParent()->getParent()->getSheetByName($sheetName); + if (strpos($cellAddress,'!') !== FALSE) { + list($sheetName, $cellAddress) = explode('!',$cellAddress); + $sheetName = trim($sheetName, "'"); + $pSheet = $pCell->getWorksheet()->getParent()->getSheetByName($sheetName); } else { - $pSheet = $pCell->getParent(); + $pSheet = $pCell->getWorksheet(); } - return PHPExcel_Calculation::getInstance()->extractNamedRange($cellAddress, $pSheet, False); + return PHPExcel_Calculation::getInstance()->extractNamedRange($cellAddress, $pSheet, FALSE); } - if (strpos($cellAddress,'!') !== false) { + if (strpos($cellAddress,'!') !== FALSE) { list($sheetName,$cellAddress) = explode('!',$cellAddress); - $pSheet = $pCell->getParent()->getParent()->getSheetByName($sheetName); + $sheetName = trim($sheetName, "'"); + $pSheet = $pCell->getWorksheet()->getParent()->getSheetByName($sheetName); } else { - $pSheet = $pCell->getParent(); + $pSheet = $pCell->getWorksheet(); } - return PHPExcel_Calculation::getInstance()->extractCellRange($cellAddress, $pSheet, False); + return PHPExcel_Calculation::getInstance()->extractCellRange($cellAddress, $pSheet, FALSE); } // function INDIRECT() @@ -373,9 +376,10 @@ class PHPExcel_Calculation_LookupRef { return PHPExcel_Calculation_Functions::REF(); } - $sheetName = null; + $sheetName = NULL; if (strpos($cellAddress,"!")) { list($sheetName,$cellAddress) = explode("!",$cellAddress); + $sheetName = trim($sheetName, "'"); } if (strpos($cellAddress,":")) { list($startCell,$endCell) = explode(":",$cellAddress); @@ -416,10 +420,10 @@ class PHPExcel_Calculation_LookupRef { $cellAddress .= ':'.$endCellColumn.$endCellRow; } - if ($sheetName !== null) { - $pSheet = $pCell->getParent()->getParent()->getSheetByName($sheetName); + if ($sheetName !== NULL) { + $pSheet = $pCell->getWorksheet()->getParent()->getSheetByName($sheetName); } else { - $pSheet = $pCell->getParent(); + $pSheet = $pCell->getWorksheet(); } return PHPExcel_Calculation::getInstance()->extractCellRange($cellAddress, $pSheet, False); @@ -458,7 +462,7 @@ class PHPExcel_Calculation_LookupRef { return PHPExcel_Calculation_Functions::VALUE(); } $chosenEntry = floor($chosenEntry); - if (($chosenEntry <= 0) || ($chosenEntry > $entryCount)) { + if (($chosenEntry < 0) || ($chosenEntry > $entryCount)) { return PHPExcel_Calculation_Functions::VALUE(); } @@ -717,7 +721,8 @@ class PHPExcel_Calculation_LookupRef { $rowNumber = $rowValue = False; foreach($lookup_array as $rowKey => $rowData) { - if (strtolower($rowData[$firstColumn]) > strtolower($lookup_value)) { + if ((is_numeric($lookup_value) && is_numeric($rowData[$firstColumn]) && ($rowData[$firstColumn] > $lookup_value)) || + (!is_numeric($lookup_value) && !is_numeric($rowData[$firstColumn]) && (strtolower($rowData[$firstColumn]) > strtolower($lookup_value)))) { break; } $rowNumber = $rowKey; @@ -730,7 +735,11 @@ class PHPExcel_Calculation_LookupRef { return PHPExcel_Calculation_Functions::NA(); } else { // otherwise return the appropriate value - return $lookup_array[$rowNumber][$returnColumn]; + $result = $lookup_array[$rowNumber][$returnColumn]; + if ((is_numeric($lookup_value) && is_numeric($result)) || + (!is_numeric($lookup_value) && !is_numeric($result))) { + return $result; + } } } @@ -738,6 +747,70 @@ class PHPExcel_Calculation_LookupRef { } // function VLOOKUP() +/** + * HLOOKUP + * The HLOOKUP function searches for value in the top-most row of lookup_array and returns the value in the same column based on the index_number. + * @param lookup_value The value that you want to match in lookup_array + * @param lookup_array The range of cells being searched + * @param index_number The row number in table_array from which the matching value must be returned. The first row is 1. + * @param not_exact_match Determines if you are looking for an exact match based on lookup_value. + * @return mixed The value of the found cell + */ + public static function HLOOKUP($lookup_value, $lookup_array, $index_number, $not_exact_match=true) { + $lookup_value = PHPExcel_Calculation_Functions::flattenSingleValue($lookup_value); + $index_number = PHPExcel_Calculation_Functions::flattenSingleValue($index_number); + $not_exact_match = PHPExcel_Calculation_Functions::flattenSingleValue($not_exact_match); + + // index_number must be greater than or equal to 1 + if ($index_number < 1) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + // index_number must be less than or equal to the number of columns in lookup_array + if ((!is_array($lookup_array)) || (empty($lookup_array))) { + return PHPExcel_Calculation_Functions::REF(); + } else { + $f = array_keys($lookup_array); + $firstRow = array_pop($f); + if ((!is_array($lookup_array[$firstRow])) || ($index_number > count($lookup_array[$firstRow]))) { + return PHPExcel_Calculation_Functions::REF(); + } else { + $columnKeys = array_keys($lookup_array[$firstRow]); + $firstkey = $f[0] - 1; + $returnColumn = $firstkey + $index_number; + $firstColumn = array_shift($f); + } + } + + if (!$not_exact_match) { + $firstRowH = asort($lookup_array[$firstColumn]); + } + + $rowNumber = $rowValue = False; + foreach($lookup_array[$firstColumn] as $rowKey => $rowData) { + if ((is_numeric($lookup_value) && is_numeric($rowData) && ($rowData > $lookup_value)) || + (!is_numeric($lookup_value) && !is_numeric($rowData) && (strtolower($rowData) > strtolower($lookup_value)))) { + break; + } + $rowNumber = $rowKey; + $rowValue = $rowData; + } + + if ($rowNumber !== false) { + if ((!$not_exact_match) && ($rowValue != $lookup_value)) { + // if an exact match is required, we have what we need to return an appropriate response + return PHPExcel_Calculation_Functions::NA(); + } else { + // otherwise return the appropriate value + $result = $lookup_array[$returnColumn][$rowNumber]; + return $result; + } + } + + return PHPExcel_Calculation_Functions::NA(); + } // function HLOOKUP() + + /** * LOOKUP * The LOOKUP function searches for value either from a one-row or one-column range or from an array. diff --git a/htdocs/includes/phpexcel/PHPExcel/Calculation/MathTrig.php b/htdocs/includes/phpexcel/PHPExcel/Calculation/MathTrig.php index 79c573b2774..10930552b35 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Calculation/MathTrig.php +++ b/htdocs/includes/phpexcel/PHPExcel/Calculation/MathTrig.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -41,7 +41,7 @@ if (!defined('PHPEXCEL_ROOT')) { * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_MathTrig { @@ -79,7 +79,7 @@ class PHPExcel_Calculation_MathTrig { * ATAN2 * * This function calculates the arc tangent of the two variables x and y. It is similar to - * calculating the arc tangent of y x, except that the signs of both arguments are used + * calculating the arc tangent of y ÷ x, except that the signs of both arguments are used * to determine the quadrant of the result. * The arctangent is the angle from the x-axis to a line containing the origin (0, 0) and a * point with coordinates (xCoordinate, yCoordinate). The angle is given in radians between @@ -495,13 +495,13 @@ class PHPExcel_Calculation_MathTrig { * * @access public * @category Mathematical and Trigonometric Functions - * @param float $value The positive real number for which you want the logarithm + * @param float $number The positive real number for which you want the logarithm * @param float $base The base of the logarithm. If base is omitted, it is assumed to be 10. * @return float */ public static function LOG_BASE($number = NULL, $base = 10) { $number = PHPExcel_Calculation_Functions::flattenSingleValue($number); - $base = (is_null($base)) ? 10 : (float) PHPExcel_Calculation_Functions::flattenSingleValue($base); + $base = (is_null($base)) ? 10 : (float) PHPExcel_Calculation_Functions::flattenSingleValue($base); if ((!is_numeric($base)) || (!is_numeric($number))) return PHPExcel_Calculation_Functions::VALUE(); @@ -547,7 +547,7 @@ class PHPExcel_Calculation_MathTrig { try { $matrix = new PHPExcel_Shared_JAMA_Matrix($matrixData); return $matrix->det(); - } catch (Exception $ex) { + } catch (PHPExcel_Exception $ex) { return PHPExcel_Calculation_Functions::VALUE(); } } // function MDETERM() @@ -589,7 +589,7 @@ class PHPExcel_Calculation_MathTrig { try { $matrix = new PHPExcel_Shared_JAMA_Matrix($matrixData); return $matrix->inverse()->getArray(); - } catch (Exception $ex) { + } catch (PHPExcel_Exception $ex) { return PHPExcel_Calculation_Functions::VALUE(); } } // function MINVERSE() @@ -642,7 +642,7 @@ class PHPExcel_Calculation_MathTrig { } return $matrixA->times($matrixB)->getArray(); - } catch (Exception $ex) { + } catch (PHPExcel_Exception $ex) { return PHPExcel_Calculation_Functions::VALUE(); } } // function MMULT() @@ -1164,7 +1164,11 @@ class PHPExcel_Calculation_MathTrig { $condition = PHPExcel_Calculation_Functions::_ifCondition($condition); // Loop through arguments foreach ($aArgs as $key => $arg) { - if (!is_numeric($arg)) { $arg = PHPExcel_Calculation::_wrapResult(strtoupper($arg)); } + if (!is_numeric($arg)) { + $arg = str_replace('"', '""', $arg); + $arg = PHPExcel_Calculation::_wrapResult(strtoupper($arg)); + } + $testCondition = '='.$arg.$condition; if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) { // Is it a value within our criteria @@ -1252,7 +1256,8 @@ class PHPExcel_Calculation_MathTrig { /** * SUMX2MY2 * - * @param mixed $value Value to check + * @param mixed[] $matrixData1 Matrix #1 + * @param mixed[] $matrixData2 Matrix #2 * @return float */ public static function SUMX2MY2($matrixData1,$matrixData2) { @@ -1281,7 +1286,8 @@ class PHPExcel_Calculation_MathTrig { /** * SUMX2PY2 * - * @param mixed $value Value to check + * @param mixed[] $matrixData1 Matrix #1 + * @param mixed[] $matrixData2 Matrix #2 * @return float */ public static function SUMX2PY2($matrixData1,$matrixData2) { @@ -1310,7 +1316,8 @@ class PHPExcel_Calculation_MathTrig { /** * SUMXMY2 * - * @param mixed $value Value to check + * @param mixed[] $matrixData1 Matrix #1 + * @param mixed[] $matrixData2 Matrix #2 * @return float */ public static function SUMXMY2($matrixData1,$matrixData2) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Calculation/Statistical.php b/htdocs/includes/phpexcel/PHPExcel/Calculation/Statistical.php index 2fbb163ef7b..32b9c781d9c 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Calculation/Statistical.php +++ b/htdocs/includes/phpexcel/PHPExcel/Calculation/Statistical.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -57,7 +57,7 @@ define('SQRT2PI', 2.5066282746310005024157652848110452530069867406099); * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_Statistical { @@ -834,6 +834,7 @@ class PHPExcel_Calculation_Statistical { * @category Mathematical and Trigonometric Functions * @param mixed $arg,... Data values * @param string $condition The criteria that defines which cells will be checked. + * @param mixed[] $averageArgs Data values * @return float */ public static function AVERAGEIF($aArgs,$condition,$averageArgs = array()) { @@ -912,6 +913,8 @@ class PHPExcel_Calculation_Statistical { * @param float $probability Probability at which you want to evaluate the distribution * @param float $alpha Parameter to the distribution * @param float $beta Parameter to the distribution + * @param float $rMin Minimum value + * @param float $rMax Maximum value * @param boolean $cumulative * @return float * @@ -1954,9 +1957,9 @@ class PHPExcel_Calculation_Statistical { * @param boolean A logical value specifying whether to return additional regression statistics. * @return array */ - public static function LINEST($yValues,$xValues=null,$const=True,$stats=False) { - $const = (is_null($const)) ? True : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($const); - $stats = (is_null($stats)) ? False : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($stats); + public static function LINEST($yValues, $xValues = NULL, $const = TRUE, $stats = FALSE) { + $const = (is_null($const)) ? TRUE : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($const); + $stats = (is_null($stats)) ? FALSE : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($stats); if (is_null($xValues)) $xValues = range(1,count(PHPExcel_Calculation_Functions::flattenArray($yValues))); if (!self::_checkTrendArrays($yValues,$xValues)) { @@ -2059,7 +2062,9 @@ class PHPExcel_Calculation_Statistical { * * Returns the inverse of the normal cumulative distribution * - * @param float $value + * @param float $probability + * @param float $mean + * @param float $stdDev * @return float * * @todo Try implementing P J Acklam's refinement algorithm for greater @@ -2088,6 +2093,8 @@ class PHPExcel_Calculation_Statistical { * with parameters mean and standard_dev. * * @param float $value + * @param float $mean + * @param float $stdDev * @return float */ public static function LOGNORMDIST($value, $mean, $stdDev) { @@ -3621,14 +3628,14 @@ class PHPExcel_Calculation_Statistical { * Returns the Weibull distribution. Use this distribution in reliability * analysis, such as calculating a device's mean time to failure. * - * @param float $value - * @param float $alpha Alpha Parameter - * @param float $beta Beta Parameter + * @param float $dataSet + * @param float $m0 Alpha Parameter + * @param float $sigma Beta Parameter * @param boolean $cumulative * @return float * */ - public static function ZTEST($dataSet, $m0, $sigma=null) { + public static function ZTEST($dataSet, $m0, $sigma = NULL) { $dataSet = PHPExcel_Calculation_Functions::flattenArrayIndexed($dataSet); $m0 = PHPExcel_Calculation_Functions::flattenSingleValue($m0); $sigma = PHPExcel_Calculation_Functions::flattenSingleValue($sigma); diff --git a/htdocs/includes/phpexcel/PHPExcel/Calculation/TextData.php b/htdocs/includes/phpexcel/PHPExcel/Calculation/TextData.php index 3289645f519..d1ba2728e0f 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Calculation/TextData.php +++ b/htdocs/includes/phpexcel/PHPExcel/Calculation/TextData.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -41,7 +41,7 @@ if (!defined('PHPEXCEL_ROOT')) { * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Calculation_TextData { @@ -89,7 +89,7 @@ class PHPExcel_Calculation_TextData { /** * TRIMNONPRINTABLE * - * @param mixed $value Value to check + * @param mixed $stringValue Value to check * @return string */ public static function TRIMNONPRINTABLE($stringValue = '') { @@ -113,7 +113,7 @@ class PHPExcel_Calculation_TextData { /** * TRIMSPACES * - * @param mixed $value Value to check + * @param mixed $stringValue Value to check * @return string */ public static function TRIMSPACES($stringValue = '') { @@ -133,7 +133,7 @@ class PHPExcel_Calculation_TextData { /** * ASCIICODE * - * @param string $character Value + * @param string $characters Value * @return int */ public static function ASCIICODE($characters) { @@ -208,16 +208,17 @@ class PHPExcel_Calculation_TextData { } $decimals = floor($decimals); + $mask = '$#,##0'; if ($decimals > 0) { - return money_format('%.'.$decimals.'n',$value); + $mask .= '.' . str_repeat('0',$decimals); } else { $round = pow(10,abs($decimals)); if ($value < 0) { $round = 0-$round; } - $value = PHPExcel_Calculation_MathTrig::MROUND($value,$round); - // The implementation of money_format used if the standard PHP function is not available can't handle decimal places of 0, - // so we display to 1 dp and chop off that character and the decimal separator using substr - return substr(money_format('%.1n',$value),0,-2); + $value = PHPExcel_Calculation_MathTrig::MROUND($value, $round); } + + return PHPExcel_Style_NumberFormat::toFormattedString($value, $mask); + } // function DOLLAR() @@ -296,7 +297,9 @@ class PHPExcel_Calculation_TextData { /** * FIXEDFORMAT * - * @param mixed $value Value to check + * @param mixed $value Value to check + * @param integer $decimals + * @param boolean $no_commas * @return boolean */ public static function FIXEDFORMAT($value, $decimals = 2, $no_commas = FALSE) { @@ -407,7 +410,6 @@ class PHPExcel_Calculation_TextData { * STRINGLENGTH * * @param string $value Value - * @param int $chars Number of characters * @return string */ public static function STRINGLENGTH($value = '') { @@ -440,11 +442,7 @@ class PHPExcel_Calculation_TextData { $mixedCaseString = ($mixedCaseString) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); } - if (function_exists('mb_convert_case')) { - return mb_convert_case($mixedCaseString, MB_CASE_LOWER, 'UTF-8'); - } else { - return strtoupper($mixedCaseString); - } + return PHPExcel_Shared_String::StrToLower($mixedCaseString); } // function LOWERCASE() @@ -463,11 +461,7 @@ class PHPExcel_Calculation_TextData { $mixedCaseString = ($mixedCaseString) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); } - if (function_exists('mb_convert_case')) { - return mb_convert_case($mixedCaseString, MB_CASE_UPPER, 'UTF-8'); - } else { - return strtoupper($mixedCaseString); - } + return PHPExcel_Shared_String::StrToUpper($mixedCaseString); } // function UPPERCASE() @@ -486,20 +480,17 @@ class PHPExcel_Calculation_TextData { $mixedCaseString = ($mixedCaseString) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); } - if (function_exists('mb_convert_case')) { - return mb_convert_case($mixedCaseString, MB_CASE_TITLE, 'UTF-8'); - } else { - return ucwords($mixedCaseString); - } + return PHPExcel_Shared_String::StrToTitle($mixedCaseString); } // function PROPERCASE() /** * REPLACE * - * @param string $value Value - * @param int $start Start character - * @param int $chars Number of characters + * @param string $oldText String to modify + * @param int $start Start character + * @param int $chars Number of characters + * @param string $newText String to replace in defined position * @return string */ public static function REPLACE($oldText = '', $start = 1, $chars = null, $newText) { @@ -565,7 +556,7 @@ class PHPExcel_Calculation_TextData { /** * RETURNSTRING * - * @param mixed $value Value to check + * @param mixed $testValue Value to check * @return boolean */ public static function RETURNSTRING($testValue = '') { @@ -582,6 +573,7 @@ class PHPExcel_Calculation_TextData { * TEXTFORMAT * * @param mixed $value Value to check + * @param string $format Format mask to use * @return boolean */ public static function TEXTFORMAT($value,$format) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Calculation/Token/Stack.php b/htdocs/includes/phpexcel/PHPExcel/Calculation/Token/Stack.php index ea7efa0c923..821f3bd280e 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Calculation/Token/Stack.php +++ b/htdocs/includes/phpexcel/PHPExcel/Calculation/Token/Stack.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,24 +20,53 @@ * * @category PHPExcel * @package PHPExcel_Calculation - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ +/** + * PHPExcel_Calculation_Token_Stack + * + * @category PHPExcel_Calculation_Token_Stack + * @package PHPExcel_Calculation + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) + */ class PHPExcel_Calculation_Token_Stack { + /** + * The parser stack for formulae + * + * @var mixed[] + */ private $_stack = array(); + + /** + * Count of entries in the parser stack + * + * @var integer + */ private $_count = 0; + /** + * Return the number of entries on the stack + * + * @return integer + */ public function count() { return $this->_count; } // function count() - - public function push($type,$value,$reference=null) { + /** + * Push a new entry onto the stack + * + * @param mixed $type + * @param mixed $value + * @param mixed $reference + */ + public function push($type, $value, $reference = NULL) { $this->_stack[$this->_count++] = array('type' => $type, 'value' => $value, 'reference' => $reference @@ -50,24 +79,37 @@ class PHPExcel_Calculation_Token_Stack { } } // function push() - + /** + * Pop the last entry from the stack + * + * @return mixed + */ public function pop() { if ($this->_count > 0) { return $this->_stack[--$this->_count]; } - return null; + return NULL; } // function pop() - - public function last($n=1) { - if ($this->_count-$n < 0) { - return null; + /** + * Return an entry from the stack without removing it + * + * @param integer $n number indicating how far back in the stack we want to look + * @return mixed + */ + public function last($n = 1) { + if ($this->_count - $n < 0) { + return NULL; } - return $this->_stack[$this->_count-$n]; + return $this->_stack[$this->_count - $n]; } // function last() - - function __construct() { + /** + * Clear the stack + */ + function clear() { + $this->_stack = array(); + $this->_count = 0; } } // class PHPExcel_Calculation_Token_Stack diff --git a/htdocs/includes/phpexcel/PHPExcel/Cell.php b/htdocs/includes/phpexcel/PHPExcel/Cell.php index 75996f2942f..1788559fd30 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Cell.php +++ b/htdocs/includes/phpexcel/PHPExcel/Cell.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Cell { @@ -50,20 +50,6 @@ class PHPExcel_Cell */ private static $_valueBinder = NULL; - /** - * Column of the cell - * - * @var string - */ - private $_column; - - /** - * Row of the cell - * - * @var int - */ - private $_row; - /** * Value of the cell * @@ -93,7 +79,7 @@ class PHPExcel_Cell /** * Parent worksheet * - * @var PHPExcel_Worksheet + * @var PHPExcel_CachedObjectStorage_CacheBase */ private $_parent; @@ -117,7 +103,8 @@ class PHPExcel_Cell * @return void **/ public function notifyCacheController() { - $this->_parent->getCellCacheController()->updateCacheData($this); + $this->_parent->updateCacheData($this); + return $this; } @@ -125,7 +112,9 @@ class PHPExcel_Cell $this->_parent = NULL; } - public function attach($parent) { + public function attach(PHPExcel_CachedObjectStorage_CacheBase $parent) { + + $this->_parent = $parent; } @@ -133,24 +122,18 @@ class PHPExcel_Cell /** * Create a new Cell * - * @param string $pColumn - * @param int $pRow * @param mixed $pValue * @param string $pDataType * @param PHPExcel_Worksheet $pSheet * @throws PHPExcel_Exception */ - public function __construct($pColumn = 'A', $pRow = 1, $pValue = NULL, $pDataType = NULL, PHPExcel_Worksheet $pSheet = NULL) + public function __construct($pValue = NULL, $pDataType = NULL, PHPExcel_Worksheet $pSheet = NULL) { - // Initialise cell coordinate - $this->_column = strtoupper($pColumn); - $this->_row = $pRow; - // Initialise cell value $this->_value = $pValue; - // Set worksheet - $this->_parent = $pSheet; + // Set worksheet cache + $this->_parent = $pSheet->getCellCacheController(); // Set datatype? if ($pDataType !== NULL) { @@ -174,7 +157,7 @@ class PHPExcel_Cell */ public function getColumn() { - return $this->_column; + return $this->_parent->getCurrentColumn(); } /** @@ -184,7 +167,7 @@ class PHPExcel_Cell */ public function getRow() { - return $this->_row; + return $this->_parent->getCurrentRow(); } /** @@ -194,7 +177,7 @@ class PHPExcel_Cell */ public function getCoordinate() { - return $this->_column . $this->_row; + return $this->_parent->getCurrentAddress(); } /** @@ -216,7 +199,7 @@ class PHPExcel_Cell { return (string) PHPExcel_Style_NumberFormat::toFormattedString( $this->getCalculatedValue(), - $this->_parent->getParent()->getCellXfByIndex($this->getXfIndex()) + $this->getWorksheet()->getParent()->getCellXfByIndex($this->getXfIndex()) ->getNumberFormat()->getFormatCode() ); } @@ -250,10 +233,12 @@ class PHPExcel_Cell { // set the value according to data type switch ($pDataType) { + case PHPExcel_Cell_DataType::TYPE_NULL: + $this->_value = $pValue; + break; case PHPExcel_Cell_DataType::TYPE_STRING2: $pDataType = PHPExcel_Cell_DataType::TYPE_STRING; case PHPExcel_Cell_DataType::TYPE_STRING: - case PHPExcel_Cell_DataType::TYPE_NULL: case PHPExcel_Cell_DataType::TYPE_INLINE: $this->_value = PHPExcel_Cell_DataType::checkString($pValue); break; @@ -285,43 +270,48 @@ class PHPExcel_Cell * * @deprecated Since version 1.7.8 for planned changes to cell for array formula handling * + * @param boolean $resetLog Whether the calculation engine logger should be reset or not * @return mixed * @throws PHPExcel_Exception */ public function getCalculatedValue($resetLog = TRUE) { -// echo 'Cell '.$this->getCoordinate().' value is a '.$this->_dataType.' with a value of '.$this->getValue().'
'; +//echo 'Cell '.$this->getCoordinate().' value is a '.$this->_dataType.' with a value of '.$this->getValue().PHP_EOL; if ($this->_dataType == PHPExcel_Cell_DataType::TYPE_FORMULA) { try { -// echo 'Cell value for '.$this->getCoordinate().' is a formula: Calculating value
'; - $result = PHPExcel_Calculation::getInstance()->calculateCellValue($this,$resetLog); -// echo $this->getCoordinate().' calculation result is '.$result.'
'; - } catch ( Exception $ex ) { +//echo 'Cell value for '.$this->getCoordinate().' is a formula: Calculating value'.PHP_EOL; + $result = PHPExcel_Calculation::getInstance( + $this->getWorksheet()->getParent() + )->calculateCellValue($this,$resetLog); +//echo $this->getCoordinate().' calculation result is '.$result.PHP_EOL; + // We don't yet handle array returns + if (is_array($result)) { + while (is_array($result)) { + $result = array_pop($result); + } + } + } catch ( PHPExcel_Exception $ex ) { if (($ex->getMessage() === 'Unable to access External Workbook') && ($this->_calculatedValue !== NULL)) { -// echo 'Returning fallback value of '.$this->_calculatedValue.' for cell '.$this->getCoordinate().'
'; +//echo 'Returning fallback value of '.$this->_calculatedValue.' for cell '.$this->getCoordinate().PHP_EOL; return $this->_calculatedValue; // Fallback for calculations referencing external files. } -// echo 'Calculation Exception: '.$ex->getMessage().'
'; +//echo 'Calculation Exception: '.$ex->getMessage().PHP_EOL; $result = '#N/A'; - throw( - new PHPExcel_Exception( - $this->getParent()->getTitle().'!'.$this->getCoordinate().' -> '.$ex->getMessage() - ) + throw new PHPExcel_Calculation_Exception( + $this->getWorksheet()->getTitle().'!'.$this->getCoordinate().' -> '.$ex->getMessage() ); } if ($result === '#Not Yet Implemented') { -// echo 'Returning fallback value of '.$this->_calculatedValue.' for cell '.$this->getCoordinate().'
'; +//echo 'Returning fallback value of '.$this->_calculatedValue.' for cell '.$this->getCoordinate().PHP_EOL; return $this->_calculatedValue; // Fallback if calculation engine does not support the formula. } -// echo 'Returning calculated value of '.$result.' for cell '.$this->getCoordinate().'
'; +//echo 'Returning calculated value of '.$result.' for cell '.$this->getCoordinate().PHP_EOL; return $result; + } elseif($this->_value instanceof PHPExcel_RichText) { +// echo 'Cell value for '.$this->getCoordinate().' is rich text: Returning data value of '.$this->_value.'
'; + return $this->_value->getPlainText(); } - -// if ($this->_value === NULL) { -// echo 'Cell '.$this->getCoordinate().' has no value, formula or otherwise
'; -// return NULL; -// } // echo 'Cell value for '.$this->getCoordinate().' is not a formula: Returning data value of '.$this->_value.'
'; return $this->_value; } @@ -382,6 +372,16 @@ class PHPExcel_Cell return $this->notifyCacheController(); } + /** + * Identify if the cell contains a formula + * + * @return boolean + */ + public function isFormula() + { + return $this->_dataType == PHPExcel_Cell_DataType::TYPE_FORMULA; + } + /** * Does this cell contain Data validation rules? * @@ -394,7 +394,7 @@ class PHPExcel_Cell throw new PHPExcel_Exception('Cannot check for data validation when cell is not bound to a worksheet'); } - return $this->_parent->dataValidationExists($this->getCoordinate()); + return $this->getWorksheet()->dataValidationExists($this->getCoordinate()); } /** @@ -409,7 +409,7 @@ class PHPExcel_Cell throw new PHPExcel_Exception('Cannot get data validation for cell that is not bound to a worksheet'); } - return $this->_parent->getDataValidation($this->getCoordinate()); + return $this->getWorksheet()->getDataValidation($this->getCoordinate()); } /** @@ -425,7 +425,7 @@ class PHPExcel_Cell throw new PHPExcel_Exception('Cannot set data validation for cell that is not bound to a worksheet'); } - $this->_parent->setDataValidation($this->getCoordinate(), $pDataValidation); + $this->getWorksheet()->setDataValidation($this->getCoordinate(), $pDataValidation); return $this->notifyCacheController(); } @@ -442,7 +442,7 @@ class PHPExcel_Cell throw new PHPExcel_Exception('Cannot check for hyperlink when cell is not bound to a worksheet'); } - return $this->_parent->hyperlinkExists($this->getCoordinate()); + return $this->getWorksheet()->hyperlinkExists($this->getCoordinate()); } /** @@ -457,7 +457,7 @@ class PHPExcel_Cell throw new PHPExcel_Exception('Cannot get hyperlink for cell that is not bound to a worksheet'); } - return $this->_parent->getHyperlink($this->getCoordinate()); + return $this->getWorksheet()->getHyperlink($this->getCoordinate()); } /** @@ -473,7 +473,7 @@ class PHPExcel_Cell throw new PHPExcel_Exception('Cannot set hyperlink for cell that is not bound to a worksheet'); } - $this->_parent->setHyperlink($this->getCoordinate(), $pHyperlink); + $this->getWorksheet()->setHyperlink($this->getCoordinate(), $pHyperlink); return $this->notifyCacheController(); } @@ -481,12 +481,31 @@ class PHPExcel_Cell /** * Get parent worksheet * - * @return PHPExcel_Worksheet + * @return PHPExcel_CachedObjectStorage_CacheBase */ public function getParent() { return $this->_parent; } + /** + * Get parent worksheet + * + * @return PHPExcel_Worksheet + */ + public function getWorksheet() { + return $this->_parent->getParent(); + } + + /** + * Get cell style + * + * @return PHPExcel_Style + */ + public function getStyle() + { + return $this->getWorksheet()->getParent()->getCellXfByIndex($this->getXfIndex()); + } + /** * Re-bind parent * @@ -494,7 +513,7 @@ class PHPExcel_Cell * @return PHPExcel_Cell */ public function rebindParent(PHPExcel_Worksheet $parent) { - $this->_parent = $parent; + $this->_parent = $parent->getCellCacheController(); return $this->notifyCacheController(); } @@ -727,7 +746,6 @@ class PHPExcel_Cell * * @param string $pString * @return int Column index (base 1 !!!) - * @throws Exception */ public static function columnIndexFromString($pString = 'A') { @@ -825,8 +843,8 @@ class PHPExcel_Cell // Range... list($rangeStart, $rangeEnd) = $range; - list($startCol, $startRow) = sscanf($rangeStart,'%[A-Z]%d'); - list($endCol, $endRow) = sscanf($rangeEnd,'%[A-Z]%d'); + sscanf($rangeStart,'%[A-Z]%d', $startCol, $startRow); + sscanf($rangeEnd,'%[A-Z]%d', $endCol, $endRow); $endCol++; // Current data @@ -848,7 +866,7 @@ class PHPExcel_Cell // Sort the result by column and row $sortKeys = array(); foreach (array_unique($returnValue) as $coord) { - list($column,$row) = sscanf($coord,'%[A-Z]%d'); + sscanf($coord,'%[A-Z]%d', $column, $row); $sortKeys[sprintf('%3s%09d',$column,$row)] = $coord; } ksort($sortKeys); @@ -861,16 +879,16 @@ class PHPExcel_Cell * Compare 2 cells * * @param PHPExcel_Cell $a Cell a - * @param PHPExcel_Cell $a Cell b + * @param PHPExcel_Cell $b Cell b * @return int Result of comparison (always -1 or 1, never zero!) */ public static function compareCells(PHPExcel_Cell $a, PHPExcel_Cell $b) { - if ($a->_row < $b->_row) { + if ($a->getRow() < $b->getRow()) { return -1; - } elseif ($a->_row > $b->_row) { + } elseif ($a->getRow() > $b->getRow()) { return 1; - } elseif (self::columnIndexFromString($a->_column) < self::columnIndexFromString($b->_column)) { + } elseif (self::columnIndexFromString($a->getColumn()) < self::columnIndexFromString($b->getColumn())) { return -1; } else { return 1; @@ -894,11 +912,11 @@ class PHPExcel_Cell * Set value binder to use * * @param PHPExcel_Cell_IValueBinder $binder - * @throws Exception + * @throws PHPExcel_Exception */ public static function setValueBinder(PHPExcel_Cell_IValueBinder $binder = NULL) { if ($binder === NULL) { - throw new Exception("A PHPExcel_Cell_IValueBinder is required for PHPExcel to function correctly."); + throw new PHPExcel_Exception("A PHPExcel_Cell_IValueBinder is required for PHPExcel to function correctly."); } self::$_valueBinder = $binder; diff --git a/htdocs/includes/phpexcel/PHPExcel/Cell/AdvancedValueBinder.php b/htdocs/includes/phpexcel/PHPExcel/Cell/AdvancedValueBinder.php index 3603f5ee61d..00a2b57fa12 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Cell/AdvancedValueBinder.php +++ b/htdocs/includes/phpexcel/PHPExcel/Cell/AdvancedValueBinder.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,19 +20,19 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.8.0, 2014-03-02 */ /** PHPExcel root directory */ if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); - require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); } @@ -41,150 +41,152 @@ if (!defined('PHPEXCEL_ROOT')) { * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Cell_AdvancedValueBinder extends PHPExcel_Cell_DefaultValueBinder implements PHPExcel_Cell_IValueBinder { - /** - * Bind value to a cell - * - * @param PHPExcel_Cell $cell Cell to bind value to - * @param mixed $value Value to bind in cell - * @return boolean - */ - public function bindValue(PHPExcel_Cell $cell, $value = null) - { - // sanitize UTF-8 strings - if (is_string($value)) { - $value = PHPExcel_Shared_String::SanitizeUTF8($value); - } + /** + * Bind value to a cell + * + * @param PHPExcel_Cell $cell Cell to bind value to + * @param mixed $value Value to bind in cell + * @return boolean + */ + public function bindValue(PHPExcel_Cell $cell, $value = null) + { + // sanitize UTF-8 strings + if (is_string($value)) { + $value = PHPExcel_Shared_String::SanitizeUTF8($value); + } - // Find out data type - $dataType = parent::dataTypeForValue($value); + // Find out data type + $dataType = parent::dataTypeForValue($value); - // Style logic - strings - if ($dataType === PHPExcel_Cell_DataType::TYPE_STRING && !$value instanceof PHPExcel_RichText) { - // Test for booleans using locale-setting - if ($value == PHPExcel_Calculation::getTRUE()) { - $cell->setValueExplicit( TRUE, PHPExcel_Cell_DataType::TYPE_BOOL); - return true; - } elseif($value == PHPExcel_Calculation::getFALSE()) { - $cell->setValueExplicit( FALSE, PHPExcel_Cell_DataType::TYPE_BOOL); - return true; - } + // Style logic - strings + if ($dataType === PHPExcel_Cell_DataType::TYPE_STRING && !$value instanceof PHPExcel_RichText) { + // Test for booleans using locale-setting + if ($value == PHPExcel_Calculation::getTRUE()) { + $cell->setValueExplicit( TRUE, PHPExcel_Cell_DataType::TYPE_BOOL); + return true; + } elseif($value == PHPExcel_Calculation::getFALSE()) { + $cell->setValueExplicit( FALSE, PHPExcel_Cell_DataType::TYPE_BOOL); + return true; + } - // Check for number in scientific format - if (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_NUMBER.'$/', $value)) { - $cell->setValueExplicit( (float) $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); - return true; - } + // Check for number in scientific format + if (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_NUMBER.'$/', $value)) { + $cell->setValueExplicit( (float) $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); + return true; + } - // Check for fraction - if (preg_match('/^([+-]?) *([0-9]*)\s?\/\s*([0-9]*)$/', $value, $matches)) { - // Convert value to number - $value = $matches[2] / $matches[3]; - if ($matches[1] == '-') $value = 0 - $value; - $cell->setValueExplicit( (float) $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); - // Set style - $cell->getParent()->getStyle( $cell->getCoordinate() ) - ->getNumberFormat()->setFormatCode( '??/??' ); - return true; - } elseif (preg_match('/^([+-]?)([0-9]*) +([0-9]*)\s?\/\s*([0-9]*)$/', $value, $matches)) { - // Convert value to number - $value = $matches[2] + ($matches[3] / $matches[4]); - if ($matches[1] == '-') $value = 0 - $value; - $cell->setValueExplicit( (float) $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); - // Set style - $cell->getParent()->getStyle( $cell->getCoordinate() ) - ->getNumberFormat()->setFormatCode( '# ??/??' ); - return true; - } + // Check for fraction + if (preg_match('/^([+-]?)\s*([0-9]+)\s?\/\s*([0-9]+)$/', $value, $matches)) { + // Convert value to number + $value = $matches[2] / $matches[3]; + if ($matches[1] == '-') $value = 0 - $value; + $cell->setValueExplicit( (float) $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); + // Set style + $cell->getWorksheet()->getStyle( $cell->getCoordinate() ) + ->getNumberFormat()->setFormatCode( '??/??' ); + return true; + } elseif (preg_match('/^([+-]?)([0-9]*) +([0-9]*)\s?\/\s*([0-9]*)$/', $value, $matches)) { + // Convert value to number + $value = $matches[2] + ($matches[3] / $matches[4]); + if ($matches[1] == '-') $value = 0 - $value; + $cell->setValueExplicit( (float) $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); + // Set style + $cell->getWorksheet()->getStyle( $cell->getCoordinate() ) + ->getNumberFormat()->setFormatCode( '# ??/??' ); + return true; + } - // Check for percentage - if (preg_match('/^\-?[0-9]*\.?[0-9]*\s?\%$/', $value)) { - // Convert value to number - $value = (float) str_replace('%', '', $value) / 100; - $cell->setValueExplicit( $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); - // Set style - $cell->getParent()->getStyle( $cell->getCoordinate() ) - ->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE_00 ); - return true; - } + // Check for percentage + if (preg_match('/^\-?[0-9]*\.?[0-9]*\s?\%$/', $value)) { + // Convert value to number + $value = (float) str_replace('%', '', $value) / 100; + $cell->setValueExplicit( $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); + // Set style + $cell->getWorksheet()->getStyle( $cell->getCoordinate() ) + ->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE_00 ); + return true; + } - // Check for currency - $currencyCode = PHPExcel_Shared_String::getCurrencyCode(); - if (preg_match('/^'.preg_quote($currencyCode).' *(\d{1,3}(\,\d{3})*|(\d+))(\.\d{2})?$/', $value)) { - // Convert value to number - $value = (float) trim(str_replace(array($currencyCode,','), '', $value)); - $cell->setValueExplicit( $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); - // Set style - $cell->getParent()->getStyle( $cell->getCoordinate() ) - ->getNumberFormat()->setFormatCode( - str_replace('$', $currencyCode, PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_USD_SIMPLE ) - ); - return true; - } elseif (preg_match('/^\$ *(\d{1,3}(\,\d{3})*|(\d+))(\.\d{2})?$/', $value)) { - // Convert value to number - $value = (float) trim(str_replace(array('$',','), '', $value)); - $cell->setValueExplicit( $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); - // Set style - $cell->getParent()->getStyle( $cell->getCoordinate() ) - ->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_USD_SIMPLE ); - return true; - } + // Check for currency + $currencyCode = PHPExcel_Shared_String::getCurrencyCode(); + $decimalSeparator = PHPExcel_Shared_String::getDecimalSeparator(); + $thousandsSeparator = PHPExcel_Shared_String::getThousandsSeparator(); + if (preg_match('/^'.preg_quote($currencyCode).' *(\d{1,3}('.preg_quote($thousandsSeparator).'\d{3})*|(\d+))('.preg_quote($decimalSeparator).'\d{2})?$/', $value)) { + // Convert value to number + $value = (float) trim(str_replace(array($currencyCode, $thousandsSeparator, $decimalSeparator), array('', '', '.'), $value)); + $cell->setValueExplicit( $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); + // Set style + $cell->getWorksheet()->getStyle( $cell->getCoordinate() ) + ->getNumberFormat()->setFormatCode( + str_replace('$', $currencyCode, PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_USD_SIMPLE ) + ); + return true; + } elseif (preg_match('/^\$ *(\d{1,3}(\,\d{3})*|(\d+))(\.\d{2})?$/', $value)) { + // Convert value to number + $value = (float) trim(str_replace(array('$',','), '', $value)); + $cell->setValueExplicit( $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); + // Set style + $cell->getWorksheet()->getStyle( $cell->getCoordinate() ) + ->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_USD_SIMPLE ); + return true; + } - // Check for time without seconds e.g. '9:45', '09:45' - if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d$/', $value)) { - // Convert value to number - list($h, $m) = explode(':', $value); - $days = $h / 24 + $m / 1440; - $cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC); - // Set style - $cell->getParent()->getStyle( $cell->getCoordinate() ) - ->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME3 ); - return true; - } + // Check for time without seconds e.g. '9:45', '09:45' + if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d$/', $value)) { + // Convert value to number + list($h, $m) = explode(':', $value); + $days = $h / 24 + $m / 1440; + $cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC); + // Set style + $cell->getWorksheet()->getStyle( $cell->getCoordinate() ) + ->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME3 ); + return true; + } - // Check for time with seconds '9:45:59', '09:45:59' - if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d:[0-5]\d$/', $value)) { - // Convert value to number - list($h, $m, $s) = explode(':', $value); - $days = $h / 24 + $m / 1440 + $s / 86400; - // Convert value to number - $cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC); - // Set style - $cell->getParent()->getStyle( $cell->getCoordinate() ) - ->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4 ); - return true; - } + // Check for time with seconds '9:45:59', '09:45:59' + if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d:[0-5]\d$/', $value)) { + // Convert value to number + list($h, $m, $s) = explode(':', $value); + $days = $h / 24 + $m / 1440 + $s / 86400; + // Convert value to number + $cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC); + // Set style + $cell->getWorksheet()->getStyle( $cell->getCoordinate() ) + ->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4 ); + return true; + } - // Check for datetime, e.g. '2008-12-31', '2008-12-31 15:59', '2008-12-31 15:59:10' - if (($d = PHPExcel_Shared_Date::stringToExcel($value)) !== false) { - // Convert value to number - $cell->setValueExplicit($d, PHPExcel_Cell_DataType::TYPE_NUMERIC); - // Determine style. Either there is a time part or not. Look for ':' - if (strpos($value, ':') !== false) { - $formatCode = 'yyyy-mm-dd h:mm'; - } else { - $formatCode = 'yyyy-mm-dd'; - } - $cell->getParent()->getStyle( $cell->getCoordinate() ) - ->getNumberFormat()->setFormatCode($formatCode); - return true; - } + // Check for datetime, e.g. '2008-12-31', '2008-12-31 15:59', '2008-12-31 15:59:10' + if (($d = PHPExcel_Shared_Date::stringToExcel($value)) !== false) { + // Convert value to number + $cell->setValueExplicit($d, PHPExcel_Cell_DataType::TYPE_NUMERIC); + // Determine style. Either there is a time part or not. Look for ':' + if (strpos($value, ':') !== false) { + $formatCode = 'yyyy-mm-dd h:mm'; + } else { + $formatCode = 'yyyy-mm-dd'; + } + $cell->getWorksheet()->getStyle( $cell->getCoordinate() ) + ->getNumberFormat()->setFormatCode($formatCode); + return true; + } - // Check for newline character "\n" - if (strpos($value, "\n") !== FALSE) { - $value = PHPExcel_Shared_String::SanitizeUTF8($value); - $cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_STRING); - // Set style - $cell->getParent()->getStyle( $cell->getCoordinate() ) - ->getAlignment()->setWrapText(TRUE); - return true; - } - } + // Check for newline character "\n" + if (strpos($value, "\n") !== FALSE) { + $value = PHPExcel_Shared_String::SanitizeUTF8($value); + $cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_STRING); + // Set style + $cell->getWorksheet()->getStyle( $cell->getCoordinate() ) + ->getAlignment()->setWrapText(TRUE); + return true; + } + } - // Not bound yet? Use parent... - return parent::bindValue($cell, $value); - } + // Not bound yet? Use parent... + return parent::bindValue($cell, $value); + } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Cell/DataType.php b/htdocs/includes/phpexcel/PHPExcel/Cell/DataType.php index a833a5a44e3..85765426b89 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Cell/DataType.php +++ b/htdocs/includes/phpexcel/PHPExcel/Cell/DataType.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.8.0, 2014-03-02 */ @@ -31,84 +31,92 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Cell_DataType { - /* Data types */ - const TYPE_STRING2 = 'str'; - const TYPE_STRING = 's'; - const TYPE_FORMULA = 'f'; - const TYPE_NUMERIC = 'n'; - const TYPE_BOOL = 'b'; - const TYPE_NULL = 'null'; - const TYPE_INLINE = 'inlineStr'; - const TYPE_ERROR = 'e'; + /* Data types */ + const TYPE_STRING2 = 'str'; + const TYPE_STRING = 's'; + const TYPE_FORMULA = 'f'; + const TYPE_NUMERIC = 'n'; + const TYPE_BOOL = 'b'; + const TYPE_NULL = 'null'; + const TYPE_INLINE = 'inlineStr'; + const TYPE_ERROR = 'e'; - /** - * List of error codes - * - * @var array - */ - private static $_errorCodes = array('#NULL!' => 0, '#DIV/0!' => 1, '#VALUE!' => 2, '#REF!' => 3, '#NAME?' => 4, '#NUM!' => 5, '#N/A' => 6); + /** + * List of error codes + * + * @var array + */ + private static $_errorCodes = array( + '#NULL!' => 0, + '#DIV/0!' => 1, + '#VALUE!' => 2, + '#REF!' => 3, + '#NAME?' => 4, + '#NUM!' => 5, + '#N/A' => 6 + ); - /** - * Get list of error codes - * - * @return array - */ - public static function getErrorCodes() { - return self::$_errorCodes; - } + /** + * Get list of error codes + * + * @return array + */ + public static function getErrorCodes() { + return self::$_errorCodes; + } - /** - * DataType for value - * - * @deprecated Replaced by PHPExcel_Cell_IValueBinder infrastructure - * @param mixed $pValue - * @return int - */ - public static function dataTypeForValue($pValue = null) { - return PHPExcel_Cell_DefaultValueBinder::dataTypeForValue($pValue); - } + /** + * DataType for value + * + * @deprecated Replaced by PHPExcel_Cell_IValueBinder infrastructure, will be removed in version 1.8.0 + * @param mixed $pValue + * @return string + */ + public static function dataTypeForValue($pValue = null) { + return PHPExcel_Cell_DefaultValueBinder::dataTypeForValue($pValue); + } - /** - * Check a string that it satisfies Excel requirements - * - * @param mixed Value to sanitize to an Excel string - * @return mixed Sanitized value - */ - public static function checkString($pValue = null) - { - if ($pValue instanceof PHPExcel_RichText) { - // TODO: Sanitize Rich-Text string (max. character count is 32,767) - return $pValue; - } + /** + * Check a string that it satisfies Excel requirements + * + * @param mixed Value to sanitize to an Excel string + * @return mixed Sanitized value + */ + public static function checkString($pValue = null) + { + if ($pValue instanceof PHPExcel_RichText) { + // TODO: Sanitize Rich-Text string (max. character count is 32,767) + return $pValue; + } - // string must never be longer than 32,767 characters, truncate if necessary - $pValue = PHPExcel_Shared_String::Substring($pValue, 0, 32767); + // string must never be longer than 32,767 characters, truncate if necessary + $pValue = PHPExcel_Shared_String::Substring($pValue, 0, 32767); - // we require that newline is represented as "\n" in core, not as "\r\n" or "\r" - $pValue = str_replace(array("\r\n", "\r"), "\n", $pValue); + // we require that newline is represented as "\n" in core, not as "\r\n" or "\r" + $pValue = str_replace(array("\r\n", "\r"), "\n", $pValue); - return $pValue; - } + return $pValue; + } - /** - * Check a value that it is a valid error code - * - * @param mixed Value to sanitize to an Excel error code - * @return string Sanitized value - */ - public static function checkErrorCode($pValue = null) - { - $pValue = (string)$pValue; + /** + * Check a value that it is a valid error code + * + * @param mixed Value to sanitize to an Excel error code + * @return string Sanitized value + */ + public static function checkErrorCode($pValue = null) + { + $pValue = (string) $pValue; - if ( !array_key_exists($pValue, self::$_errorCodes) ) { - $pValue = '#NULL!'; - } + if ( !array_key_exists($pValue, self::$_errorCodes) ) { + $pValue = '#NULL!'; + } - return $pValue; - } + return $pValue; + } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Cell/DataValidation.php b/htdocs/includes/phpexcel/PHPExcel/Cell/DataValidation.php index 01b1edb7e52..3174a3fe44a 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Cell/DataValidation.php +++ b/htdocs/includes/phpexcel/PHPExcel/Cell/DataValidation.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.8.0, 2014-03-02 */ @@ -31,34 +31,34 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Cell_DataValidation { - /* Data validation types */ - const TYPE_NONE = 'none'; - const TYPE_CUSTOM = 'custom'; - const TYPE_DATE = 'date'; - const TYPE_DECIMAL = 'decimal'; - const TYPE_LIST = 'list'; - const TYPE_TEXTLENGTH = 'textLength'; - const TYPE_TIME = 'time'; - const TYPE_WHOLE = 'whole'; + /* Data validation types */ + const TYPE_NONE = 'none'; + const TYPE_CUSTOM = 'custom'; + const TYPE_DATE = 'date'; + const TYPE_DECIMAL = 'decimal'; + const TYPE_LIST = 'list'; + const TYPE_TEXTLENGTH = 'textLength'; + const TYPE_TIME = 'time'; + const TYPE_WHOLE = 'whole'; - /* Data validation error styles */ - const STYLE_STOP = 'stop'; - const STYLE_WARNING = 'warning'; - const STYLE_INFORMATION = 'information'; + /* Data validation error styles */ + const STYLE_STOP = 'stop'; + const STYLE_WARNING = 'warning'; + const STYLE_INFORMATION = 'information'; - /* Data validation operators */ - const OPERATOR_BETWEEN = 'between'; - const OPERATOR_EQUAL = 'equal'; - const OPERATOR_GREATERTHAN = 'greaterThan'; - const OPERATOR_GREATERTHANOREQUAL = 'greaterThanOrEqual'; - const OPERATOR_LESSTHAN = 'lessThan'; - const OPERATOR_LESSTHANOREQUAL = 'lessThanOrEqual'; - const OPERATOR_NOTBETWEEN = 'notBetween'; - const OPERATOR_NOTEQUAL = 'notEqual'; + /* Data validation operators */ + const OPERATOR_BETWEEN = 'between'; + const OPERATOR_EQUAL = 'equal'; + const OPERATOR_GREATERTHAN = 'greaterThan'; + const OPERATOR_GREATERTHANOREQUAL = 'greaterThanOrEqual'; + const OPERATOR_LESSTHAN = 'lessThan'; + const OPERATOR_LESSTHANOREQUAL = 'lessThanOrEqual'; + const OPERATOR_NOTBETWEEN = 'notBetween'; + const OPERATOR_NOTEQUAL = 'notEqual'; /** * Formula 1 @@ -153,322 +153,320 @@ class PHPExcel_Cell_DataValidation /** * Create a new PHPExcel_Cell_DataValidation - * - * @throws Exception */ public function __construct() { - // Initialise member variables - $this->_formula1 = ''; - $this->_formula2 = ''; - $this->_type = PHPExcel_Cell_DataValidation::TYPE_NONE; - $this->_errorStyle = PHPExcel_Cell_DataValidation::STYLE_STOP; - $this->_operator = ''; - $this->_allowBlank = false; - $this->_showDropDown = false; - $this->_showInputMessage = false; - $this->_showErrorMessage = false; - $this->_errorTitle = ''; - $this->_error = ''; - $this->_promptTitle = ''; - $this->_prompt = ''; + // Initialise member variables + $this->_formula1 = ''; + $this->_formula2 = ''; + $this->_type = PHPExcel_Cell_DataValidation::TYPE_NONE; + $this->_errorStyle = PHPExcel_Cell_DataValidation::STYLE_STOP; + $this->_operator = ''; + $this->_allowBlank = FALSE; + $this->_showDropDown = FALSE; + $this->_showInputMessage = FALSE; + $this->_showErrorMessage = FALSE; + $this->_errorTitle = ''; + $this->_error = ''; + $this->_promptTitle = ''; + $this->_prompt = ''; } - /** - * Get Formula 1 - * - * @return string - */ - public function getFormula1() { - return $this->_formula1; - } - - /** - * Set Formula 1 - * - * @param string $value - * @return PHPExcel_Cell_DataValidation - */ - public function setFormula1($value = '') { - $this->_formula1 = $value; - return $this; - } - - /** - * Get Formula 2 - * - * @return string - */ - public function getFormula2() { - return $this->_formula2; - } - - /** - * Set Formula 2 - * - * @param string $value - * @return PHPExcel_Cell_DataValidation - */ - public function setFormula2($value = '') { - $this->_formula2 = $value; - return $this; - } - - /** - * Get Type - * - * @return string - */ - public function getType() { - return $this->_type; - } - - /** - * Set Type - * - * @param string $value - * @return PHPExcel_Cell_DataValidation - */ - public function setType($value = PHPExcel_Cell_DataValidation::TYPE_NONE) { - $this->_type = $value; - return $this; - } - - /** - * Get Error style - * - * @return string - */ - public function getErrorStyle() { - return $this->_errorStyle; - } - - /** - * Set Error style - * - * @param string $value - * @return PHPExcel_Cell_DataValidation - */ - public function setErrorStyle($value = PHPExcel_Cell_DataValidation::STYLE_STOP) { - $this->_errorStyle = $value; - return $this; - } - - /** - * Get Operator - * - * @return string - */ - public function getOperator() { - return $this->_operator; - } - - /** - * Set Operator - * - * @param string $value - * @return PHPExcel_Cell_DataValidation - */ - public function setOperator($value = '') { - $this->_operator = $value; - return $this; - } - - /** - * Get Allow Blank - * - * @return boolean - */ - public function getAllowBlank() { - return $this->_allowBlank; - } - - /** - * Set Allow Blank - * - * @param boolean $value - * @return PHPExcel_Cell_DataValidation - */ - public function setAllowBlank($value = false) { - $this->_allowBlank = $value; - return $this; - } - - /** - * Get Show DropDown - * - * @return boolean - */ - public function getShowDropDown() { - return $this->_showDropDown; - } - - /** - * Set Show DropDown - * - * @param boolean $value - * @return PHPExcel_Cell_DataValidation - */ - public function setShowDropDown($value = false) { - $this->_showDropDown = $value; - return $this; - } - - /** - * Get Show InputMessage - * - * @return boolean - */ - public function getShowInputMessage() { - return $this->_showInputMessage; - } - - /** - * Set Show InputMessage - * - * @param boolean $value - * @return PHPExcel_Cell_DataValidation - */ - public function setShowInputMessage($value = false) { - $this->_showInputMessage = $value; - return $this; - } - - /** - * Get Show ErrorMessage - * - * @return boolean - */ - public function getShowErrorMessage() { - return $this->_showErrorMessage; - } - - /** - * Set Show ErrorMessage - * - * @param boolean $value - * @return PHPExcel_Cell_DataValidation - */ - public function setShowErrorMessage($value = false) { - $this->_showErrorMessage = $value; - return $this; - } - - /** - * Get Error title - * - * @return string - */ - public function getErrorTitle() { - return $this->_errorTitle; - } - - /** - * Set Error title - * - * @param string $value - * @return PHPExcel_Cell_DataValidation - */ - public function setErrorTitle($value = '') { - $this->_errorTitle = $value; - return $this; - } - - /** - * Get Error - * - * @return string - */ - public function getError() { - return $this->_error; - } - - /** - * Set Error - * - * @param string $value - * @return PHPExcel_Cell_DataValidation - */ - public function setError($value = '') { - $this->_error = $value; - return $this; - } - - /** - * Get Prompt title - * - * @return string - */ - public function getPromptTitle() { - return $this->_promptTitle; - } - - /** - * Set Prompt title - * - * @param string $value - * @return PHPExcel_Cell_DataValidation - */ - public function setPromptTitle($value = '') { - $this->_promptTitle = $value; - return $this; - } - - /** - * Get Prompt - * - * @return string - */ - public function getPrompt() { - return $this->_prompt; - } - - /** - * Set Prompt - * - * @param string $value - * @return PHPExcel_Cell_DataValidation - */ - public function setPrompt($value = '') { - $this->_prompt = $value; - return $this; - } - - /** - * Get hash code - * - * @return string Hash code - */ - public function getHashCode() { - return md5( - $this->_formula1 - . $this->_formula2 - . $this->_type = PHPExcel_Cell_DataValidation::TYPE_NONE - . $this->_errorStyle = PHPExcel_Cell_DataValidation::STYLE_STOP - . $this->_operator - . ($this->_allowBlank ? 't' : 'f') - . ($this->_showDropDown ? 't' : 'f') - . ($this->_showInputMessage ? 't' : 'f') - . ($this->_showErrorMessage ? 't' : 'f') - . $this->_errorTitle - . $this->_error - . $this->_promptTitle - . $this->_prompt - . __CLASS__ - ); + /** + * Get Formula 1 + * + * @return string + */ + public function getFormula1() { + return $this->_formula1; } - /** - * Implement PHP __clone to create a deep clone, not just a shallow copy. - */ - public function __clone() { - $vars = get_object_vars($this); - foreach ($vars as $key => $value) { - if (is_object($value)) { - $this->$key = clone $value; - } else { - $this->$key = $value; - } - } - } + /** + * Set Formula 1 + * + * @param string $value + * @return PHPExcel_Cell_DataValidation + */ + public function setFormula1($value = '') { + $this->_formula1 = $value; + return $this; + } + + /** + * Get Formula 2 + * + * @return string + */ + public function getFormula2() { + return $this->_formula2; + } + + /** + * Set Formula 2 + * + * @param string $value + * @return PHPExcel_Cell_DataValidation + */ + public function setFormula2($value = '') { + $this->_formula2 = $value; + return $this; + } + + /** + * Get Type + * + * @return string + */ + public function getType() { + return $this->_type; + } + + /** + * Set Type + * + * @param string $value + * @return PHPExcel_Cell_DataValidation + */ + public function setType($value = PHPExcel_Cell_DataValidation::TYPE_NONE) { + $this->_type = $value; + return $this; + } + + /** + * Get Error style + * + * @return string + */ + public function getErrorStyle() { + return $this->_errorStyle; + } + + /** + * Set Error style + * + * @param string $value + * @return PHPExcel_Cell_DataValidation + */ + public function setErrorStyle($value = PHPExcel_Cell_DataValidation::STYLE_STOP) { + $this->_errorStyle = $value; + return $this; + } + + /** + * Get Operator + * + * @return string + */ + public function getOperator() { + return $this->_operator; + } + + /** + * Set Operator + * + * @param string $value + * @return PHPExcel_Cell_DataValidation + */ + public function setOperator($value = '') { + $this->_operator = $value; + return $this; + } + + /** + * Get Allow Blank + * + * @return boolean + */ + public function getAllowBlank() { + return $this->_allowBlank; + } + + /** + * Set Allow Blank + * + * @param boolean $value + * @return PHPExcel_Cell_DataValidation + */ + public function setAllowBlank($value = false) { + $this->_allowBlank = $value; + return $this; + } + + /** + * Get Show DropDown + * + * @return boolean + */ + public function getShowDropDown() { + return $this->_showDropDown; + } + + /** + * Set Show DropDown + * + * @param boolean $value + * @return PHPExcel_Cell_DataValidation + */ + public function setShowDropDown($value = false) { + $this->_showDropDown = $value; + return $this; + } + + /** + * Get Show InputMessage + * + * @return boolean + */ + public function getShowInputMessage() { + return $this->_showInputMessage; + } + + /** + * Set Show InputMessage + * + * @param boolean $value + * @return PHPExcel_Cell_DataValidation + */ + public function setShowInputMessage($value = false) { + $this->_showInputMessage = $value; + return $this; + } + + /** + * Get Show ErrorMessage + * + * @return boolean + */ + public function getShowErrorMessage() { + return $this->_showErrorMessage; + } + + /** + * Set Show ErrorMessage + * + * @param boolean $value + * @return PHPExcel_Cell_DataValidation + */ + public function setShowErrorMessage($value = false) { + $this->_showErrorMessage = $value; + return $this; + } + + /** + * Get Error title + * + * @return string + */ + public function getErrorTitle() { + return $this->_errorTitle; + } + + /** + * Set Error title + * + * @param string $value + * @return PHPExcel_Cell_DataValidation + */ + public function setErrorTitle($value = '') { + $this->_errorTitle = $value; + return $this; + } + + /** + * Get Error + * + * @return string + */ + public function getError() { + return $this->_error; + } + + /** + * Set Error + * + * @param string $value + * @return PHPExcel_Cell_DataValidation + */ + public function setError($value = '') { + $this->_error = $value; + return $this; + } + + /** + * Get Prompt title + * + * @return string + */ + public function getPromptTitle() { + return $this->_promptTitle; + } + + /** + * Set Prompt title + * + * @param string $value + * @return PHPExcel_Cell_DataValidation + */ + public function setPromptTitle($value = '') { + $this->_promptTitle = $value; + return $this; + } + + /** + * Get Prompt + * + * @return string + */ + public function getPrompt() { + return $this->_prompt; + } + + /** + * Set Prompt + * + * @param string $value + * @return PHPExcel_Cell_DataValidation + */ + public function setPrompt($value = '') { + $this->_prompt = $value; + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + return md5( + $this->_formula1 + . $this->_formula2 + . $this->_type = PHPExcel_Cell_DataValidation::TYPE_NONE + . $this->_errorStyle = PHPExcel_Cell_DataValidation::STYLE_STOP + . $this->_operator + . ($this->_allowBlank ? 't' : 'f') + . ($this->_showDropDown ? 't' : 'f') + . ($this->_showInputMessage ? 't' : 'f') + . ($this->_showErrorMessage ? 't' : 'f') + . $this->_errorTitle + . $this->_error + . $this->_promptTitle + . $this->_prompt + . __CLASS__ + ); + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Cell/DefaultValueBinder.php b/htdocs/includes/phpexcel/PHPExcel/Cell/DefaultValueBinder.php index f520cc5ed7a..f1880faa790 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Cell/DefaultValueBinder.php +++ b/htdocs/includes/phpexcel/PHPExcel/Cell/DefaultValueBinder.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,19 +20,19 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.8.0, 2014-03-02 */ /** PHPExcel root directory */ if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); - require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); } @@ -41,66 +41,66 @@ if (!defined('PHPEXCEL_ROOT')) { * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Cell_DefaultValueBinder implements PHPExcel_Cell_IValueBinder { - /** - * Bind value to a cell - * - * @param PHPExcel_Cell $cell Cell to bind value to - * @param mixed $value Value to bind in cell - * @return boolean - */ - public function bindValue(PHPExcel_Cell $cell, $value = null) - { - // sanitize UTF-8 strings - if (is_string($value)) { - $value = PHPExcel_Shared_String::SanitizeUTF8($value); - } + /** + * Bind value to a cell + * + * @param PHPExcel_Cell $cell Cell to bind value to + * @param mixed $value Value to bind in cell + * @return boolean + */ + public function bindValue(PHPExcel_Cell $cell, $value = null) + { + // sanitize UTF-8 strings + if (is_string($value)) { + $value = PHPExcel_Shared_String::SanitizeUTF8($value); + } - // Set value explicit - $cell->setValueExplicit( $value, self::dataTypeForValue($value) ); + // Set value explicit + $cell->setValueExplicit( $value, self::dataTypeForValue($value) ); - // Done! - return true; - } + // Done! + return TRUE; + } - /** - * DataType for value - * - * @param mixed $pValue - * @return int - */ - public static function dataTypeForValue($pValue = null) { - // Match the value against a few data types - if (is_null($pValue)) { - return PHPExcel_Cell_DataType::TYPE_NULL; + /** + * DataType for value + * + * @param mixed $pValue + * @return string + */ + public static function dataTypeForValue($pValue = null) { + // Match the value against a few data types + if (is_null($pValue)) { + return PHPExcel_Cell_DataType::TYPE_NULL; - } elseif ($pValue === '') { - return PHPExcel_Cell_DataType::TYPE_STRING; + } elseif ($pValue === '') { + return PHPExcel_Cell_DataType::TYPE_STRING; - } elseif ($pValue instanceof PHPExcel_RichText) { - return PHPExcel_Cell_DataType::TYPE_INLINE; + } elseif ($pValue instanceof PHPExcel_RichText) { + return PHPExcel_Cell_DataType::TYPE_INLINE; - } elseif ($pValue{0} === '=' && strlen($pValue) > 1) { - return PHPExcel_Cell_DataType::TYPE_FORMULA; + } elseif ($pValue{0} === '=' && strlen($pValue) > 1) { + return PHPExcel_Cell_DataType::TYPE_FORMULA; - } elseif (is_bool($pValue)) { - return PHPExcel_Cell_DataType::TYPE_BOOL; + } elseif (is_bool($pValue)) { + return PHPExcel_Cell_DataType::TYPE_BOOL; - } elseif (is_float($pValue) || is_int($pValue)) { - return PHPExcel_Cell_DataType::TYPE_NUMERIC; + } elseif (is_float($pValue) || is_int($pValue)) { + return PHPExcel_Cell_DataType::TYPE_NUMERIC; - } elseif (preg_match('/^\-?([0-9]+\\.?[0-9]*|[0-9]*\\.?[0-9]+)$/', $pValue)) { - return PHPExcel_Cell_DataType::TYPE_NUMERIC; + } elseif (preg_match('/^\-?([0-9]+\\.?[0-9]*|[0-9]*\\.?[0-9]+)$/', $pValue)) { + return PHPExcel_Cell_DataType::TYPE_NUMERIC; - } elseif (is_string($pValue) && array_key_exists($pValue, PHPExcel_Cell_DataType::getErrorCodes())) { - return PHPExcel_Cell_DataType::TYPE_ERROR; + } elseif (is_string($pValue) && array_key_exists($pValue, PHPExcel_Cell_DataType::getErrorCodes())) { + return PHPExcel_Cell_DataType::TYPE_ERROR; - } else { - return PHPExcel_Cell_DataType::TYPE_STRING; + } else { + return PHPExcel_Cell_DataType::TYPE_STRING; - } - } + } + } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Cell/Hyperlink.php b/htdocs/includes/phpexcel/PHPExcel/Cell/Hyperlink.php index 9dc13042aa5..06edfad0b69 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Cell/Hyperlink.php +++ b/htdocs/includes/phpexcel/PHPExcel/Cell/Hyperlink.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.8.0, 2014-03-02 */ @@ -31,97 +31,96 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Cell_Hyperlink { - /** - * URL to link the cell to - * - * @var string - */ - private $_url; + /** + * URL to link the cell to + * + * @var string + */ + private $_url; - /** - * Tooltip to display on the hyperlink - * - * @var string - */ - private $_tooltip; + /** + * Tooltip to display on the hyperlink + * + * @var string + */ + private $_tooltip; /** * Create a new PHPExcel_Cell_Hyperlink * - * @param string $pUrl Url to link the cell to - * @param string $pTooltip Tooltip to display on the hyperlink - * @throws Exception + * @param string $pUrl Url to link the cell to + * @param string $pTooltip Tooltip to display on the hyperlink */ public function __construct($pUrl = '', $pTooltip = '') { - // Initialise member variables - $this->_url = $pUrl; - $this->_tooltip = $pTooltip; + // Initialise member variables + $this->_url = $pUrl; + $this->_tooltip = $pTooltip; } - /** - * Get URL - * - * @return string - */ - public function getUrl() { - return $this->_url; - } + /** + * Get URL + * + * @return string + */ + public function getUrl() { + return $this->_url; + } - /** - * Set URL - * - * @param string $value - * @return PHPExcel_Cell_Hyperlink - */ - public function setUrl($value = '') { - $this->_url = $value; - return $this; - } + /** + * Set URL + * + * @param string $value + * @return PHPExcel_Cell_Hyperlink + */ + public function setUrl($value = '') { + $this->_url = $value; + return $this; + } - /** - * Get tooltip - * - * @return string - */ - public function getTooltip() { - return $this->_tooltip; - } + /** + * Get tooltip + * + * @return string + */ + public function getTooltip() { + return $this->_tooltip; + } - /** - * Set tooltip - * - * @param string $value - * @return PHPExcel_Cell_Hyperlink - */ - public function setTooltip($value = '') { - $this->_tooltip = $value; - return $this; - } + /** + * Set tooltip + * + * @param string $value + * @return PHPExcel_Cell_Hyperlink + */ + public function setTooltip($value = '') { + $this->_tooltip = $value; + return $this; + } - /** - * Is this hyperlink internal? (to another sheet) - * - * @return boolean - */ - public function isInternal() { - return strpos($this->_url, 'sheet://') !== false; - } + /** + * Is this hyperlink internal? (to another worksheet) + * + * @return boolean + */ + public function isInternal() { + return strpos($this->_url, 'sheet://') !== false; + } - /** - * Get hash code - * - * @return string Hash code - */ - public function getHashCode() { - return md5( - $this->_url - . $this->_tooltip - . __CLASS__ - ); + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + return md5( + $this->_url + . $this->_tooltip + . __CLASS__ + ); } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Cell/IValueBinder.php b/htdocs/includes/phpexcel/PHPExcel/Cell/IValueBinder.php index 4070b674c77..bc7b468b9cd 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Cell/IValueBinder.php +++ b/htdocs/includes/phpexcel/PHPExcel/Cell/IValueBinder.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.8.0, 2014-03-02 */ @@ -31,16 +31,16 @@ * * @category PHPExcel * @package PHPExcel_Cell - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ interface PHPExcel_Cell_IValueBinder { - /** - * Bind value to a cell - * - * @param PHPExcel_Cell $cell Cell to bind value to - * @param mixed $value Value to bind in cell - * @return boolean - */ - public function bindValue(PHPExcel_Cell $cell, $value = null); + /** + * Bind value to a cell + * + * @param PHPExcel_Cell $cell Cell to bind value to + * @param mixed $value Value to bind in cell + * @return boolean + */ + public function bindValue(PHPExcel_Cell $cell, $value = NULL); } diff --git a/htdocs/includes/phpexcel/PHPExcel/Chart.php b/htdocs/includes/phpexcel/PHPExcel/Chart.php index 4fa4cddb2df..9d251b8fd49 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Chart.php +++ b/htdocs/includes/phpexcel/PHPExcel/Chart.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Chart - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Chart - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Chart { @@ -184,7 +184,7 @@ class PHPExcel_Chart * Set Worksheet * * @param PHPExcel_Worksheet $pValue - * @throws Exception + * @throws PHPExcel_Chart_Exception * @return PHPExcel_Chart */ public function setWorksheet(PHPExcel_Worksheet $pValue = null) { @@ -378,6 +378,13 @@ class PHPExcel_Chart return $this; } + /** + * Set the offset position within the Top Left cell for the chart + * + * @param integer $xOffset + * @param integer $yOffset + * @return PHPExcel_Chart + */ public function setTopLeftOffset($xOffset=null,$yOffset=null) { if (!is_null($xOffset)) $this->setTopLeftXOffset($xOffset); @@ -387,6 +394,11 @@ class PHPExcel_Chart return $this; } + /** + * Get the offset position within the Top Left cell for the chart + * + * @return integer[] + */ public function getTopLeftOffset() { return array( 'X' => $this->_topLeftXOffset, 'Y' => $this->_topLeftYOffset @@ -458,6 +470,13 @@ class PHPExcel_Chart return $this->_bottomRightCellRef; } + /** + * Set the offset position within the Bottom Right cell for the chart + * + * @param integer $xOffset + * @param integer $yOffset + * @return PHPExcel_Chart + */ public function setBottomRightOffset($xOffset=null,$yOffset=null) { if (!is_null($xOffset)) $this->setBottomRightXOffset($xOffset); @@ -467,6 +486,11 @@ class PHPExcel_Chart return $this; } + /** + * Get the offset position within the Bottom Right cell for the chart + * + * @return integer[] + */ public function getBottomRightOffset() { return array( 'X' => $this->_bottomRightXOffset, 'Y' => $this->_bottomRightYOffset diff --git a/htdocs/includes/phpexcel/PHPExcel/Chart/DataSeries.php b/htdocs/includes/phpexcel/PHPExcel/Chart/DataSeries.php index 16e5e23194f..f5391aae995 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Chart/DataSeries.php +++ b/htdocs/includes/phpexcel/PHPExcel/Chart/DataSeries.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Chart - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Chart - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Chart_DataSeries { @@ -52,6 +52,7 @@ class PHPExcel_Chart_DataSeries const TYPE_RADARCHART = 'radarChart'; const TYPE_BUBBLECHART = 'bubbleChart'; const TYPE_STOCKCHART = 'stockChart'; + const TYPE_CANDLECHART = self::TYPE_STOCKCHART; // Synonym const GROUPING_CLUSTERED = 'clustered'; const GROUPING_STACKED = 'stacked'; @@ -169,9 +170,11 @@ class PHPExcel_Chart_DataSeries * Set Plot Type * * @param string $plotType + * @return PHPExcel_Chart_DataSeries */ public function setPlotType($plotType = '') { $this->_plotType = $plotType; + return $this; } /** @@ -187,9 +190,11 @@ class PHPExcel_Chart_DataSeries * Set Plot Grouping Type * * @param string $groupingType + * @return PHPExcel_Chart_DataSeries */ public function setPlotGrouping($groupingType = null) { $this->_plotGrouping = $groupingType; + return $this; } /** @@ -205,9 +210,11 @@ class PHPExcel_Chart_DataSeries * Set Plot Direction * * @param string $plotDirection + * @return PHPExcel_Chart_DataSeries */ public function setPlotDirection($plotDirection = null) { $this->_plotDirection = $plotDirection; + return $this; } /** @@ -280,9 +287,11 @@ class PHPExcel_Chart_DataSeries * Set Plot Style * * @param string $plotStyle + * @return PHPExcel_Chart_DataSeries */ public function setPlotStyle($plotStyle = null) { $this->_plotStyle = $plotStyle; + return $this; } /** @@ -331,9 +340,11 @@ class PHPExcel_Chart_DataSeries * Set Smooth Line * * @param boolean $smoothLine + * @return PHPExcel_Chart_DataSeries */ public function setSmoothLine($smoothLine = TRUE) { $this->_smoothLine = $smoothLine; + return $this; } public function refresh(PHPExcel_Worksheet $worksheet) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Chart/DataSeriesValues.php b/htdocs/includes/phpexcel/PHPExcel/Chart/DataSeriesValues.php index e49d0c79a84..930542b5601 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Chart/DataSeriesValues.php +++ b/htdocs/includes/phpexcel/PHPExcel/Chart/DataSeriesValues.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Chart - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Chart - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Chart_DataSeriesValues { @@ -279,7 +279,7 @@ class PHPExcel_Chart_DataSeriesValues public function refresh(PHPExcel_Worksheet $worksheet, $flatten = TRUE) { if ($this->_dataSource !== NULL) { - $calcEngine = PHPExcel_Calculation::getInstance(); + $calcEngine = PHPExcel_Calculation::getInstance($worksheet->getParent()); $newDataValues = PHPExcel_Calculation::_unwrapResult( $calcEngine->_calculateFormulaValue( '='.$this->_dataSource, @@ -289,6 +289,12 @@ class PHPExcel_Chart_DataSeriesValues ); if ($flatten) { $this->_dataValues = PHPExcel_Calculation_Functions::flattenArray($newDataValues); + foreach($this->_dataValues as &$dataValue) { + if ((!empty($dataValue)) && ($dataValue[0] == '#')) { + $dataValue = 0.0; + } + } + unset($dataValue); } else { $cellRange = explode('!',$this->_dataSource); if (count($cellRange) > 1) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Chart/Exception.php b/htdocs/includes/phpexcel/PHPExcel/Chart/Exception.php index 984d5f91ddb..ecf3c43824e 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Chart/Exception.php +++ b/htdocs/includes/phpexcel/PHPExcel/Chart/Exception.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Chart - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,9 +31,9 @@ * * @category PHPExcel * @package PHPExcel_Chart - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Chart_Exception extends Exception { +class PHPExcel_Chart_Exception extends PHPExcel_Exception { /** * Error handler callback * diff --git a/htdocs/includes/phpexcel/PHPExcel/Chart/Layout.php b/htdocs/includes/phpexcel/PHPExcel/Chart/Layout.php index d128382c16f..d749dfedce2 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Chart/Layout.php +++ b/htdocs/includes/phpexcel/PHPExcel/Chart/Layout.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Chart - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Chart - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Chart_Layout { @@ -167,9 +167,11 @@ class PHPExcel_Chart_Layout * Set Layout Target * * @param Layout Target $value + * @return PHPExcel_Chart_Layout */ public function setLayoutTarget($value) { $this->_layoutTarget = $value; + return $this; } /** @@ -185,9 +187,11 @@ class PHPExcel_Chart_Layout * Set X-Mode * * @param X-Mode $value + * @return PHPExcel_Chart_Layout */ public function setXMode($value) { $this->_xMode = $value; + return $this; } /** @@ -196,16 +200,18 @@ class PHPExcel_Chart_Layout * @return string */ public function getYMode() { - return $this->_xMode; + return $this->_yMode; } /** * Set Y-Mode * * @param Y-Mode $value + * @return PHPExcel_Chart_Layout */ public function setYMode($value) { - $this->_xMode = $value; + $this->_yMode = $value; + return $this; } /** @@ -221,9 +227,11 @@ class PHPExcel_Chart_Layout * Set X-Position * * @param X-Position $value + * @return PHPExcel_Chart_Layout */ public function setXPosition($value) { $this->_xPos = $value; + return $this; } /** @@ -239,9 +247,11 @@ class PHPExcel_Chart_Layout * Set Y-Position * * @param Y-Position $value + * @return PHPExcel_Chart_Layout */ public function setYPosition($value) { $this->_yPos = $value; + return $this; } /** @@ -257,9 +267,11 @@ class PHPExcel_Chart_Layout * Set Width * * @param Width $value + * @return PHPExcel_Chart_Layout */ public function setWidth($value) { $this->_width = $value; + return $this; } /** @@ -275,9 +287,11 @@ class PHPExcel_Chart_Layout * Set Height * * @param Height $value + * @return PHPExcel_Chart_Layout */ public function setHeight($value) { $this->_height = $value; + return $this; } @@ -295,9 +309,11 @@ class PHPExcel_Chart_Layout * Specifies that legend keys should be shown in data labels. * * @param boolean $value Show legend key + * @return PHPExcel_Chart_Layout */ public function setShowLegendKey($value) { $this->_showLegendKey = $value; + return $this; } /** @@ -314,9 +330,11 @@ class PHPExcel_Chart_Layout * Specifies that the value should be shown in data labels. * * @param boolean $value Show val + * @return PHPExcel_Chart_Layout */ public function setShowVal($value) { $this->_showVal = $value; + return $this; } /** @@ -333,9 +351,11 @@ class PHPExcel_Chart_Layout * Specifies that the category name should be shown in data labels. * * @param boolean $value Show cat name + * @return PHPExcel_Chart_Layout */ public function setShowCatName($value) { $this->_showCatName = $value; + return $this; } /** @@ -351,10 +371,12 @@ class PHPExcel_Chart_Layout * Set show ser name * Specifies that the series name should be shown in data labels. * - * @param boolean $value Show ser name + * @param boolean $value Show series name + * @return PHPExcel_Chart_Layout */ public function setShowSerName($value) { $this->_showSerName = $value; + return $this; } /** @@ -371,9 +393,11 @@ class PHPExcel_Chart_Layout * Specifies that the percentage should be shown in data labels. * * @param boolean $value Show percentage + * @return PHPExcel_Chart_Layout */ public function setShowPercent($value) { $this->_showPercent = $value; + return $this; } /** @@ -390,9 +414,11 @@ class PHPExcel_Chart_Layout * Specifies that the bubble size should be shown in data labels. * * @param boolean $value Show bubble size + * @return PHPExcel_Chart_Layout */ public function setShowBubbleSize($value) { $this->_showBubbleSize = $value; + return $this; } /** @@ -409,9 +435,11 @@ class PHPExcel_Chart_Layout * Specifies that leader lines should be shown in data labels. * * @param boolean $value Show leader lines + * @return PHPExcel_Chart_Layout */ public function setShowLeaderLines($value) { $this->_showLeaderLines = $value; + return $this; } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Chart/Legend.php b/htdocs/includes/phpexcel/PHPExcel/Chart/Legend.php index 0ccd77e958d..4b7c6449aab 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Chart/Legend.php +++ b/htdocs/includes/phpexcel/PHPExcel/Chart/Legend.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Chart - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Chart - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Chart_Legend { diff --git a/htdocs/includes/phpexcel/PHPExcel/Chart/PlotArea.php b/htdocs/includes/phpexcel/PHPExcel/Chart/PlotArea.php index 134ee59550a..237d29b0e25 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Chart/PlotArea.php +++ b/htdocs/includes/phpexcel/PHPExcel/Chart/PlotArea.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Chart - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Chart - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Chart_PlotArea { @@ -110,10 +110,13 @@ class PHPExcel_Chart_PlotArea /** * Set Plot Series * - * @param array of PHPExcel_Chart_DataSeries + * @param [PHPExcel_Chart_DataSeries] + * @return PHPExcel_Chart_PlotArea */ public function setPlotSeries($plotSeries = array()) { $this->_plotSeries = $plotSeries; + + return $this; } public function refresh(PHPExcel_Worksheet $worksheet) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Chart/Renderer/jpgraph.php b/htdocs/includes/phpexcel/PHPExcel/Chart/Renderer/jpgraph.php index 889fd9fce08..14ba2a04152 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Chart/Renderer/jpgraph.php +++ b/htdocs/includes/phpexcel/PHPExcel/Chart/Renderer/jpgraph.php @@ -3,7 +3,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,10 +20,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * @category PHPExcel - * @package PHPExcel_Chart - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @package PHPExcel_Chart_Renderer + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -35,7 +35,7 @@ require_once(PHPExcel_Settings::getChartRendererPath().'/jpgraph.php'); * * @category PHPExcel * @package PHPExcel_Chart_Renderer - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Chart_Renderer_jpgraph { @@ -107,13 +107,11 @@ class PHPExcel_Chart_Renderer_jpgraph $testCurrentIndex = 0; foreach($datasetLabels as $i => $datasetLabel) { - array_reverse($datasetLabel); - if (is_array($datasetLabel)) { if ($rotation == 'bar') { - $datasetLabel = array_reverse($datasetLabel); $datasetLabels[$i] = implode(" ",$datasetLabel); } else { + $datasetLabel = array_reverse($datasetLabel); $datasetLabels[$i] = implode("\n",$datasetLabel); } } else { @@ -519,19 +517,37 @@ class PHPExcel_Chart_Renderer_jpgraph private function _renderPlotStock($groupID) { $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); $plotOrder = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotOrder(); - $seriesPlots = array(); $dataValues = array(); - // Loop through each data series in turn - for($i = 0; $i < $seriesCount; ++$i) { - $dataValuesY = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues(); - $dataValuesX = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); - - foreach($dataValuesX as $j => $dataValueX) - $dataValues[$j][$plotOrder[$i]] = $dataValueX; + // Loop through each data series in turn and build the plot arrays + foreach($plotOrder as $i => $v) { + $dataValuesX = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($v)->getDataValues(); + foreach($dataValuesX as $j => $dataValueX) { + $dataValues[$plotOrder[$i]][$j] = $dataValueX; + } + } + if(empty($dataValues)) { + return; } - $seriesPlot = new StockPlot($dataValues); + $dataValuesPlot = array(); + // Flatten the plot arrays to a single dimensional array to work with jpgraph + for($j = 0; $j < count($dataValues[0]); $j++) { + for($i = 0; $i < $seriesCount; $i++) { + $dataValuesPlot[] = $dataValues[$i][$j]; + } + } + + // Set the x-axis labels + $labelCount = count($this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount()); + if ($labelCount > 0) { + $datasetLabels = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues(); + $datasetLabels = $this->_formatDataSetLabels($groupID, $datasetLabels, $labelCount); + $this->_graph->xaxis->SetTickLabels($datasetLabels); + } + + $seriesPlot = new StockPlot($dataValuesPlot); + $seriesPlot->SetWidth(20); $this->_graph->Add($seriesPlot); } // function _renderPlotStock() @@ -683,9 +699,9 @@ class PHPExcel_Chart_Renderer_jpgraph private function _renderStockChart($groupCount) { require_once('jpgraph_stock.php'); - $this->_renderCartesianPlotArea(); + $this->_renderCartesianPlotArea('intint'); - for($groupID = 0; $groupID < $groupCount; ++$i) { + for($groupID = 0; $groupID < $groupCount; ++$groupID) { $this->_renderPlotStock($groupID); } } // function _renderStockChart() diff --git a/htdocs/includes/phpexcel/PHPExcel/Chart/Title.php b/htdocs/includes/phpexcel/PHPExcel/Chart/Title.php index ef26f465825..415551b3f0f 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Chart/Title.php +++ b/htdocs/includes/phpexcel/PHPExcel/Chart/Title.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Chart - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Chart - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Chart_Title { @@ -72,9 +72,12 @@ class PHPExcel_Chart_Title * Set caption * * @param string $caption + * @return PHPExcel_Chart_Title */ public function setCaption($caption = null) { $this->_caption = $caption; + + return $this; } /** diff --git a/htdocs/includes/phpexcel/PHPExcel/Comment.php b/htdocs/includes/phpexcel/PHPExcel/Comment.php index 4ba239f4b7c..a2422c60e9e 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Comment.php +++ b/htdocs/includes/phpexcel/PHPExcel/Comment.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.8.0, 2014-03-02 */ @@ -31,85 +31,85 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Comment implements PHPExcel_IComparable { - /** - * Author - * - * @var string - */ - private $_author; + /** + * Author + * + * @var string + */ + private $_author; - /** - * Rich text comment - * - * @var PHPExcel_RichText - */ - private $_text; + /** + * Rich text comment + * + * @var PHPExcel_RichText + */ + private $_text; - /** - * Comment width (CSS style, i.e. XXpx or YYpt) - * - * @var string - */ - private $_width = '96pt'; + /** + * Comment width (CSS style, i.e. XXpx or YYpt) + * + * @var string + */ + private $_width = '96pt'; - /** - * Left margin (CSS style, i.e. XXpx or YYpt) - * - * @var string - */ - private $_marginLeft = '59.25pt'; + /** + * Left margin (CSS style, i.e. XXpx or YYpt) + * + * @var string + */ + private $_marginLeft = '59.25pt'; - /** - * Top margin (CSS style, i.e. XXpx or YYpt) - * - * @var string - */ - private $_marginTop = '1.5pt'; + /** + * Top margin (CSS style, i.e. XXpx or YYpt) + * + * @var string + */ + private $_marginTop = '1.5pt'; - /** - * Visible - * - * @var boolean - */ - private $_visible = false; + /** + * Visible + * + * @var boolean + */ + private $_visible = false; - /** - * Comment height (CSS style, i.e. XXpx or YYpt) - * - * @var string - */ - private $_height = '55.5pt'; + /** + * Comment height (CSS style, i.e. XXpx or YYpt) + * + * @var string + */ + private $_height = '55.5pt'; - /** - * Comment fill color - * - * @var PHPExcel_Style_Color - */ - private $_fillColor; + /** + * Comment fill color + * + * @var PHPExcel_Style_Color + */ + private $_fillColor; - /** - * Alignment - * - * @var string - */ - private $_alignment; + /** + * Alignment + * + * @var string + */ + private $_alignment; /** * Create a new PHPExcel_Comment * - * @throws Exception + * @throws PHPExcel_Exception */ public function __construct() { - // Initialise variables - $this->_author = 'Author'; - $this->_text = new PHPExcel_RichText(); - $this->_fillColor = new PHPExcel_Style_Color('FFFFFFE1'); - $this->_alignment = PHPExcel_Style_Alignment::HORIZONTAL_GENERAL; + // Initialise variables + $this->_author = 'Author'; + $this->_text = new PHPExcel_RichText(); + $this->_fillColor = new PHPExcel_Style_Color('FFFFFFE1'); + $this->_alignment = PHPExcel_Style_Alignment::HORIZONTAL_GENERAL; } /** @@ -118,7 +118,7 @@ class PHPExcel_Comment implements PHPExcel_IComparable * @return string */ public function getAuthor() { - return $this->_author; + return $this->_author; } /** @@ -127,10 +127,10 @@ class PHPExcel_Comment implements PHPExcel_IComparable * @param string $pValue * @return PHPExcel_Comment */ - public function setAuthor($pValue = '') { - $this->_author = $pValue; - return $this; - } + public function setAuthor($pValue = '') { + $this->_author = $pValue; + return $this; + } /** * Get Rich text comment @@ -138,7 +138,7 @@ class PHPExcel_Comment implements PHPExcel_IComparable * @return PHPExcel_RichText */ public function getText() { - return $this->_text; + return $this->_text; } /** @@ -148,8 +148,8 @@ class PHPExcel_Comment implements PHPExcel_IComparable * @return PHPExcel_Comment */ public function setText(PHPExcel_RichText $pValue) { - $this->_text = $pValue; - return $this; + $this->_text = $pValue; + return $this; } /** @@ -268,8 +268,8 @@ class PHPExcel_Comment implements PHPExcel_IComparable * @return PHPExcel_Comment */ public function setAlignment($pValue = PHPExcel_Style_Alignment::HORIZONTAL_GENERAL) { - $this->_alignment = $pValue; - return $this; + $this->_alignment = $pValue; + return $this; } /** @@ -278,40 +278,50 @@ class PHPExcel_Comment implements PHPExcel_IComparable * @return string */ public function getAlignment() { - return $this->_alignment; + return $this->_alignment; } - /** - * Get hash code - * - * @return string Hash code - */ - public function getHashCode() { - return md5( - $this->_author - . $this->_text->getHashCode() - . $this->_width - . $this->_height - . $this->_marginLeft - . $this->_marginTop - . ($this->_visible ? 1 : 0) - . $this->_fillColor->getHashCode() - . $this->_alignment - . __CLASS__ - ); + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + return md5( + $this->_author + . $this->_text->getHashCode() + . $this->_width + . $this->_height + . $this->_marginLeft + . $this->_marginTop + . ($this->_visible ? 1 : 0) + . $this->_fillColor->getHashCode() + . $this->_alignment + . __CLASS__ + ); + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } + + /** + * Convert to string + * + * @return string + */ + public function __toString() { + return $this->_text->getPlainText(); } - /** - * Implement PHP __clone to create a deep clone, not just a shallow copy. - */ - public function __clone() { - $vars = get_object_vars($this); - foreach ($vars as $key => $value) { - if (is_object($value)) { - $this->$key = clone $value; - } else { - $this->$key = $value; - } - } - } } diff --git a/htdocs/includes/phpexcel/PHPExcel/DocumentProperties.php b/htdocs/includes/phpexcel/PHPExcel/DocumentProperties.php index 1f4cad247ca..2f1fa1ede7d 100644 --- a/htdocs/includes/phpexcel/PHPExcel/DocumentProperties.php +++ b/htdocs/includes/phpexcel/PHPExcel/DocumentProperties.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,571 +18,570 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - * @category PHPExcel - * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @category PHPExcel + * @package PHPExcel + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.8.0, 2014-03-02 */ /** * PHPExcel_DocumentProperties * - * @category PHPExcel - * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @category PHPExcel + * @package PHPExcel + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_DocumentProperties { - /** constants */ - const PROPERTY_TYPE_BOOLEAN = 'b'; - const PROPERTY_TYPE_INTEGER = 'i'; - const PROPERTY_TYPE_FLOAT = 'f'; - const PROPERTY_TYPE_DATE = 'd'; - const PROPERTY_TYPE_STRING = 's'; - const PROPERTY_TYPE_UNKNOWN = 'u'; + /** constants */ + const PROPERTY_TYPE_BOOLEAN = 'b'; + const PROPERTY_TYPE_INTEGER = 'i'; + const PROPERTY_TYPE_FLOAT = 'f'; + const PROPERTY_TYPE_DATE = 'd'; + const PROPERTY_TYPE_STRING = 's'; + const PROPERTY_TYPE_UNKNOWN = 'u'; + + /** + * Creator + * + * @var string + */ + private $_creator = 'Unknown Creator'; + + /** + * LastModifiedBy + * + * @var string + */ + private $_lastModifiedBy; + + /** + * Created + * + * @var datetime + */ + private $_created; + + /** + * Modified + * + * @var datetime + */ + private $_modified; + + /** + * Title + * + * @var string + */ + private $_title = 'Untitled Spreadsheet'; + + /** + * Description + * + * @var string + */ + private $_description = ''; + + /** + * Subject + * + * @var string + */ + private $_subject = ''; + + /** + * Keywords + * + * @var string + */ + private $_keywords = ''; + + /** + * Category + * + * @var string + */ + private $_category = ''; + + /** + * Manager + * + * @var string + */ + private $_manager = ''; + + /** + * Company + * + * @var string + */ + private $_company = 'Microsoft Corporation'; + + /** + * Custom Properties + * + * @var string + */ + private $_customProperties = array(); - /** - * Creator - * - * @var string - */ - private $_creator = 'Unknown Creator'; + /** + * Create a new PHPExcel_DocumentProperties + */ + public function __construct() + { + // Initialise values + $this->_lastModifiedBy = $this->_creator; + $this->_created = time(); + $this->_modified = time(); + } - /** - * LastModifiedBy - * - * @var string - */ - private $_lastModifiedBy; + /** + * Get Creator + * + * @return string + */ + public function getCreator() { + return $this->_creator; + } - /** - * Created - * - * @var datetime - */ - private $_created; + /** + * Set Creator + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setCreator($pValue = '') { + $this->_creator = $pValue; + return $this; + } - /** - * Modified - * - * @var datetime - */ - private $_modified; + /** + * Get Last Modified By + * + * @return string + */ + public function getLastModifiedBy() { + return $this->_lastModifiedBy; + } - /** - * Title - * - * @var string - */ - private $_title = 'Untitled Spreadsheet'; + /** + * Set Last Modified By + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setLastModifiedBy($pValue = '') { + $this->_lastModifiedBy = $pValue; + return $this; + } - /** - * Description - * - * @var string - */ - private $_description = ''; + /** + * Get Created + * + * @return datetime + */ + public function getCreated() { + return $this->_created; + } - /** - * Subject - * - * @var string - */ - private $_subject = ''; + /** + * Set Created + * + * @param datetime $pValue + * @return PHPExcel_DocumentProperties + */ + public function setCreated($pValue = null) { + if ($pValue === NULL) { + $pValue = time(); + } elseif (is_string($pValue)) { + if (is_numeric($pValue)) { + $pValue = intval($pValue); + } else { + $pValue = strtotime($pValue); + } + } - /** - * Keywords - * - * @var string - */ - private $_keywords = ''; + $this->_created = $pValue; + return $this; + } - /** - * Category - * - * @var string - */ - private $_category = ''; + /** + * Get Modified + * + * @return datetime + */ + public function getModified() { + return $this->_modified; + } - /** - * Manager - * - * @var string - */ - private $_manager = ''; + /** + * Set Modified + * + * @param datetime $pValue + * @return PHPExcel_DocumentProperties + */ + public function setModified($pValue = null) { + if ($pValue === NULL) { + $pValue = time(); + } elseif (is_string($pValue)) { + if (is_numeric($pValue)) { + $pValue = intval($pValue); + } else { + $pValue = strtotime($pValue); + } + } - /** - * Company - * - * @var string - */ - private $_company = 'Microsoft Corporation'; + $this->_modified = $pValue; + return $this; + } - /** - * Custom Properties - * - * @var string - */ - private $_customProperties = array(); + /** + * Get Title + * + * @return string + */ + public function getTitle() { + return $this->_title; + } + /** + * Set Title + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setTitle($pValue = '') { + $this->_title = $pValue; + return $this; + } - /** - * Create a new PHPExcel_DocumentProperties - */ - public function __construct() - { - // Initialise values - $this->_lastModifiedBy = $this->_creator; - $this->_created = time(); - $this->_modified = time(); - } + /** + * Get Description + * + * @return string + */ + public function getDescription() { + return $this->_description; + } - /** - * Get Creator - * - * @return string - */ - public function getCreator() { - return $this->_creator; - } + /** + * Set Description + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setDescription($pValue = '') { + $this->_description = $pValue; + return $this; + } - /** - * Set Creator - * - * @param string $pValue - * @return PHPExcel_DocumentProperties - */ - public function setCreator($pValue = '') { - $this->_creator = $pValue; - return $this; - } + /** + * Get Subject + * + * @return string + */ + public function getSubject() { + return $this->_subject; + } - /** - * Get Last Modified By - * - * @return string - */ - public function getLastModifiedBy() { - return $this->_lastModifiedBy; - } + /** + * Set Subject + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setSubject($pValue = '') { + $this->_subject = $pValue; + return $this; + } - /** - * Set Last Modified By - * - * @param string $pValue - * @return PHPExcel_DocumentProperties - */ - public function setLastModifiedBy($pValue = '') { - $this->_lastModifiedBy = $pValue; - return $this; - } + /** + * Get Keywords + * + * @return string + */ + public function getKeywords() { + return $this->_keywords; + } - /** - * Get Created - * - * @return datetime - */ - public function getCreated() { - return $this->_created; - } + /** + * Set Keywords + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setKeywords($pValue = '') { + $this->_keywords = $pValue; + return $this; + } - /** - * Set Created - * - * @param datetime $pValue - * @return PHPExcel_DocumentProperties - */ - public function setCreated($pValue = null) { - if ($pValue === NULL) { - $pValue = time(); - } elseif (is_string($pValue)) { - if (is_numeric($pValue)) { - $pValue = intval($pValue); - } else { - $pValue = strtotime($pValue); - } - } + /** + * Get Category + * + * @return string + */ + public function getCategory() { + return $this->_category; + } - $this->_created = $pValue; - return $this; - } + /** + * Set Category + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setCategory($pValue = '') { + $this->_category = $pValue; + return $this; + } - /** - * Get Modified - * - * @return datetime - */ - public function getModified() { - return $this->_modified; - } + /** + * Get Company + * + * @return string + */ + public function getCompany() { + return $this->_company; + } - /** - * Set Modified - * - * @param datetime $pValue - * @return PHPExcel_DocumentProperties - */ - public function setModified($pValue = null) { - if ($pValue === NULL) { - $pValue = time(); - } elseif (is_string($pValue)) { - if (is_numeric($pValue)) { - $pValue = intval($pValue); - } else { - $pValue = strtotime($pValue); - } - } + /** + * Set Company + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setCompany($pValue = '') { + $this->_company = $pValue; + return $this; + } - $this->_modified = $pValue; - return $this; - } + /** + * Get Manager + * + * @return string + */ + public function getManager() { + return $this->_manager; + } - /** - * Get Title - * - * @return string - */ - public function getTitle() { - return $this->_title; - } + /** + * Set Manager + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setManager($pValue = '') { + $this->_manager = $pValue; + return $this; + } - /** - * Set Title - * - * @param string $pValue - * @return PHPExcel_DocumentProperties - */ - public function setTitle($pValue = '') { - $this->_title = $pValue; - return $this; - } + /** + * Get a List of Custom Property Names + * + * @return array of string + */ + public function getCustomProperties() { + return array_keys($this->_customProperties); + } - /** - * Get Description - * - * @return string - */ - public function getDescription() { - return $this->_description; - } + /** + * Check if a Custom Property is defined + * + * @param string $propertyName + * @return boolean + */ + public function isCustomPropertySet($propertyName) { + return isset($this->_customProperties[$propertyName]); + } - /** - * Set Description - * - * @param string $pValue - * @return PHPExcel_DocumentProperties - */ - public function setDescription($pValue = '') { - $this->_description = $pValue; - return $this; - } + /** + * Get a Custom Property Value + * + * @param string $propertyName + * @return string + */ + public function getCustomPropertyValue($propertyName) { + if (isset($this->_customProperties[$propertyName])) { + return $this->_customProperties[$propertyName]['value']; + } - /** - * Get Subject - * - * @return string - */ - public function getSubject() { - return $this->_subject; - } + } - /** - * Set Subject - * - * @param string $pValue - * @return PHPExcel_DocumentProperties - */ - public function setSubject($pValue = '') { - $this->_subject = $pValue; - return $this; - } + /** + * Get a Custom Property Type + * + * @param string $propertyName + * @return string + */ + public function getCustomPropertyType($propertyName) { + if (isset($this->_customProperties[$propertyName])) { + return $this->_customProperties[$propertyName]['type']; + } - /** - * Get Keywords - * - * @return string - */ - public function getKeywords() { - return $this->_keywords; - } + } - /** - * Set Keywords - * - * @param string $pValue - * @return PHPExcel_DocumentProperties - */ - public function setKeywords($pValue = '') { - $this->_keywords = $pValue; - return $this; - } + /** + * Set a Custom Property + * + * @param string $propertyName + * @param mixed $propertyValue + * @param string $propertyType + * 'i' : Integer + * 'f' : Floating Point + * 's' : String + * 'd' : Date/Time + * 'b' : Boolean + * @return PHPExcel_DocumentProperties + */ + public function setCustomProperty($propertyName,$propertyValue='',$propertyType=NULL) { + if (($propertyType === NULL) || (!in_array($propertyType,array(self::PROPERTY_TYPE_INTEGER, + self::PROPERTY_TYPE_FLOAT, + self::PROPERTY_TYPE_STRING, + self::PROPERTY_TYPE_DATE, + self::PROPERTY_TYPE_BOOLEAN)))) { + if ($propertyValue === NULL) { + $propertyType = self::PROPERTY_TYPE_STRING; + } elseif (is_float($propertyValue)) { + $propertyType = self::PROPERTY_TYPE_FLOAT; + } elseif(is_int($propertyValue)) { + $propertyType = self::PROPERTY_TYPE_INTEGER; + } elseif (is_bool($propertyValue)) { + $propertyType = self::PROPERTY_TYPE_BOOLEAN; + } else { + $propertyType = self::PROPERTY_TYPE_STRING; + } + } - /** - * Get Category - * - * @return string - */ - public function getCategory() { - return $this->_category; - } + $this->_customProperties[$propertyName] = array('value' => $propertyValue, 'type' => $propertyType); + return $this; + } - /** - * Set Category - * - * @param string $pValue - * @return PHPExcel_DocumentProperties - */ - public function setCategory($pValue = '') { - $this->_category = $pValue; - return $this; - } + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } - /** - * Get Company - * - * @return string - */ - public function getCompany() { - return $this->_company; - } + public static function convertProperty($propertyValue,$propertyType) { + switch ($propertyType) { + case 'empty' : // Empty + return ''; + break; + case 'null' : // Null + return NULL; + break; + case 'i1' : // 1-Byte Signed Integer + case 'i2' : // 2-Byte Signed Integer + case 'i4' : // 4-Byte Signed Integer + case 'i8' : // 8-Byte Signed Integer + case 'int' : // Integer + return (int) $propertyValue; + break; + case 'ui1' : // 1-Byte Unsigned Integer + case 'ui2' : // 2-Byte Unsigned Integer + case 'ui4' : // 4-Byte Unsigned Integer + case 'ui8' : // 8-Byte Unsigned Integer + case 'uint' : // Unsigned Integer + return abs((int) $propertyValue); + break; + case 'r4' : // 4-Byte Real Number + case 'r8' : // 8-Byte Real Number + case 'decimal' : // Decimal + return (float) $propertyValue; + break; + case 'lpstr' : // LPSTR + case 'lpwstr' : // LPWSTR + case 'bstr' : // Basic String + return $propertyValue; + break; + case 'date' : // Date and Time + case 'filetime' : // File Time + return strtotime($propertyValue); + break; + case 'bool' : // Boolean + return ($propertyValue == 'true') ? True : False; + break; + case 'cy' : // Currency + case 'error' : // Error Status Code + case 'vector' : // Vector + case 'array' : // Array + case 'blob' : // Binary Blob + case 'oblob' : // Binary Blob Object + case 'stream' : // Binary Stream + case 'ostream' : // Binary Stream Object + case 'storage' : // Binary Storage + case 'ostorage' : // Binary Storage Object + case 'vstream' : // Binary Versioned Stream + case 'clsid' : // Class ID + case 'cf' : // Clipboard Data + return $propertyValue; + break; + } + return $propertyValue; + } - /** - * Set Company - * - * @param string $pValue - * @return PHPExcel_DocumentProperties - */ - public function setCompany($pValue = '') { - $this->_company = $pValue; - return $this; - } - - /** - * Get Manager - * - * @return string - */ - public function getManager() { - return $this->_manager; - } - - /** - * Set Manager - * - * @param string $pValue - * @return PHPExcel_DocumentProperties - */ - public function setManager($pValue = '') { - $this->_manager = $pValue; - return $this; - } - - /** - * Get a List of Custom Property Names - * - * @return array of string - */ - public function getCustomProperties() { - return array_keys($this->_customProperties); - } - - /** - * Check if a Custom Property is defined - * - * @param string $propertyName - * @return boolean - */ - public function isCustomPropertySet($propertyName) { - return isset($this->_customProperties[$propertyName]); - } - - /** - * Get a Custom Property Value - * - * @param string $propertyName - * @return string - */ - public function getCustomPropertyValue($propertyName) { - if (isset($this->_customProperties[$propertyName])) { - return $this->_customProperties[$propertyName]['value']; - } - - } - - /** - * Get a Custom Property Type - * - * @param string $propertyName - * @return string - */ - public function getCustomPropertyType($propertyName) { - if (isset($this->_customProperties[$propertyName])) { - return $this->_customProperties[$propertyName]['type']; - } - - } - - /** - * Set a Custom Property - * - * @param string $propertyName - * @param mixed $propertyValue - * @param string $propertyType - * 'i' : Integer - * 'f' : Floating Point - * 's' : String - * 'd' : Date/Time - * 'b' : Boolean - * @return PHPExcel_DocumentProperties - */ - public function setCustomProperty($propertyName,$propertyValue='',$propertyType=NULL) { - if (($propertyType === NULL) || (!in_array($propertyType,array(self::PROPERTY_TYPE_INTEGER, - self::PROPERTY_TYPE_FLOAT, - self::PROPERTY_TYPE_STRING, - self::PROPERTY_TYPE_DATE, - self::PROPERTY_TYPE_BOOLEAN)))) { - if ($propertyValue === NULL) { - $propertyType = self::PROPERTY_TYPE_STRING; - } elseif (is_float($propertyValue)) { - $propertyType = self::PROPERTY_TYPE_FLOAT; - } elseif(is_int($propertyValue)) { - $propertyType = self::PROPERTY_TYPE_INTEGER; - } elseif (is_bool($propertyValue)) { - $propertyType = self::PROPERTY_TYPE_BOOLEAN; - } else { - $propertyType = self::PROPERTY_TYPE_STRING; - } - } - - $this->_customProperties[$propertyName] = array('value' => $propertyValue, 'type' => $propertyType); - return $this; - } - - /** - * Implement PHP __clone to create a deep clone, not just a shallow copy. - */ - public function __clone() { - $vars = get_object_vars($this); - foreach ($vars as $key => $value) { - if (is_object($value)) { - $this->$key = clone $value; - } else { - $this->$key = $value; - } - } - } - - public static function convertProperty($propertyValue,$propertyType) { - switch ($propertyType) { - case 'empty' : // Empty - return ''; - break; - case 'null' : // Null - return NULL; - break; - case 'i1' : // 1-Byte Signed Integer - case 'i2' : // 2-Byte Signed Integer - case 'i4' : // 4-Byte Signed Integer - case 'i8' : // 8-Byte Signed Integer - case 'int' : // Integer - return (int) $propertyValue; - break; - case 'ui1' : // 1-Byte Unsigned Integer - case 'ui2' : // 2-Byte Unsigned Integer - case 'ui4' : // 4-Byte Unsigned Integer - case 'ui8' : // 8-Byte Unsigned Integer - case 'uint' : // Unsigned Integer - return abs((int) $propertyValue); - break; - case 'r4' : // 4-Byte Real Number - case 'r8' : // 8-Byte Real Number - case 'decimal' : // Decimal - return (float) $propertyValue; - break; - case 'lpstr' : // LPSTR - case 'lpwstr' : // LPWSTR - case 'bstr' : // Basic String - return $propertyValue; - break; - case 'date' : // Date and Time - case 'filetime' : // File Time - return strtotime($propertyValue); - break; - case 'bool' : // Boolean - return ($propertyValue == 'true') ? True : False; - break; - case 'cy' : // Currency - case 'error' : // Error Status Code - case 'vector' : // Vector - case 'array' : // Array - case 'blob' : // Binary Blob - case 'oblob' : // Binary Blob Object - case 'stream' : // Binary Stream - case 'ostream' : // Binary Stream Object - case 'storage' : // Binary Storage - case 'ostorage' : // Binary Storage Object - case 'vstream' : // Binary Versioned Stream - case 'clsid' : // Class ID - case 'cf' : // Clipboard Data - return $propertyValue; - break; - } - return $propertyValue; - } - - public static function convertPropertyType($propertyType) { - switch ($propertyType) { - case 'i1' : // 1-Byte Signed Integer - case 'i2' : // 2-Byte Signed Integer - case 'i4' : // 4-Byte Signed Integer - case 'i8' : // 8-Byte Signed Integer - case 'int' : // Integer - case 'ui1' : // 1-Byte Unsigned Integer - case 'ui2' : // 2-Byte Unsigned Integer - case 'ui4' : // 4-Byte Unsigned Integer - case 'ui8' : // 8-Byte Unsigned Integer - case 'uint' : // Unsigned Integer - return self::PROPERTY_TYPE_INTEGER; - break; - case 'r4' : // 4-Byte Real Number - case 'r8' : // 8-Byte Real Number - case 'decimal' : // Decimal - return self::PROPERTY_TYPE_FLOAT; - break; - case 'empty' : // Empty - case 'null' : // Null - case 'lpstr' : // LPSTR - case 'lpwstr' : // LPWSTR - case 'bstr' : // Basic String - return self::PROPERTY_TYPE_STRING; - break; - case 'date' : // Date and Time - case 'filetime' : // File Time - return self::PROPERTY_TYPE_DATE; - break; - case 'bool' : // Boolean - return self::PROPERTY_TYPE_BOOLEAN; - break; - case 'cy' : // Currency - case 'error' : // Error Status Code - case 'vector' : // Vector - case 'array' : // Array - case 'blob' : // Binary Blob - case 'oblob' : // Binary Blob Object - case 'stream' : // Binary Stream - case 'ostream' : // Binary Stream Object - case 'storage' : // Binary Storage - case 'ostorage' : // Binary Storage Object - case 'vstream' : // Binary Versioned Stream - case 'clsid' : // Class ID - case 'cf' : // Clipboard Data - return self::PROPERTY_TYPE_UNKNOWN; - break; - } - return self::PROPERTY_TYPE_UNKNOWN; - } + public static function convertPropertyType($propertyType) { + switch ($propertyType) { + case 'i1' : // 1-Byte Signed Integer + case 'i2' : // 2-Byte Signed Integer + case 'i4' : // 4-Byte Signed Integer + case 'i8' : // 8-Byte Signed Integer + case 'int' : // Integer + case 'ui1' : // 1-Byte Unsigned Integer + case 'ui2' : // 2-Byte Unsigned Integer + case 'ui4' : // 4-Byte Unsigned Integer + case 'ui8' : // 8-Byte Unsigned Integer + case 'uint' : // Unsigned Integer + return self::PROPERTY_TYPE_INTEGER; + break; + case 'r4' : // 4-Byte Real Number + case 'r8' : // 8-Byte Real Number + case 'decimal' : // Decimal + return self::PROPERTY_TYPE_FLOAT; + break; + case 'empty' : // Empty + case 'null' : // Null + case 'lpstr' : // LPSTR + case 'lpwstr' : // LPWSTR + case 'bstr' : // Basic String + return self::PROPERTY_TYPE_STRING; + break; + case 'date' : // Date and Time + case 'filetime' : // File Time + return self::PROPERTY_TYPE_DATE; + break; + case 'bool' : // Boolean + return self::PROPERTY_TYPE_BOOLEAN; + break; + case 'cy' : // Currency + case 'error' : // Error Status Code + case 'vector' : // Vector + case 'array' : // Array + case 'blob' : // Binary Blob + case 'oblob' : // Binary Blob Object + case 'stream' : // Binary Stream + case 'ostream' : // Binary Stream Object + case 'storage' : // Binary Storage + case 'ostorage' : // Binary Storage Object + case 'vstream' : // Binary Versioned Stream + case 'clsid' : // Class ID + case 'cf' : // Clipboard Data + return self::PROPERTY_TYPE_UNKNOWN; + break; + } + return self::PROPERTY_TYPE_UNKNOWN; + } } diff --git a/htdocs/includes/phpexcel/PHPExcel/DocumentSecurity.php b/htdocs/includes/phpexcel/PHPExcel/DocumentSecurity.php index 32bcb93035d..340504e8f18 100644 --- a/htdocs/includes/phpexcel/PHPExcel/DocumentSecurity.php +++ b/htdocs/includes/phpexcel/PHPExcel/DocumentSecurity.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_DocumentSecurity { diff --git a/htdocs/includes/phpexcel/PHPExcel/Exception.php b/htdocs/includes/phpexcel/PHPExcel/Exception.php index 454eaaa21b1..683e9099d8c 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Exception.php +++ b/htdocs/includes/phpexcel/PHPExcel/Exception.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.8.0, 2014-03-02 */ @@ -31,22 +31,22 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Exception extends Exception { - /** - * Error handler callback - * - * @param mixed $code - * @param mixed $string - * @param mixed $file - * @param mixed $line - * @param mixed $context - */ - public static function errorHandlerCallback($code, $string, $file, $line, $context) { - $e = new self($string, $code); - $e->line = $line; - $e->file = $file; - throw $e; - } + /** + * Error handler callback + * + * @param mixed $code + * @param mixed $string + * @param mixed $file + * @param mixed $line + * @param mixed $context + */ + public static function errorHandlerCallback($code, $string, $file, $line, $context) { + $e = new self($string, $code); + $e->line = $line; + $e->file = $file; + throw $e; + } } diff --git a/htdocs/includes/phpexcel/PHPExcel/HashTable.php b/htdocs/includes/phpexcel/PHPExcel/HashTable.php index ca15e6e7a79..7a9205e5b95 100644 --- a/htdocs/includes/phpexcel/PHPExcel/HashTable.php +++ b/htdocs/includes/phpexcel/PHPExcel/HashTable.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_HashTable { @@ -53,7 +53,7 @@ class PHPExcel_HashTable * Create a new PHPExcel_HashTable * * @param PHPExcel_IComparable[] $pSource Optional source array to create HashTable from - * @throws Exception + * @throws PHPExcel_Exception */ public function __construct($pSource = null) { @@ -67,14 +67,14 @@ class PHPExcel_HashTable * Add HashTable items from source * * @param PHPExcel_IComparable[] $pSource Source array to create HashTable from - * @throws Exception + * @throws PHPExcel_Exception */ public function addFromSource($pSource = null) { // Check if an array was passed if ($pSource == null) { return; } else if (!is_array($pSource)) { - throw new Exception('Invalid array parameter passed.'); + throw new PHPExcel_Exception('Invalid array parameter passed.'); } foreach ($pSource as $item) { @@ -86,7 +86,7 @@ class PHPExcel_HashTable * Add HashTable item * * @param PHPExcel_IComparable $pSource Item to add - * @throws Exception + * @throws PHPExcel_Exception */ public function add(PHPExcel_IComparable $pSource = null) { $hash = $pSource->getHashCode(); @@ -100,7 +100,7 @@ class PHPExcel_HashTable * Remove HashTable item * * @param PHPExcel_IComparable $pSource Item to remove - * @throws Exception + * @throws PHPExcel_Exception */ public function remove(PHPExcel_IComparable $pSource = null) { $hash = $pSource->getHashCode(); diff --git a/htdocs/includes/phpexcel/PHPExcel/IComparable.php b/htdocs/includes/phpexcel/PHPExcel/IComparable.php index 1c87f398cf4..6b1e18aa901 100644 --- a/htdocs/includes/phpexcel/PHPExcel/IComparable.php +++ b/htdocs/includes/phpexcel/PHPExcel/IComparable.php @@ -18,9 +18,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -29,7 +29,7 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ interface PHPExcel_IComparable { diff --git a/htdocs/includes/phpexcel/PHPExcel/IOFactory.php b/htdocs/includes/phpexcel/PHPExcel/IOFactory.php index eeeb2af93a1..69ec8b69531 100644 --- a/htdocs/includes/phpexcel/PHPExcel/IOFactory.php +++ b/htdocs/includes/phpexcel/PHPExcel/IOFactory.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -40,7 +40,7 @@ if (!defined('PHPEXCEL_ROOT')) { * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_IOFactory { @@ -96,13 +96,13 @@ class PHPExcel_IOFactory * @static * @access public * @param array $value - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public static function setSearchLocations($value) { if (is_array($value)) { self::$_searchLocations = $value; } else { - throw new Exception('Invalid parameter passed.'); + throw new PHPExcel_Reader_Exception('Invalid parameter passed.'); } } // function setSearchLocations() @@ -127,7 +127,7 @@ class PHPExcel_IOFactory * @param PHPExcel $phpExcel * @param string $writerType Example: Excel2007 * @return PHPExcel_Writer_IWriter - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public static function createWriter(PHPExcel $phpExcel, $writerType = '') { // Search type @@ -146,7 +146,7 @@ class PHPExcel_IOFactory } // Nothing found... - throw new Exception("No $searchType found for type $writerType"); + throw new PHPExcel_Reader_Exception("No $searchType found for type $writerType"); } // function createWriter() /** @@ -156,7 +156,7 @@ class PHPExcel_IOFactory * @access public * @param string $readerType Example: Excel2007 * @return PHPExcel_Reader_IReader - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public static function createReader($readerType = '') { // Search type @@ -175,7 +175,7 @@ class PHPExcel_IOFactory } // Nothing found... - throw new Exception("No $searchType found for type $readerType"); + throw new PHPExcel_Reader_Exception("No $searchType found for type $readerType"); } // function createReader() /** @@ -183,9 +183,9 @@ class PHPExcel_IOFactory * * @static * @access public - * @param string $pFileName The name of the spreadsheet file + * @param string $pFilename The name of the spreadsheet file * @return PHPExcel - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public static function load($pFilename) { $reader = self::createReaderForFile($pFilename); @@ -197,9 +197,9 @@ class PHPExcel_IOFactory * * @static * @access public - * @param string $pFileName The name of the spreadsheet file to identify + * @param string $pFilename The name of the spreadsheet file to identify * @return string - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public static function identify($pFilename) { $reader = self::createReaderForFile($pFilename); @@ -214,9 +214,9 @@ class PHPExcel_IOFactory * * @static * @access public - * @param string $pFileName The name of the spreadsheet file + * @param string $pFilename The name of the spreadsheet file * @return PHPExcel_Reader_IReader - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public static function createReaderForFile($pFilename) { @@ -283,6 +283,6 @@ class PHPExcel_IOFactory } } - throw new Exception('Unable to identify a reader for this file'); + throw new PHPExcel_Reader_Exception('Unable to identify a reader for this file'); } // function createReaderForFile() } diff --git a/htdocs/includes/phpexcel/PHPExcel/NamedRange.php b/htdocs/includes/phpexcel/PHPExcel/NamedRange.php index 3debd41a184..3ad5caabd46 100644 --- a/htdocs/includes/phpexcel/PHPExcel/NamedRange.php +++ b/htdocs/includes/phpexcel/PHPExcel/NamedRange.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_NamedRange { @@ -78,12 +78,13 @@ class PHPExcel_NamedRange * @param string $pRange * @param bool $pLocalOnly * @param PHPExcel_Worksheet|null $pScope Scope. Only applies when $pLocalOnly = true. Null for global scope. + * @throws PHPExcel_Exception */ public function __construct($pName = null, PHPExcel_Worksheet $pWorksheet, $pRange = 'A1', $pLocalOnly = false, $pScope = null) { // Validate data if (($pName === NULL) || ($pWorksheet === NULL) || ($pRange === NULL)) { - throw new Exception('Parameters can not be null.'); + throw new PHPExcel_Exception('Parameters can not be null.'); } // Set local members diff --git a/htdocs/includes/phpexcel/PHPExcel/Reader/Abstract.php b/htdocs/includes/phpexcel/PHPExcel/Reader/Abstract.php new file mode 100644 index 00000000000..0d5180c6e3e --- /dev/null +++ b/htdocs/includes/phpexcel/PHPExcel/Reader/Abstract.php @@ -0,0 +1,227 @@ +_readDataOnly; + } + + /** + * Set read data only + * Set to true, to advise the Reader only to read data values for cells, and to ignore any formatting information. + * Set to false (the default) to advise the Reader to read both data and formatting for cells. + * + * @param boolean $pValue + * + * @return PHPExcel_Reader_IReader + */ + public function setReadDataOnly($pValue = FALSE) { + $this->_readDataOnly = $pValue; + return $this; + } + + /** + * Read charts in workbook? + * If this is true, then the Reader will include any charts that exist in the workbook. + * Note that a ReadDataOnly value of false overrides, and charts won't be read regardless of the IncludeCharts value. + * If false (the default) it will ignore any charts defined in the workbook file. + * + * @return boolean + */ + public function getIncludeCharts() { + return $this->_includeCharts; + } + + /** + * Set read charts in workbook + * Set to true, to advise the Reader to include any charts that exist in the workbook. + * Note that a ReadDataOnly value of false overrides, and charts won't be read regardless of the IncludeCharts value. + * Set to false (the default) to discard charts. + * + * @param boolean $pValue + * + * @return PHPExcel_Reader_IReader + */ + public function setIncludeCharts($pValue = FALSE) { + $this->_includeCharts = (boolean) $pValue; + return $this; + } + + /** + * Get which sheets to load + * Returns either an array of worksheet names (the list of worksheets that should be loaded), or a null + * indicating that all worksheets in the workbook should be loaded. + * + * @return mixed + */ + public function getLoadSheetsOnly() + { + return $this->_loadSheetsOnly; + } + + /** + * Set which sheets to load + * + * @param mixed $value + * This should be either an array of worksheet names to be loaded, or a string containing a single worksheet name. + * If NULL, then it tells the Reader to read all worksheets in the workbook + * + * @return PHPExcel_Reader_IReader + */ + public function setLoadSheetsOnly($value = NULL) + { + $this->_loadSheetsOnly = is_array($value) ? + $value : array($value); + return $this; + } + + /** + * Set all sheets to load + * Tells the Reader to load all worksheets from the workbook. + * + * @return PHPExcel_Reader_IReader + */ + public function setLoadAllSheets() + { + $this->_loadSheetsOnly = NULL; + return $this; + } + + /** + * Read filter + * + * @return PHPExcel_Reader_IReadFilter + */ + public function getReadFilter() { + return $this->_readFilter; + } + + /** + * Set read filter + * + * @param PHPExcel_Reader_IReadFilter $pValue + * @return PHPExcel_Reader_IReader + */ + public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) { + $this->_readFilter = $pValue; + return $this; + } + + /** + * Open file for reading + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + * @return resource + */ + protected function _openFile($pFilename) + { + // Check if file exists + if (!file_exists($pFilename) || !is_readable($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + // Open file + $this->_fileHandle = fopen($pFilename, 'r'); + if ($this->_fileHandle === FALSE) { + throw new PHPExcel_Reader_Exception("Could not open file " . $pFilename . " for reading."); + } + } + + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFilename + * @return boolean + * @throws PHPExcel_Reader_Exception + */ + public function canRead($pFilename) + { + // Check if file exists + try { + $this->_openFile($pFilename); + } catch (Exception $e) { + return FALSE; + } + + $readable = $this->_isValidFormat(); + fclose ($this->_fileHandle); + return $readable; + } + +} diff --git a/htdocs/includes/phpexcel/PHPExcel/Reader/CSV.php b/htdocs/includes/phpexcel/PHPExcel/Reader/CSV.php index 2739e3c4136..8bf7b848195 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Reader/CSV.php +++ b/htdocs/includes/phpexcel/PHPExcel/Reader/CSV.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -40,9 +40,9 @@ if (!defined('PHPEXCEL_ROOT')) { * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader +class PHPExcel_Reader_CSV extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader { /** * Input encoding @@ -92,144 +92,104 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader */ private $_contiguous = false; - /** * Row counter for loading rows contiguously * - * @access private * @var int */ private $_contiguousRow = -1; - /** - * PHPExcel_Reader_IReadFilter instance - * - * @access private - * @var PHPExcel_Reader_IReadFilter - */ - private $_readFilter = null; - /** * Create a new PHPExcel_Reader_CSV */ public function __construct() { $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); - } // function __construct() - + } /** - * Can the current PHPExcel_Reader_IReader read the file? + * Validate that the current file is a CSV file * - * @access public - * @param string $pFileName * @return boolean - * @throws Exception */ - public function canRead($pFilename) + protected function _isValidFormat() { - // Check if file exists - if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } - - return true; - } // function canRead() - - - /** - * Read filter - * - * @access public - * @return PHPExcel_Reader_IReadFilter - */ - public function getReadFilter() { - return $this->_readFilter; - } // function getReadFilter() - - - /** - * Set read filter - * - * @access public - * @param PHPExcel_Reader_IReadFilter $pValue - */ - public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) { - $this->_readFilter = $pValue; - return $this; - } // function setReadFilter() - + return TRUE; + } /** * Set input encoding * - * @access public * @param string $pValue Input encoding */ public function setInputEncoding($pValue = 'UTF-8') { $this->_inputEncoding = $pValue; return $this; - } // function setInputEncoding() - + } /** * Get input encoding * - * @access public * @return string */ public function getInputEncoding() { return $this->_inputEncoding; - } // function getInputEncoding() - + } /** - * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) + * Move filepointer past any BOM marker * - * @access public - * @param string $pFilename - * @throws Exception */ - public function listWorksheetInfo($pFilename) + protected function _skipBOM() { - // Check if file exists - if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } + rewind($this->_fileHandle); - // Open file - $fileHandle = fopen($pFilename, 'r'); - if ($fileHandle === false) { - throw new Exception("Could not open file " . $pFilename . " for reading."); - } - - // Skip BOM, if any switch ($this->_inputEncoding) { case 'UTF-8': - fgets($fileHandle, 4) == "\xEF\xBB\xBF" ? - fseek($fileHandle, 3) : fseek($fileHandle, 0); + fgets($this->_fileHandle, 4) == "\xEF\xBB\xBF" ? + fseek($this->_fileHandle, 3) : fseek($this->_fileHandle, 0); break; case 'UTF-16LE': - fgets($fileHandle, 3) == "\xFF\xFE" ? - fseek($fileHandle, 2) : fseek($fileHandle, 0); + fgets($this->_fileHandle, 3) == "\xFF\xFE" ? + fseek($this->_fileHandle, 2) : fseek($this->_fileHandle, 0); break; case 'UTF-16BE': - fgets($fileHandle, 3) == "\xFE\xFF" ? - fseek($fileHandle, 2) : fseek($fileHandle, 0); + fgets($this->_fileHandle, 3) == "\xFE\xFF" ? + fseek($this->_fileHandle, 2) : fseek($this->_fileHandle, 0); break; case 'UTF-32LE': - fgets($fileHandle, 5) == "\xFF\xFE\x00\x00" ? - fseek($fileHandle, 4) : fseek($fileHandle, 0); + fgets($this->_fileHandle, 5) == "\xFF\xFE\x00\x00" ? + fseek($this->_fileHandle, 4) : fseek($this->_fileHandle, 0); break; case 'UTF-32BE': - fgets($fileHandle, 5) == "\x00\x00\xFE\xFF" ? - fseek($fileHandle, 4) : fseek($fileHandle, 0); + fgets($this->_fileHandle, 5) == "\x00\x00\xFE\xFF" ? + fseek($this->_fileHandle, 4) : fseek($this->_fileHandle, 0); break; default: break; } + } + + /** + * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetInfo($pFilename) + { + // Open file + $this->_openFile($pFilename); + if (!$this->_isValidFormat()) { + fclose ($this->_fileHandle); + throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); + } + $fileHandle = $this->_fileHandle; + + // Skip BOM, if any + $this->_skipBOM(); $escapeEnclosures = array( "\\" . $this->_enclosure, $this->_enclosure . $this->_enclosure ); @@ -255,14 +215,12 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader return $worksheetInfo; } - /** * Loads PHPExcel from file * - * @access public * @param string $pFilename * @return PHPExcel - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function load($pFilename) { @@ -271,65 +229,37 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader // Load into this instance return $this->loadIntoExisting($pFilename, $objPHPExcel); - } // function load() - + } /** * Loads PHPExcel from file into PHPExcel instance * - * @access public * @param string $pFilename * @param PHPExcel $objPHPExcel * @return PHPExcel - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) { - // Check if file exists - if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } - - // Create new PHPExcel - while ($objPHPExcel->getSheetCount() <= $this->_sheetIndex) { - $objPHPExcel->createSheet(); - } - $sheet = $objPHPExcel->setActiveSheetIndex( $this->_sheetIndex ); - $lineEnding = ini_get('auto_detect_line_endings'); ini_set('auto_detect_line_endings', true); // Open file - $fileHandle = fopen($pFilename, 'r'); - if ($fileHandle === false) { - throw new Exception("Could not open file $pFilename for reading."); + $this->_openFile($pFilename); + if (!$this->_isValidFormat()) { + fclose ($this->_fileHandle); + throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); } + $fileHandle = $this->_fileHandle; // Skip BOM, if any - switch ($this->_inputEncoding) { - case 'UTF-8': - fgets($fileHandle, 4) == "\xEF\xBB\xBF" ? - fseek($fileHandle, 3) : fseek($fileHandle, 0); - break; - case 'UTF-16LE': - fgets($fileHandle, 3) == "\xFF\xFE" ? - fseek($fileHandle, 2) : fseek($fileHandle, 0); - break; - case 'UTF-16BE': - fgets($fileHandle, 3) == "\xFE\xFF" ? - fseek($fileHandle, 2) : fseek($fileHandle, 0); - break; - case 'UTF-32LE': - fgets($fileHandle, 5) == "\xFF\xFE\x00\x00" ? - fseek($fileHandle, 4) : fseek($fileHandle, 0); - break; - case 'UTF-32BE': - fgets($fileHandle, 5) == "\x00\x00\xFE\xFF" ? - fseek($fileHandle, 4) : fseek($fileHandle, 0); - break; - default: - break; + $this->_skipBOM(); + + // Create new PHPExcel object + while ($objPHPExcel->getSheetCount() <= $this->_sheetIndex) { + $objPHPExcel->createSheet(); } + $sheet = $objPHPExcel->setActiveSheetIndex($this->_sheetIndex); $escapeEnclosures = array( "\\" . $this->_enclosure, $this->_enclosure . $this->_enclosure @@ -373,48 +303,40 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader // Return return $objPHPExcel; - } // function loadIntoExisting() - + } /** * Get delimiter * - * @access public * @return string */ public function getDelimiter() { return $this->_delimiter; - } // function getDelimiter() - + } /** * Set delimiter * - * @access public * @param string $pValue Delimiter, defaults to , * @return PHPExcel_Reader_CSV */ public function setDelimiter($pValue = ',') { $this->_delimiter = $pValue; return $this; - } // function setDelimiter() - + } /** * Get enclosure * - * @access public * @return string */ public function getEnclosure() { return $this->_enclosure; - } // function getEnclosure() - + } /** * Set enclosure * - * @access public * @param string $pValue Enclosure, defaults to " * @return PHPExcel_Reader_CSV */ @@ -424,82 +346,70 @@ class PHPExcel_Reader_CSV implements PHPExcel_Reader_IReader } $this->_enclosure = $pValue; return $this; - } // function setEnclosure() - + } /** * Get line ending * - * @access public * @return string */ public function getLineEnding() { return $this->_lineEnding; - } // function getLineEnding() - + } /** * Set line ending * - * @access public * @param string $pValue Line ending, defaults to OS line ending (PHP_EOL) * @return PHPExcel_Reader_CSV */ public function setLineEnding($pValue = PHP_EOL) { $this->_lineEnding = $pValue; return $this; - } // function setLineEnding() - + } /** * Get sheet index * - * @access public - * @return int + * @return integer */ public function getSheetIndex() { return $this->_sheetIndex; - } // function getSheetIndex() - + } /** * Set sheet index * - * @access public - * @param int $pValue Sheet index + * @param integer $pValue Sheet index * @return PHPExcel_Reader_CSV */ public function setSheetIndex($pValue = 0) { $this->_sheetIndex = $pValue; return $this; - } // function setSheetIndex() - + } /** * Set Contiguous * - * @access public - * @param string $pValue Input encoding + * @param boolean $contiguous */ - public function setContiguous($contiguous = false) + public function setContiguous($contiguous = FALSE) { - $this->_contiguous = (bool)$contiguous; + $this->_contiguous = (bool) $contiguous; if (!$contiguous) { - $this->_contiguousRow = -1; + $this->_contiguousRow = -1; } return $this; - } // function setInputEncoding() - + } /** * Get Contiguous * - * @access public * @return boolean */ public function getContiguous() { return $this->_contiguous; - } // function getSheetIndex() + } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Reader/DefaultReadFilter.php b/htdocs/includes/phpexcel/PHPExcel/Reader/DefaultReadFilter.php index 276b974eecc..228ed10877a 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Reader/DefaultReadFilter.php +++ b/htdocs/includes/phpexcel/PHPExcel/Reader/DefaultReadFilter.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -40,7 +40,7 @@ if (!defined('PHPEXCEL_ROOT')) { * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Reader_DefaultReadFilter implements PHPExcel_Reader_IReadFilter { diff --git a/htdocs/includes/phpexcel/PHPExcel/Reader/Excel2003XML.php b/htdocs/includes/phpexcel/PHPExcel/Reader/Excel2003XML.php index 33ffe6dcb3f..ce1f31d6772 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Reader/Excel2003XML.php +++ b/htdocs/includes/phpexcel/PHPExcel/Reader/Excel2003XML.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -40,24 +40,10 @@ if (!defined('PHPEXCEL_ROOT')) { * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Reader_Excel2003XML implements PHPExcel_Reader_IReader +class PHPExcel_Reader_Excel2003XML extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader { - /** - * Read data only? - * - * @var boolean - */ - private $_readDataOnly = false; - - /** - * Restict which sheets should be loaded? - * - * @var array - */ - private $_loadSheetsOnly = null; - /** * Formats * @@ -65,13 +51,6 @@ class PHPExcel_Reader_Excel2003XML implements PHPExcel_Reader_IReader */ private $_styles = array(); - /** - * PHPExcel_Reader_IReadFilter instance - * - * @var PHPExcel_Reader_IReadFilter - */ - private $_readFilter = null; - /** * Character set used in the file * @@ -88,93 +67,12 @@ class PHPExcel_Reader_Excel2003XML implements PHPExcel_Reader_IReader } - /** - * Read data only? - * - * @return boolean - */ - public function getReadDataOnly() { - return $this->_readDataOnly; - } - - - /** - * Set read data only - * - * @param boolean $pValue - * @return PHPExcel_Reader_Excel2003XML - */ - public function setReadDataOnly($pValue = false) { - $this->_readDataOnly = $pValue; - return $this; - } - - - /** - * Get which sheets to load - * - * @return mixed - */ - public function getLoadSheetsOnly() - { - return $this->_loadSheetsOnly; - } - - - /** - * Set which sheets to load - * - * @param mixed $value - * @return PHPExcel_Reader_Excel2003XML - */ - public function setLoadSheetsOnly($value = null) - { - $this->_loadSheetsOnly = is_array($value) ? - $value : array($value); - return $this; - } - - - /** - * Set all sheets to load - * - * @return PHPExcel_Reader_Excel2003XML - */ - public function setLoadAllSheets() - { - $this->_loadSheetsOnly = null; - return $this; - } - - - /** - * Read filter - * - * @return PHPExcel_Reader_IReadFilter - */ - public function getReadFilter() { - return $this->_readFilter; - } - - - /** - * Set read filter - * - * @param PHPExcel_Reader_IReadFilter $pValue - * @return PHPExcel_Reader_Excel2003XML - */ - public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) { - $this->_readFilter = $pValue; - return $this; - } - - /** * Can the current PHPExcel_Reader_IReader read the file? * - * @param string $pFileName + * @param string $pFilename * @return boolean - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function canRead($pFilename) { @@ -194,15 +92,13 @@ class PHPExcel_Reader_Excel2003XML implements PHPExcel_Reader_IReader '' ); - // Check if file exists - if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } - + // Open file + $this->_openFile($pFilename); + $fileHandle = $this->_fileHandle; + // Read sample data (first 2 KB will do) - $fh = fopen($pFilename, 'r'); - $data = fread($fh, 2048); - fclose($fh); + $data = fread($fileHandle, 2048); + fclose($fileHandle); $valid = true; foreach($signature as $match) { @@ -227,21 +123,21 @@ class PHPExcel_Reader_Excel2003XML implements PHPExcel_Reader_IReader * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object * * @param string $pFilename - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function listWorksheetNames($pFilename) { // Check if file exists if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); } if (!$this->canRead($pFilename)) { - throw new Exception($pFilename . " is an Invalid Spreadsheet file."); + throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); } $worksheetNames = array(); - $xml = simplexml_load_file($pFilename); + $xml = simplexml_load_file($pFilename, 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); $namespaces = $xml->getNamespaces(true); $xml_ss = $xml->children($namespaces['ss']); @@ -258,18 +154,18 @@ class PHPExcel_Reader_Excel2003XML implements PHPExcel_Reader_IReader * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) * * @param string $pFilename - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function listWorksheetInfo($pFilename) { // Check if file exists if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); } $worksheetInfo = array(); - $xml = simplexml_load_file($pFilename); + $xml = simplexml_load_file($pFilename, 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); $namespaces = $xml->getNamespaces(true); $worksheetID = 1; @@ -330,7 +226,7 @@ class PHPExcel_Reader_Excel2003XML implements PHPExcel_Reader_IReader * * @param string $pFilename * @return PHPExcel - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function load($pFilename) { @@ -392,7 +288,7 @@ class PHPExcel_Reader_Excel2003XML implements PHPExcel_Reader_IReader * @param string $pFilename * @param PHPExcel $objPHPExcel * @return PHPExcel - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) { @@ -427,14 +323,14 @@ class PHPExcel_Reader_Excel2003XML implements PHPExcel_Reader_IReader // Check if file exists if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); } if (!$this->canRead($pFilename)) { - throw new Exception($pFilename . " is an Invalid Spreadsheet file."); + throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); } - $xml = simplexml_load_file($pFilename); + $xml = simplexml_load_file($pFilename, 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); $namespaces = $xml->getNamespaces(true); $docProps = $objPHPExcel->getProperties(); diff --git a/htdocs/includes/phpexcel/PHPExcel/Reader/Excel2007.php b/htdocs/includes/phpexcel/PHPExcel/Reader/Excel2007.php index fbb9158ebd3..d8344ac7a29 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Reader/Excel2007.php +++ b/htdocs/includes/phpexcel/PHPExcel/Reader/Excel2007.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -40,42 +40,10 @@ if (!defined('PHPEXCEL_ROOT')) { * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader +class PHPExcel_Reader_Excel2007 extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader { - /** - * Read data only? - * Identifies whether the Reader should only read data values for cells, and ignore any formatting information; - * or whether it should read both data and formatting - * - * @var boolean - */ - private $_readDataOnly = FALSE; - - /** - * Read charts that are defined in the workbook? - * Identifies whether the Reader should read the definitions for any charts that exist in the workbook; - * - * @var boolean - */ - private $_includeCharts = FALSE; - - /** - * Restrict which sheets should be loaded? - * This property holds an array of worksheet names to be loaded. If null, then all worksheets will be loaded. - * - * @var array of string - */ - private $_loadSheetsOnly = NULL; - - /** - * PHPExcel_Reader_IReadFilter instance - * - * @var PHPExcel_Reader_IReadFilter - */ - private $_readFilter = NULL; - /** * PHPExcel_ReferenceHelper instance * @@ -100,152 +68,33 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } - /** - * Read data only? - * If this is true, then the Reader will only read data values for cells, it will not read any formatting information. - * If false (the default) it will read data and formatting. - * - * @return boolean - */ - public function getReadDataOnly() { - return $this->_readDataOnly; - } - - - /** - * Set read data only - * Set to true, to advise the Reader only to read data values for cells, and to ignore any formatting information. - * Set to false (the default) to advise the Reader to read both data and formatting for cells. - * - * @param boolean $pValue - * - * @return PHPExcel_Reader_Excel2007 - */ - public function setReadDataOnly($pValue = FALSE) { - $this->_readDataOnly = $pValue; - return $this; - } - - - /** - * Read charts in workbook? - * If this is true, then the Reader will include any charts that exist in the workbook. - * Note that a ReadDataOnly value of false overrides, and charts won't be read regardless of the IncludeCharts value. - * If false (the default) it will ignore any charts defined in the workbook file. - * - * @return boolean - */ - public function getIncludeCharts() { - return $this->_includeCharts; - } - - - /** - * Set read charts in workbook - * Set to true, to advise the Reader to include any charts that exist in the workbook. - * Note that a ReadDataOnly value of false overrides, and charts won't be read regardless of the IncludeCharts value. - * Set to false (the default) to discard charts. - * - * @param boolean $pValue - * - * @return PHPExcel_Reader_Excel2007 - */ - public function setIncludeCharts($pValue = FALSE) { - $this->_includeCharts = (boolean) $pValue; - return $this; - } - - - /** - * Get which sheets to load - * Returns either an array of worksheet names (the list of worksheets that should be loaded), or a null - * indicating that all worksheets in the workbook should be loaded. - * - * @return mixed - */ - public function getLoadSheetsOnly() - { - return $this->_loadSheetsOnly; - } - - - /** - * Set which sheets to load - * - * @param mixed $value - * This should be either an array of worksheet names to be loaded, or a string containing a single worksheet name. - * If NULL, then it tells the Reader to read all worksheets in the workbook - * - * @return PHPExcel_Reader_Excel2007 - */ - public function setLoadSheetsOnly($value = NULL) - { - $this->_loadSheetsOnly = is_array($value) ? - $value : array($value); - return $this; - } - - - /** - * Set all sheets to load - * Tells the Reader to load all worksheets from the workbook. - * - * @return PHPExcel_Reader_Excel2007 - */ - public function setLoadAllSheets() - { - $this->_loadSheetsOnly = NULL; - return $this; - } - - - /** - * Read filter - * - * @return PHPExcel_Reader_IReadFilter - */ - public function getReadFilter() { - return $this->_readFilter; - } - - - /** - * Set read filter - * - * @param PHPExcel_Reader_IReadFilter $pValue - * @return PHPExcel_Reader_Excel2007 - */ - public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) { - $this->_readFilter = $pValue; - return $this; - } - - /** * Can the current PHPExcel_Reader_IReader read the file? * - * @param string $pFileName + * @param string $pFilename * @return boolean - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function canRead($pFilename) { // Check if file exists if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); } + $zipClass = PHPExcel_Settings::getZipClass(); + // Check if zip class exists - if (!class_exists('ZipArchive',FALSE)) { - throw new Exception("ZipArchive library is not enabled"); - } +// if (!class_exists($zipClass, FALSE)) { +// throw new PHPExcel_Reader_Exception($zipClass . " library is not enabled"); +// } $xl = false; // Load file - $zip = new ZipArchive; + $zip = new $zipClass; if ($zip->open($pFilename) === true) { // check if it is an OOXML archive - $rels = simplexml_load_string($this->_getFromZipArchive($zip, "_rels/.rels")); + $rels = simplexml_load_string($this->_getFromZipArchive($zip, "_rels/.rels"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); if ($rels !== false) { foreach ($rels->Relationship as $rel) { switch ($rel["Type"]) { @@ -265,29 +114,77 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } + /** + * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetNames($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $worksheetNames = array(); + + $zipClass = PHPExcel_Settings::getZipClass(); + + $zip = new $zipClass; + $zip->open($pFilename); + + // The files we're looking at here are small enough that simpleXML is more efficient than XMLReader + $rels = simplexml_load_string( + $this->_getFromZipArchive($zip, "_rels/.rels", 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()) + ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + foreach ($rels->Relationship as $rel) { + switch ($rel["Type"]) { + case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument": + $xmlWorkbook = simplexml_load_string( + $this->_getFromZipArchive($zip, "{$rel['Target']}", 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()) + ); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + + if ($xmlWorkbook->sheets) { + foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { + // Check if sheet should be skipped + $worksheetNames[] = (string) $eleSheet["name"]; + } + } + } + } + + $zip->close(); + + return $worksheetNames; + } + + /** * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) * * @param string $pFilename - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function listWorksheetInfo($pFilename) { // Check if file exists if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); } $worksheetInfo = array(); - $zip = new ZipArchive; + $zipClass = PHPExcel_Settings::getZipClass(); + + $zip = new $zipClass; $zip->open($pFilename); - $rels = simplexml_load_string($this->_getFromZipArchive($zip, "_rels/.rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $rels = simplexml_load_string($this->_getFromZipArchive($zip, "_rels/.rels"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); foreach ($rels->Relationship as $rel) { if ($rel["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument") { $dir = dirname($rel["Target"]); - $relsWorkbook = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/_rels/" . basename($rel["Target"]) . ".rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $relsWorkbook = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/_rels/" . basename($rel["Target"]) . ".rels"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); $relsWorkbook->registerXPathNamespace("rel", "http://schemas.openxmlformats.org/package/2006/relationships"); $worksheets = array(); @@ -297,36 +194,40 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } } - $xmlWorkbook = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + $xmlWorkbook = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); if ($xmlWorkbook->sheets) { $dir = dirname($rel["Target"]); foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { - $tmpInfo = array(); - $tmpInfo['worksheetName'] = (string) $eleSheet["name"]; - $tmpInfo['lastColumnLetter'] = 'A'; - $tmpInfo['lastColumnIndex'] = 0; - $tmpInfo['totalRows'] = 0; - $tmpInfo['totalColumns'] = 0; + $tmpInfo = array( + 'worksheetName' => (string) $eleSheet["name"], + 'lastColumnLetter' => 'A', + 'lastColumnIndex' => 0, + 'totalRows' => 0, + 'totalColumns' => 0, + ); $fileWorksheet = $worksheets[(string) self::array_item($eleSheet->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; - $xmlSheet = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/$fileWorksheet")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - if ($xmlSheet && $xmlSheet->sheetData && $xmlSheet->sheetData->row) { - foreach ($xmlSheet->sheetData->row as $row) { - foreach ($row->c as $c) { - $r = (string) $c["r"]; - $coordinates = PHPExcel_Cell::coordinateFromString($r); - $rowIndex = $coordinates[1]; - $columnIndex = PHPExcel_Cell::columnIndexFromString($coordinates[0]) - 1; + $xml = new XMLReader(); + $res = $xml->open('zip://'.PHPExcel_Shared_File::realpath($pFilename).'#'."$dir/$fileWorksheet", null, PHPExcel_Settings::getLibXmlLoaderOptions()); + $xml->setParserProperty(2,true); - $tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex); - $tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex); - } + $currCells = 0; + while ($xml->read()) { + if ($xml->name == 'row' && $xml->nodeType == XMLReader::ELEMENT) { + $row = $xml->getAttribute('r'); + $tmpInfo['totalRows'] = $row; + $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'],$currCells); + $currCells = 0; + } elseif ($xml->name == 'c' && $xml->nodeType == XMLReader::ELEMENT) { + $currCells++; } } + $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'],$currCells); + $xml->close(); + $tmpInfo['lastColumnIndex'] = $tmpInfo['totalColumns'] - 1; $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); - $tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1; $worksheetInfo[] = $tmpInfo; } @@ -341,7 +242,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader private static function _castToBool($c) { -// echo 'Initial Cast to Boolean
'; +// echo 'Initial Cast to Boolean', PHP_EOL; $value = isset($c->v) ? (string) $c->v : NULL; if ($value == '0') { return FALSE; @@ -355,48 +256,46 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader private static function _castToError($c) { -// echo 'Initial Cast to Error
'; +// echo 'Initial Cast to Error', PHP_EOL; return isset($c->v) ? (string) $c->v : NULL; } // function _castToError() private static function _castToString($c) { -// echo 'Initial Cast to String
'; +// echo 'Initial Cast to String, PHP_EOL; return isset($c->v) ? (string) $c->v : NULL; } // function _castToString() private function _castToFormula($c,$r,&$cellDataType,&$value,&$calculatedValue,&$sharedFormulas,$castBaseType) { -// echo 'Formula
'; -// echo '$c->f is '.$c->f.'
'; +// echo 'Formula', PHP_EOL; +// echo '$c->f is ', $c->f, PHP_EOL; $cellDataType = 'f'; $value = "={$c->f}"; $calculatedValue = self::$castBaseType($c); // Shared formula? if (isset($c->f['t']) && strtolower((string)$c->f['t']) == 'shared') { -// echo 'SHARED FORMULA
'; +// echo 'SHARED FORMULA', PHP_EOL; $instance = (string)$c->f['si']; -// echo 'Instance ID = '.$instance.'
'; +// echo 'Instance ID = ', $instance, PHP_EOL; // -// echo 'Shared Formula Array:
';
+//			echo 'Shared Formula Array:', PHP_EOL;
 //			print_r($sharedFormulas);
-//			echo '
'; if (!isset($sharedFormulas[(string)$c->f['si']])) { -// echo 'SETTING NEW SHARED FORMULA
'; -// echo 'Master is '.$r.'
'; -// echo 'Formula is '.$value.'
'; +// echo 'SETTING NEW SHARED FORMULA', PHP_EOL; +// echo 'Master is ', $r, PHP_EOL; +// echo 'Formula is ', $value, PHP_EOL; $sharedFormulas[$instance] = array( 'master' => $r, 'formula' => $value ); -// echo 'New Shared Formula Array:
';
+//				echo 'New Shared Formula Array:', PHP_EOL;
 //				print_r($sharedFormulas);
-//				echo '
'; } else { -// echo 'GETTING SHARED FORMULA
'; -// echo 'Master is '.$sharedFormulas[$instance]['master'].'
'; -// echo 'Formula is '.$sharedFormulas[$instance]['formula'].'
'; +// echo 'GETTING SHARED FORMULA', PHP_EOL; +// echo 'Master is ', $sharedFormulas[$instance]['master'], PHP_EOL; +// echo 'Formula is ', $sharedFormulas[$instance]['formula'], PHP_EOL; $master = PHPExcel_Cell::coordinateFromString($sharedFormulas[$instance]['master']); $current = PHPExcel_Cell::coordinateFromString($r); @@ -409,13 +308,13 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $difference[0], $difference[1] ); -// echo 'Adjusted Formula is '.$value.'
'; +// echo 'Adjusted Formula is ', $value, PHP_EOL; } } } - public function _getFromZipArchive(ZipArchive $archive, $fileName = '') + public function _getFromZipArchive($archive, $fileName = '') { // Root-relative paths if (strpos($fileName, '//') !== false) @@ -435,56 +334,17 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } - /** - * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object - * - * @param string $pFilename - * @throws Exception - */ - public function listWorksheetNames($pFilename) - { - // Check if file exists - if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } - - $worksheetNames = array(); - - $zip = new ZipArchive; - $zip->open($pFilename); - - $rels = simplexml_load_string($this->_getFromZipArchive($zip, "_rels/.rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships"); - foreach ($rels->Relationship as $rel) { - switch ($rel["Type"]) { - case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument": - $xmlWorkbook = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - - if ($xmlWorkbook->sheets) { - foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { - // Check if sheet should be skipped - $worksheetNames[] = (string) $eleSheet["name"]; - } - } - } - } - - $zip->close(); - - return $worksheetNames; - } - - /** * Loads PHPExcel from file * * @param string $pFilename - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function load($pFilename) { // Check if file exists if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); } // Initialisations @@ -494,18 +354,21 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $excel->removeCellStyleXfByIndex(0); // remove the default style $excel->removeCellXfByIndex(0); // remove the default style } - $zip = new ZipArchive; + + $zipClass = PHPExcel_Settings::getZipClass(); + + $zip = new $zipClass; $zip->open($pFilename); // Read the theme first, because we need the colour scheme when reading the styles - $wbRels = simplexml_load_string($this->_getFromZipArchive($zip, "xl/_rels/workbook.xml.rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $wbRels = simplexml_load_string($this->_getFromZipArchive($zip, "xl/_rels/workbook.xml.rels"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); foreach ($wbRels->Relationship as $rel) { switch ($rel["Type"]) { case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme": $themeOrderArray = array('lt1','dk1','lt2','dk2'); $themeOrderAdditional = count($themeOrderArray); - $xmlTheme = simplexml_load_string($this->_getFromZipArchive($zip, "xl/{$rel['Target']}")); + $xmlTheme = simplexml_load_string($this->_getFromZipArchive($zip, "xl/{$rel['Target']}"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); if (is_object($xmlTheme)) { $xmlThemeName = $xmlTheme->attributes(); $xmlTheme = $xmlTheme->children("http://schemas.openxmlformats.org/drawingml/2006/main"); @@ -535,11 +398,11 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } } - $rels = simplexml_load_string($this->_getFromZipArchive($zip, "_rels/.rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $rels = simplexml_load_string($this->_getFromZipArchive($zip, "_rels/.rels"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); foreach ($rels->Relationship as $rel) { switch ($rel["Type"]) { case "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties": - $xmlCore = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}")); + $xmlCore = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); if (is_object($xmlCore)) { $xmlCore->registerXPathNamespace("dc", "http://purl.org/dc/elements/1.1/"); $xmlCore->registerXPathNamespace("dcterms", "http://purl.org/dc/terms/"); @@ -558,7 +421,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader break; case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties": - $xmlCore = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}")); + $xmlCore = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); if (is_object($xmlCore)) { $docProps = $excel->getProperties(); if (isset($xmlCore->Company)) @@ -569,7 +432,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader break; case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties": - $xmlCore = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}")); + $xmlCore = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); if (is_object($xmlCore)) { $docProps = $excel->getProperties(); foreach ($xmlCore as $xmlProperty) { @@ -586,15 +449,21 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } } break; - + //Ribbon + case "http://schemas.microsoft.com/office/2006/relationships/ui/extensibility": + $customUI = $rel['Target']; + if(!is_null($customUI)){ + $this->_readRibbon($excel, $customUI, $zip); + } + break; case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument": $dir = dirname($rel["Target"]); - $relsWorkbook = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/_rels/" . basename($rel["Target"]) . ".rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $relsWorkbook = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/_rels/" . basename($rel["Target"]) . ".rels"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); $relsWorkbook->registerXPathNamespace("rel", "http://schemas.openxmlformats.org/package/2006/relationships"); $sharedStrings = array(); $xpath = self::array_item($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings']")); - $xmlStrings = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/$xpath[Target]")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + $xmlStrings = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/$xpath[Target]"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); if (isset($xmlStrings) && isset($xmlStrings->si)) { foreach ($xmlStrings->si as $val) { if (isset($val->t)) { @@ -606,16 +475,34 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } $worksheets = array(); + $macros = $customUI = NULL; foreach ($relsWorkbook->Relationship as $ele) { - if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet") { + switch($ele['Type']){ + case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet": $worksheets[(string) $ele["Id"]] = $ele["Target"]; + break; + // a vbaProject ? (: some macros) + case "http://schemas.microsoft.com/office/2006/relationships/vbaProject": + $macros = $ele["Target"]; + break; } } + if(!is_null($macros)){ + $macrosCode = $this->_getFromZipArchive($zip, 'xl/vbaProject.bin');//vbaProject.bin always in 'xl' dir and always named vbaProject.bin + if($macrosCode !== false){ + $excel->setMacrosCode($macrosCode); + $excel->setHasMacros(true); + //short-circuit : not reading vbaProject.bin.rel to get Signature =>allways vbaProjectSignature.bin in 'xl' dir + $Certificate = $this->_getFromZipArchive($zip, 'xl/vbaProjectSignature.bin'); + if($Certificate !== false) + $excel->setMacrosCertificate($Certificate); + } + } $styles = array(); $cellStyles = array(); $xpath = self::array_item($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles']")); - $xmlStyles = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/$xpath[Target]")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + $xmlStyles = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/$xpath[Target]"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); $numFmts = null; if ($xmlStyles && $xmlStyles->numFmts[0]) { $numFmts = $xmlStyles->numFmts[0]; @@ -640,6 +527,10 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $numFmt = PHPExcel_Style_NumberFormat::builtInFormatCode((int)$xf["numFmtId"]); } } + $quotePrefix = false; + if (isset($xf["quotePrefix"])) { + $quotePrefix = (boolean) $xf["quotePrefix"]; + } //$numFmt = str_replace('mm', 'i', $numFmt); //$numFmt = str_replace('h', 'H', $numFmt); @@ -650,6 +541,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader "border" => $xmlStyles->borders->border[intval($xf["borderId"])], "alignment" => $xf->alignment, "protection" => $xf->protection, + "quotePrefix" => $quotePrefix, ); $styles[] = $style; @@ -677,6 +569,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader "border" => $xmlStyles->borders->border[intval($xf["borderId"])], "alignment" => $xf->alignment, "protection" => $xf->protection, + "quotePrefix" => $quotePrefix, ); $cellStyles[] = $cellStyle; @@ -713,14 +606,13 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } } - $xmlWorkbook = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + $xmlWorkbook = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); // Set base date if ($xmlWorkbook->workbookPr) { PHPExcel_Shared_Date::setExcelCalendar(PHPExcel_Shared_Date::CALENDAR_WINDOWS_1900); if (isset($xmlWorkbook->workbookPr['date1904'])) { - $date1904 = (string)$xmlWorkbook->workbookPr['date1904']; - if ($date1904 == "true" || $date1904 == "1") { + if (self::boolean((string) $xmlWorkbook->workbookPr['date1904'])) { PHPExcel_Shared_Date::setExcelCalendar(PHPExcel_Shared_Date::CALENDAR_MAC_1904); } } @@ -757,7 +649,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader // reverse $docSheet->setTitle((string) $eleSheet["name"],false); $fileWorksheet = $worksheets[(string) self::array_item($eleSheet->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; - $xmlSheet = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/$fileWorksheet")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + $xmlSheet = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/$fileWorksheet"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); $sharedFormulas = array(); @@ -779,15 +671,15 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } if (isset($xmlSheet->sheetViews->sheetView['showGridLines'])) { - $docSheet->setShowGridLines((string)$xmlSheet->sheetViews->sheetView['showGridLines'] ? true : false); + $docSheet->setShowGridLines(self::boolean((string)$xmlSheet->sheetViews->sheetView['showGridLines'])); } if (isset($xmlSheet->sheetViews->sheetView['showRowColHeaders'])) { - $docSheet->setShowRowColHeaders((string)$xmlSheet->sheetViews->sheetView['showRowColHeaders'] ? true : false); + $docSheet->setShowRowColHeaders(self::boolean((string)$xmlSheet->sheetViews->sheetView['showRowColHeaders'])); } if (isset($xmlSheet->sheetViews->sheetView['rightToLeft'])) { - $docSheet->setRightToLeft((string)$xmlSheet->sheetViews->sheetView['rightToLeft'] ? true : false); + $docSheet->setRightToLeft(self::boolean((string)$xmlSheet->sheetViews->sheetView['rightToLeft'])); } if (isset($xmlSheet->sheetViews->sheetView->pane)) { @@ -825,31 +717,38 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $docSheet->getTabColor()->setARGB( (string)$xmlSheet->sheetPr->tabColor['rgb'] ); } } - + if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr['codeName'])) { + $docSheet->setCodeName((string) $xmlSheet->sheetPr['codeName']); + } if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->outlinePr)) { - if (isset($xmlSheet->sheetPr->outlinePr['summaryRight']) && $xmlSheet->sheetPr->outlinePr['summaryRight'] == false) { - $docSheet->setShowSummaryRight(false); + if (isset($xmlSheet->sheetPr->outlinePr['summaryRight']) && + !self::boolean((string) $xmlSheet->sheetPr->outlinePr['summaryRight'])) { + $docSheet->setShowSummaryRight(FALSE); } else { - $docSheet->setShowSummaryRight(true); + $docSheet->setShowSummaryRight(TRUE); } - if (isset($xmlSheet->sheetPr->outlinePr['summaryBelow']) && $xmlSheet->sheetPr->outlinePr['summaryBelow'] == false) { - $docSheet->setShowSummaryBelow(false); + if (isset($xmlSheet->sheetPr->outlinePr['summaryBelow']) && + !self::boolean((string) $xmlSheet->sheetPr->outlinePr['summaryBelow'])) { + $docSheet->setShowSummaryBelow(FALSE); } else { - $docSheet->setShowSummaryBelow(true); + $docSheet->setShowSummaryBelow(TRUE); } } if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->pageSetUpPr)) { - if (isset($xmlSheet->sheetPr->pageSetUpPr['fitToPage']) && $xmlSheet->sheetPr->pageSetUpPr['fitToPage'] == false) { - $docSheet->getPageSetup()->setFitToPage(false); + if (isset($xmlSheet->sheetPr->pageSetUpPr['fitToPage']) && + !self::boolean((string) $xmlSheet->sheetPr->pageSetUpPr['fitToPage'])) { + $docSheet->getPageSetup()->setFitToPage(FALSE); } else { - $docSheet->getPageSetup()->setFitToPage(true); + $docSheet->getPageSetup()->setFitToPage(TRUE); } } if (isset($xmlSheet->sheetFormatPr)) { - if (isset($xmlSheet->sheetFormatPr['customHeight']) && ((string)$xmlSheet->sheetFormatPr['customHeight'] == '1' || strtolower((string)$xmlSheet->sheetFormatPr['customHeight']) == 'true') && isset($xmlSheet->sheetFormatPr['defaultRowHeight'])) { + if (isset($xmlSheet->sheetFormatPr['customHeight']) && + self::boolean((string) $xmlSheet->sheetFormatPr['customHeight']) && + isset($xmlSheet->sheetFormatPr['defaultRowHeight'])) { $docSheet->getDefaultRowDimension()->setRowHeight( (float)$xmlSheet->sheetFormatPr['defaultRowHeight'] ); } if (isset($xmlSheet->sheetFormatPr['defaultColWidth'])) { @@ -863,18 +762,19 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader if (isset($xmlSheet->cols) && !$this->_readDataOnly) { foreach ($xmlSheet->cols->col as $col) { - for ($i = intval($col["min"]) - 1; $i < intval($col["max"]); ++$i) { + for ($i = intval($col["min"]) - 1; $i < intval($col["max"]); ++$i) { if ($col["style"] && !$this->_readDataOnly) { $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setXfIndex(intval($col["style"])); } - if ($col["bestFit"]) { - //$docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setAutoSize(true); + if (self::boolean($col["bestFit"])) { + //$docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setAutoSize(TRUE); } - if ($col["hidden"]) { - $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setVisible(false); + if (self::boolean($col["hidden"])) { + // echo PHPExcel_Cell::stringFromColumnIndex($i),': HIDDEN COLUMN',PHP_EOL; + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setVisible(FALSE); } - if ($col["collapsed"]) { - $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setCollapsed(true); + if (self::boolean($col["collapsed"])) { + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setCollapsed(TRUE); } if ($col["outlineLevel"] > 0) { $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setOutlineLevel(intval($col["outlineLevel"])); @@ -889,19 +789,19 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } if (isset($xmlSheet->printOptions) && !$this->_readDataOnly) { - if ($xmlSheet->printOptions['gridLinesSet'] == 'true' && $xmlSheet->printOptions['gridLinesSet'] == '1') { - $docSheet->setShowGridlines(true); + if (self::boolean((string) $xmlSheet->printOptions['gridLinesSet'])) { + $docSheet->setShowGridlines(TRUE); } - if ($xmlSheet->printOptions['gridLines'] == 'true' || $xmlSheet->printOptions['gridLines'] == '1') { - $docSheet->setPrintGridlines(true); + if (self::boolean((string) $xmlSheet->printOptions['gridLines'])) { + $docSheet->setPrintGridlines(TRUE); } - if ($xmlSheet->printOptions['horizontalCentered']) { - $docSheet->getPageSetup()->setHorizontalCentered(true); + if (self::boolean((string) $xmlSheet->printOptions['horizontalCentered'])) { + $docSheet->getPageSetup()->setHorizontalCentered(TRUE); } - if ($xmlSheet->printOptions['verticalCentered']) { - $docSheet->getPageSetup()->setVerticalCentered(true); + if (self::boolean((string) $xmlSheet->printOptions['verticalCentered'])) { + $docSheet->getPageSetup()->setVerticalCentered(TRUE); } } @@ -910,11 +810,11 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader if ($row["ht"] && !$this->_readDataOnly) { $docSheet->getRowDimension(intval($row["r"]))->setRowHeight(floatval($row["ht"])); } - if ($row["hidden"] && !$this->_readDataOnly) { - $docSheet->getRowDimension(intval($row["r"]))->setVisible(false); + if (self::boolean($row["hidden"]) && !$this->_readDataOnly) { + $docSheet->getRowDimension(intval($row["r"]))->setVisible(FALSE); } - if ($row["collapsed"]) { - $docSheet->getRowDimension(intval($row["r"]))->setCollapsed(true); + if (self::boolean($row["collapsed"])) { + $docSheet->getRowDimension(intval($row["r"]))->setCollapsed(TRUE); } if ($row["outlineLevel"] > 0) { $docSheet->getRowDimension(intval($row["r"]))->setOutlineLevel(intval($row["outlineLevel"])); @@ -938,15 +838,15 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } } - // echo 'Reading cell '.$coordinates[0].$coordinates[1].'
'; + // echo 'Reading cell ', $coordinates[0], $coordinates[1], PHP_EOL; // print_r($c); - // echo '
'; - // echo 'Cell Data Type is '.$cellDataType.': '; + // echo PHP_EOL; + // echo 'Cell Data Type is ', $cellDataType, ': '; // // Read cell! switch ($cellDataType) { case "s": - // echo 'String
'; + // echo 'String', PHP_EOL; if ((string)$c->v != '') { $value = $sharedStrings[intval($c->v)]; @@ -959,7 +859,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader break; case "b": - // echo 'Boolean
'; + // echo 'Boolean', PHP_EOL; if (!isset($c->f)) { $value = self::_castToBool($c); } else { @@ -970,41 +870,41 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $att = $c->f; $docSheet->getCell($r)->setFormulaAttributes($att); } - // echo '$calculatedValue = '.$calculatedValue.'
'; + // echo '$calculatedValue = ', $calculatedValue, PHP_EOL; } break; case "inlineStr": - // echo 'Inline String
'; + // echo 'Inline String', PHP_EOL; $value = $this->_parseRichText($c->is); break; case "e": - // echo 'Error
'; + // echo 'Error', PHP_EOL; if (!isset($c->f)) { $value = self::_castToError($c); } else { // Formula $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToError'); - // echo '$calculatedValue = '.$calculatedValue.'
'; + // echo '$calculatedValue = ', $calculatedValue, PHP_EOL; } break; default: - // echo 'Default
'; + // echo 'Default', PHP_EOL; if (!isset($c->f)) { - // echo 'Not a Formula
'; + // echo 'Not a Formula', PHP_EOL; $value = self::_castToString($c); } else { - // echo 'Treat as Formula
'; + // echo 'Treat as Formula', PHP_EOL; // Formula $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToString'); - // echo '$calculatedValue = '.$calculatedValue.'
'; + // echo '$calculatedValue = ', $calculatedValue, PHP_EOL; } break; } - // echo 'Value is '.$value.'
'; + // echo 'Value is ', $value, PHP_EOL; // Check for numeric values if (is_numeric($value) && $cellDataType != 's') { @@ -1091,12 +991,12 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) { foreach ($aKeys as $key) { $method = "set" . ucfirst($key); - $docSheet->getProtection()->$method($xmlSheet->sheetProtection[$key] == "true"); + $docSheet->getProtection()->$method(self::boolean((string) $xmlSheet->sheetProtection[$key])); } } if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) { - $docSheet->getProtection()->setPassword((string) $xmlSheet->sheetProtection["password"], true); + $docSheet->getProtection()->setPassword((string) $xmlSheet->sheetProtection["password"], TRUE); if ($xmlSheet->protectedRanges->protectedRange) { foreach ($xmlSheet->protectedRanges->protectedRange as $protectedRange) { $docSheet->protectCells((string) $protectedRange["sqref"], (string) $protectedRange["password"], true); @@ -1233,16 +1133,16 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $docPageSetup->setPaperSize(intval($xmlSheet->pageSetup["paperSize"])); } if (isset($xmlSheet->pageSetup["scale"])) { - $docPageSetup->setScale(intval($xmlSheet->pageSetup["scale"]), false); + $docPageSetup->setScale(intval($xmlSheet->pageSetup["scale"]), FALSE); } if (isset($xmlSheet->pageSetup["fitToHeight"]) && intval($xmlSheet->pageSetup["fitToHeight"]) >= 0) { - $docPageSetup->setFitToHeight(intval($xmlSheet->pageSetup["fitToHeight"]), false); + $docPageSetup->setFitToHeight(intval($xmlSheet->pageSetup["fitToHeight"]), FALSE); } if (isset($xmlSheet->pageSetup["fitToWidth"]) && intval($xmlSheet->pageSetup["fitToWidth"]) >= 0) { - $docPageSetup->setFitToWidth(intval($xmlSheet->pageSetup["fitToWidth"]), false); + $docPageSetup->setFitToWidth(intval($xmlSheet->pageSetup["fitToWidth"]), FALSE); } if (isset($xmlSheet->pageSetup["firstPageNumber"]) && isset($xmlSheet->pageSetup["useFirstPageNumber"]) && - ((string)$xmlSheet->pageSetup["useFirstPageNumber"] == 'true' || (string)$xmlSheet->pageSetup["useFirstPageNumber"] == '1')) { + self::boolean((string) $xmlSheet->pageSetup["useFirstPageNumber"])) { $docPageSetup->setFirstPageNumber(intval($xmlSheet->pageSetup["firstPageNumber"])); } } @@ -1251,28 +1151,28 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $docHeaderFooter = $docSheet->getHeaderFooter(); if (isset($xmlSheet->headerFooter["differentOddEven"]) && - ((string)$xmlSheet->headerFooter["differentOddEven"] == 'true' || (string)$xmlSheet->headerFooter["differentOddEven"] == '1')) { - $docHeaderFooter->setDifferentOddEven(true); + self::boolean((string)$xmlSheet->headerFooter["differentOddEven"])) { + $docHeaderFooter->setDifferentOddEven(TRUE); } else { - $docHeaderFooter->setDifferentOddEven(false); + $docHeaderFooter->setDifferentOddEven(FALSE); } if (isset($xmlSheet->headerFooter["differentFirst"]) && - ((string)$xmlSheet->headerFooter["differentFirst"] == 'true' || (string)$xmlSheet->headerFooter["differentFirst"] == '1')) { - $docHeaderFooter->setDifferentFirst(true); + self::boolean((string)$xmlSheet->headerFooter["differentFirst"])) { + $docHeaderFooter->setDifferentFirst(TRUE); } else { - $docHeaderFooter->setDifferentFirst(false); + $docHeaderFooter->setDifferentFirst(FALSE); } if (isset($xmlSheet->headerFooter["scaleWithDoc"]) && - ((string)$xmlSheet->headerFooter["scaleWithDoc"] == 'false' || (string)$xmlSheet->headerFooter["scaleWithDoc"] == '0')) { - $docHeaderFooter->setScaleWithDocument(false); + !self::boolean((string)$xmlSheet->headerFooter["scaleWithDoc"])) { + $docHeaderFooter->setScaleWithDocument(FALSE); } else { - $docHeaderFooter->setScaleWithDocument(true); + $docHeaderFooter->setScaleWithDocument(TRUE); } if (isset($xmlSheet->headerFooter["alignWithMargins"]) && - ((string)$xmlSheet->headerFooter["alignWithMargins"] == 'false' || (string)$xmlSheet->headerFooter["alignWithMargins"] == '0')) { - $docHeaderFooter->setAlignWithMargins(false); + !self::boolean((string)$xmlSheet->headerFooter["alignWithMargins"])) { + $docHeaderFooter->setAlignWithMargins(FALSE); } else { - $docHeaderFooter->setAlignWithMargins(true); + $docHeaderFooter->setAlignWithMargins(TRUE); } $docHeaderFooter->setOddHeader((string) $xmlSheet->headerFooter->oddHeader); @@ -1334,7 +1234,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader if (!$this->_readDataOnly) { // Locate hyperlink relations if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { - $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") , 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); foreach ($relsWorksheet->Relationship as $ele) { if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink") { $hyperlinks[(string)$ele["Id"]] = (string)$ele["Target"]; @@ -1351,9 +1251,12 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader foreach (PHPExcel_Cell::extractAllCellReferencesInRange($hyperlink['ref']) as $cellReference) { $cell = $docSheet->getCell( $cellReference ); if (isset($linkRel['id'])) { - $cell->getHyperlink()->setUrl( $hyperlinks[ (string)$linkRel['id'] ] ); - } - if (isset($hyperlink['location'])) { + $hyperlinkUrl = $hyperlinks[ (string)$linkRel['id'] ]; + if (isset($hyperlink['location'])) { + $hyperlinkUrl .= '#' . (string) $hyperlink['location']; + } + $cell->getHyperlink()->setUrl($hyperlinkUrl); + } elseif (isset($hyperlink['location'])) { $cell->getHyperlink()->setUrl( 'sheet://' . (string)$hyperlink['location'] ); } @@ -1372,7 +1275,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader if (!$this->_readDataOnly) { // Locate comment relations if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { - $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") , 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); foreach ($relsWorksheet->Relationship as $ele) { if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments") { $comments[(string)$ele["Id"]] = (string)$ele["Target"]; @@ -1387,7 +1290,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader foreach ($comments as $relName => $relPath) { // Load comments file $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath); - $commentsFile = simplexml_load_string($this->_getFromZipArchive($zip, $relPath) ); + $commentsFile = simplexml_load_string($this->_getFromZipArchive($zip, $relPath) , 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); // Utility variables $authors = array(); @@ -1408,7 +1311,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader foreach ($vmlComments as $relName => $relPath) { // Load VML comments file $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath); - $vmlCommentsFile = simplexml_load_string( $this->_getFromZipArchive($zip, $relPath) ); + $vmlCommentsFile = simplexml_load_string( $this->_getFromZipArchive($zip, $relPath) , 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); $vmlCommentsFile->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); $shapes = $vmlCommentsFile->xpath('//v:shape'); @@ -1459,7 +1362,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader // Header/footer images if ($xmlSheet && $xmlSheet->legacyDrawingHF && !$this->_readDataOnly) { if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { - $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") , 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); $vmlRelationship = ''; foreach ($relsWorksheet->Relationship as $ele) { @@ -1470,7 +1373,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader if ($vmlRelationship != '') { // Fetch linked images - $relsVML = simplexml_load_string($this->_getFromZipArchive($zip, dirname($vmlRelationship) . '/_rels/' . basename($vmlRelationship) . '.rels' )); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $relsVML = simplexml_load_string($this->_getFromZipArchive($zip, dirname($vmlRelationship) . '/_rels/' . basename($vmlRelationship) . '.rels' ), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); $drawings = array(); foreach ($relsVML->Relationship as $ele) { if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") { @@ -1479,16 +1382,16 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } // Fetch VML document - $vmlDrawing = simplexml_load_string($this->_getFromZipArchive($zip, $vmlRelationship)); + $vmlDrawing = simplexml_load_string($this->_getFromZipArchive($zip, $vmlRelationship), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); $vmlDrawing->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); $hfImages = array(); $shapes = $vmlDrawing->xpath('//v:shape'); - foreach ($shapes as $shape) { + foreach ($shapes as $idx => $shape) { $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); $imageData = $shape->xpath('//v:imagedata'); - $imageData = $imageData[0]; + $imageData = $imageData[$idx]; $imageData = $imageData->attributes('urn:schemas-microsoft-com:office:office'); $style = self::toCSSArray( (string)$shape['style'] ); @@ -1498,11 +1401,13 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $hfImages[ (string)$shape['id'] ]->setName( (string)$imageData['title'] ); } - $hfImages[ (string)$shape['id'] ]->setPath("zip://$pFilename#" . $drawings[(string)$imageData['relid']], false); + $hfImages[ (string)$shape['id'] ]->setPath("zip://".PHPExcel_Shared_File::realpath($pFilename)."#" . $drawings[(string)$imageData['relid']], false); $hfImages[ (string)$shape['id'] ]->setResizeProportional(false); $hfImages[ (string)$shape['id'] ]->setWidth($style['width']); $hfImages[ (string)$shape['id'] ]->setHeight($style['height']); - $hfImages[ (string)$shape['id'] ]->setOffsetX($style['margin-left']); + if (isset($style['margin-left'])) { + $hfImages[ (string)$shape['id'] ]->setOffsetX($style['margin-left']); + } $hfImages[ (string)$shape['id'] ]->setOffsetY($style['margin-top']); $hfImages[ (string)$shape['id'] ]->setResizeProportional(true); } @@ -1514,9 +1419,9 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } -// TODO: Autoshapes from twoCellAnchors! + // TODO: Autoshapes from twoCellAnchors! if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { - $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") , 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); $drawings = array(); foreach ($relsWorksheet->Relationship as $ele) { if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing") { @@ -1526,7 +1431,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader if ($xmlSheet->drawing && !$this->_readDataOnly) { foreach ($xmlSheet->drawing as $drawing) { $fileDrawing = $drawings[(string) self::array_item($drawing->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; - $relsDrawing = simplexml_load_string($this->_getFromZipArchive($zip, dirname($fileDrawing) . "/_rels/" . basename($fileDrawing) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $relsDrawing = simplexml_load_string($this->_getFromZipArchive($zip, dirname($fileDrawing) . "/_rels/" . basename($fileDrawing) . ".rels") , 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); //~ http://schemas.openxmlformats.org/package/2006/relationships"); $images = array(); if ($relsDrawing && $relsDrawing->Relationship) { @@ -1542,7 +1447,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } } } - $xmlDrawing = simplexml_load_string($this->_getFromZipArchive($zip, $fileDrawing))->children("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"); + $xmlDrawing = simplexml_load_string($this->_getFromZipArchive($zip, $fileDrawing), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions())->children("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"); if ($xmlDrawing->oneCellAnchor) { foreach ($xmlDrawing->oneCellAnchor as $oneCellAnchor) { @@ -1553,7 +1458,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $objDrawing = new PHPExcel_Worksheet_Drawing; $objDrawing->setName((string) self::array_item($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name")); $objDrawing->setDescription((string) self::array_item($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr")); - $objDrawing->setPath("zip://$pFilename#" . $images[(string) self::array_item($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false); + $objDrawing->setPath("zip://".PHPExcel_Shared_File::realpath($pFilename)."#" . $images[(string) self::array_item($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false); $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex((string) $oneCellAnchor->from->col) . ($oneCellAnchor->from->row + 1)); $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->colOff)); $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->rowOff)); @@ -1593,7 +1498,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $objDrawing = new PHPExcel_Worksheet_Drawing; $objDrawing->setName((string) self::array_item($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name")); $objDrawing->setDescription((string) self::array_item($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr")); - $objDrawing->setPath("zip://$pFilename#" . $images[(string) self::array_item($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false); + $objDrawing->setPath("zip://".PHPExcel_Shared_File::realpath($pFilename)."#" . $images[(string) self::array_item($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false); $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex((string) $twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1)); $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->colOff)); $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->rowOff)); @@ -1679,13 +1584,14 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader // Set print titles foreach ($extractedRange as $range) { $matches = array(); + $range = str_replace('$', '', $range); // check for repeating columns, e g. 'A:A' or 'A:D' - if (preg_match('/^([A-Z]+)\:([A-Z]+)$/', $range, $matches)) { + if (preg_match('/!?([A-Z]+)\:([A-Z]+)$/', $range, $matches)) { $docSheet->getPageSetup()->setColumnsToRepeatAtLeft(array($matches[1], $matches[2])); } // check for repeating rows, e.g. '1:1' or '1:5' - elseif (preg_match('/^(\d+)\:(\d+)$/', $range, $matches)) { + elseif (preg_match('/!?(\d+)\:(\d+)$/', $range, $matches)) { $docSheet->getPageSetup()->setRowsToRepeatAtTop(array($matches[1], $matches[2])); } } @@ -1697,6 +1603,9 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader foreach($rangeSets as $rangeSet) { $range = explode('!', $rangeSet); // FIXME: what if sheetname contains exclamation mark? $rangeSet = isset($range[1]) ? $range[1] : $range[0]; + if (strpos($rangeSet, ':') === FALSE) { + $rangeSet = $rangeSet . ':' . $rangeSet; + } $newRangeSets[] = str_replace('$', '', $rangeSet); } $docSheet->getPageSetup()->setPrintArea(implode(',',$newRangeSets)); @@ -1742,15 +1651,16 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader break; default: - $range = explode('!', (string)$definedName); - if (count($range) == 2) { - $range[0] = str_replace("''", "'", $range[0]); - $range[0] = str_replace("'", "", $range[0]); - if ($worksheet = $docSheet->getParent()->getSheetByName($range[0])) { - $extractedRange = str_replace('$', '', $range[1]); - $scope = $docSheet->getParent()->getSheet((string)$definedName['localSheetId']); - - $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $worksheet, $extractedRange, true, $scope) ); + if ($mapSheetId[(integer) $definedName['localSheetId']] !== null) { + $range = explode('!', (string)$definedName); + if (count($range) == 2) { + $range[0] = str_replace("''", "'", $range[0]); + $range[0] = str_replace("'", "", $range[0]); + if ($worksheet = $docSheet->getParent()->getSheetByName($range[0])) { + $extractedRange = str_replace('$', '', $range[1]); + $scope = $docSheet->getParent()->getSheet($mapSheetId[(integer) $definedName['localSheetId']]); + $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $worksheet, $extractedRange, true, $scope) ); + } } } break; @@ -1780,7 +1690,7 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } } - if (!$this->_readDataOnly) { + if ((!$this->_readDataOnly) || (!empty($this->_loadSheetsOnly))) { // active sheet index $activeTab = intval($xmlWorkbook->bookViews->workbookView["activeTab"]); // refers to old sheet index @@ -1801,13 +1711,13 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader if (!$this->_readDataOnly) { - $contentTypes = simplexml_load_string($this->_getFromZipArchive($zip, "[Content_Types].xml")); + $contentTypes = simplexml_load_string($this->_getFromZipArchive($zip, "[Content_Types].xml"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); foreach ($contentTypes->Override as $contentType) { switch ($contentType["ContentType"]) { case "application/vnd.openxmlformats-officedocument.drawingml.chart+xml": if ($this->_includeCharts) { $chartEntryRef = ltrim($contentType['PartName'],'/'); - $chartElements = simplexml_load_string($this->_getFromZipArchive($zip, $chartEntryRef)); + $chartElements = simplexml_load_string($this->_getFromZipArchive($zip, $chartEntryRef), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); $objChart = PHPExcel_Reader_Excel2007_Chart::readChart($chartElements,basename($chartEntryRef,'.xml')); // echo 'Chart ',$chartEntryRef,'
'; @@ -1880,13 +1790,13 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $docStyle->getFont()->setName((string) $style->font->name["val"]); $docStyle->getFont()->setSize((string) $style->font->sz["val"]); if (isset($style->font->b)) { - $docStyle->getFont()->setBold(!isset($style->font->b["val"]) || $style->font->b["val"] == 'true' || $style->font->b["val"] == '1'); + $docStyle->getFont()->setBold(!isset($style->font->b["val"]) || self::boolean((string) $style->font->b["val"])); } if (isset($style->font->i)) { - $docStyle->getFont()->setItalic(!isset($style->font->i["val"]) || $style->font->i["val"] == 'true' || $style->font->i["val"] == '1'); + $docStyle->getFont()->setItalic(!isset($style->font->i["val"]) || self::boolean((string) $style->font->i["val"])); } if (isset($style->font->strike)) { - $docStyle->getFont()->setStrikethrough(!isset($style->font->strike["val"]) || $style->font->strike["val"] == 'true' || $style->font->strike["val"] == '1'); + $docStyle->getFont()->setStrikethrough(!isset($style->font->strike["val"]) || self::boolean((string) $style->font->strike["val"])); } $docStyle->getFont()->getColor()->setARGB(self::_readColor($style->font->color)); @@ -1934,21 +1844,15 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader // border if (isset($style->border)) { - $diagonalUp = false; - $diagonalDown = false; - if ($style->border["diagonalUp"] == 'true' || $style->border["diagonalUp"] == 1) { - $diagonalUp = true; - } - if ($style->border["diagonalDown"] == 'true' || $style->border["diagonalDown"] == 1) { - $diagonalDown = true; - } - if ($diagonalUp == false && $diagonalDown == false) { + $diagonalUp = self::boolean((string) $style->border["diagonalUp"]); + $diagonalDown = self::boolean((string) $style->border["diagonalDown"]); + if (!$diagonalUp && !$diagonalDown) { $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_NONE); - } elseif ($diagonalUp == true && $diagonalDown == false) { + } elseif ($diagonalUp && !$diagonalDown) { $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_UP); - } elseif ($diagonalUp == false && $diagonalDown == true) { + } elseif (!$diagonalUp && $diagonalDown) { $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_DOWN); - } elseif ($diagonalUp == true && $diagonalDown == true) { + } else { $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_BOTH); } self::_readBorder($docStyle->getBorders()->getLeft(), $style->border->left); @@ -1971,15 +1875,15 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } $docStyle->getAlignment()->setTextRotation(intval($textRotation)); - $docStyle->getAlignment()->setWrapText( (string)$style->alignment["wrapText"] == "true" || (string)$style->alignment["wrapText"] == "1" ); - $docStyle->getAlignment()->setShrinkToFit( (string)$style->alignment["shrinkToFit"] == "true" || (string)$style->alignment["shrinkToFit"] == "1" ); + $docStyle->getAlignment()->setWrapText(self::boolean((string) $style->alignment["wrapText"])); + $docStyle->getAlignment()->setShrinkToFit(self::boolean((string) $style->alignment["shrinkToFit"])); $docStyle->getAlignment()->setIndent( intval((string)$style->alignment["indent"]) > 0 ? intval((string)$style->alignment["indent"]) : 0 ); } // protection if (isset($style->protection)) { if (isset($style->protection['locked'])) { - if ((string)$style->protection['locked'] == 'true') { + if (self::boolean((string) $style->protection['locked'])) { $docStyle->getProtection()->setLocked(PHPExcel_Style_Protection::PROTECTION_PROTECTED); } else { $docStyle->getProtection()->setLocked(PHPExcel_Style_Protection::PROTECTION_UNPROTECTED); @@ -1987,13 +1891,18 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader } if (isset($style->protection['hidden'])) { - if ((string)$style->protection['hidden'] == 'true') { + if (self::boolean((string) $style->protection['hidden'])) { $docStyle->getProtection()->setHidden(PHPExcel_Style_Protection::PROTECTION_PROTECTED); } else { $docStyle->getProtection()->setHidden(PHPExcel_Style_Protection::PROTECTION_UNPROTECTED); } } } + + // top-level style settings + if (isset($style->quotePrefix)) { + $docStyle->setQuotePrefix($style->quotePrefix); + } } @@ -2032,23 +1941,23 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $objText->getFont()->setColor( new PHPExcel_Style_Color( self::_readColor($run->rPr->color) ) ); } - if ( (isset($run->rPr->b["val"]) && ((string) $run->rPr->b["val"] == 'true' || (string) $run->rPr->b["val"] == '1')) - || (isset($run->rPr->b) && !isset($run->rPr->b["val"])) ) { - $objText->getFont()->setBold(true); + if ((isset($run->rPr->b["val"]) && self::boolean((string) $run->rPr->b["val"])) || + (isset($run->rPr->b) && !isset($run->rPr->b["val"]))) { + $objText->getFont()->setBold(TRUE); } - if ( (isset($run->rPr->i["val"]) && ((string) $run->rPr->i["val"] == 'true' || (string) $run->rPr->i["val"] == '1')) - || (isset($run->rPr->i) && !isset($run->rPr->i["val"])) ) { - $objText->getFont()->setItalic(true); + if ((isset($run->rPr->i["val"]) && self::boolean((string) $run->rPr->i["val"])) || + (isset($run->rPr->i) && !isset($run->rPr->i["val"]))) { + $objText->getFont()->setItalic(TRUE); } if (isset($run->rPr->vertAlign) && isset($run->rPr->vertAlign["val"])) { $vertAlign = strtolower((string)$run->rPr->vertAlign["val"]); if ($vertAlign == 'superscript') { - $objText->getFont()->setSuperScript(true); + $objText->getFont()->setSuperScript(TRUE); } if ($vertAlign == 'subscript') { - $objText->getFont()->setSubScript(true); + $objText->getFont()->setSubScript(TRUE); } } @@ -2058,9 +1967,9 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader $objText->getFont()->setUnderline((string)$run->rPr->u["val"]); } - if ( (isset($run->rPr->strike["val"]) && ((string) $run->rPr->strike["val"] == 'true' || (string) $run->rPr->strike["val"] == '1')) - || (isset($run->rPr->strike) && !isset($run->rPr->strike["val"])) ) { - $objText->getFont()->setStrikethrough(true); + if ((isset($run->rPr->strike["val"]) && self::boolean((string) $run->rPr->strike["val"])) || + (isset($run->rPr->strike) && !isset($run->rPr->strike["val"]))) { + $objText->getFont()->setStrikethrough(TRUE); } } } @@ -2069,6 +1978,43 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader return $value; } + private function _readRibbon($excel, $customUITarget, $zip) + { + $baseDir = dirname($customUITarget); + $nameCustomUI = basename($customUITarget); + // get the xml file (ribbon) + $localRibbon = $this->_getFromZipArchive($zip, $customUITarget); + $customUIImagesNames = array(); + $customUIImagesBinaries = array(); + // something like customUI/_rels/customUI.xml.rels + $pathRels = $baseDir . '/_rels/' . $nameCustomUI . '.rels'; + $dataRels = $this->_getFromZipArchive($zip, $pathRels); + if ($dataRels) { + // exists and not empty if the ribbon have some pictures (other than internal MSO) + $UIRels = simplexml_load_string($dataRels, 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + if ($UIRels) { + // we need to save id and target to avoid parsing customUI.xml and "guess" if it's a pseudo callback who load the image + foreach ($UIRels->Relationship as $ele) { + if ($ele["Type"] == 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image') { + // an image ? + $customUIImagesNames[(string) $ele['Id']] = (string)$ele['Target']; + $customUIImagesBinaries[(string)$ele['Target']] = $this->_getFromZipArchive($zip, $baseDir . '/' . (string) $ele['Target']); + } + } + } + } + if ($localRibbon) { + $excel->setRibbonXMLData($customUITarget, $localRibbon); + if (count($customUIImagesNames) > 0 && count($customUIImagesBinaries) > 0) { + $excel->setRibbonBinObjects($customUIImagesNames, $customUIImagesBinaries); + } else { + $excel->setRibbonBinObjects(NULL); + } + } else { + $excel->setRibbonXMLData(NULL); + $excel->setRibbonBinObjects(NULL); + } + } private static function array_item($array, $key = 0) { return (isset($array[$key]) ? $array[$key] : null); @@ -2109,4 +2055,15 @@ class PHPExcel_Reader_Excel2007 implements PHPExcel_Reader_IReader return $style; } + + private static function boolean($value = NULL) + { + if (is_object($value)) { + $value = (string) $value; + } + if (is_numeric($value)) { + return (bool) $value; + } + return ($value === 'true' || $value === 'TRUE'); + } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Reader/Excel2007/Chart.php b/htdocs/includes/phpexcel/PHPExcel/Reader/Excel2007/Chart.php index f4d38bdb44a..0de88acb120 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Reader/Excel2007/Chart.php +++ b/htdocs/includes/phpexcel/PHPExcel/Reader/Excel2007/Chart.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,10 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * @category PHPExcel - * @package PHPExcel_Reader_Excel5 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @package PHPExcel_Reader_Excel2007 + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Reader_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Reader_Excel2007_Chart { @@ -42,7 +42,7 @@ class PHPExcel_Reader_Excel2007_Chart } elseif ($format == 'integer') { return (integer) $attributes[$name]; } elseif ($format == 'boolean') { - return (boolean) ($attributes[$name] == '0') ? false : true; + return (boolean) ($attributes[$name] === '0' || $attributes[$name] !== 'true') ? false : true; } else { return (float) $attributes[$name]; } @@ -347,6 +347,10 @@ class PHPExcel_Reader_Excel2007_Chart } } + if (empty($seriesVal)) { + $seriesVal = NULL; + } + return array( 'formatCode' => $formatCode, 'pointCount' => $pointCount, 'dataValues' => $seriesVal diff --git a/htdocs/includes/phpexcel/PHPExcel/Reader/Excel2007/Theme.php b/htdocs/includes/phpexcel/PHPExcel/Reader/Excel2007/Theme.php index 6b38fa79fb9..820fa96db89 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Reader/Excel2007/Theme.php +++ b/htdocs/includes/phpexcel/PHPExcel/Reader/Excel2007/Theme.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Reader_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Reader_Excel2007_Theme { diff --git a/htdocs/includes/phpexcel/PHPExcel/Reader/Excel5.php b/htdocs/includes/phpexcel/PHPExcel/Reader/Excel5.php index 535654243c2..91e0fa086f7 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Reader/Excel5.php +++ b/htdocs/includes/phpexcel/PHPExcel/Reader/Excel5.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader_Excel5 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ // Original file header of ParseXL (used as the base for this class): @@ -73,9 +73,9 @@ if (!defined('PHPEXCEL_ROOT')) { * * @category PHPExcel * @package PHPExcel_Reader_Excel5 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader +class PHPExcel_Reader_Excel5 extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader { // ParseXL definitions const XLS_BIFF8 = 0x0600; @@ -156,32 +156,16 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader const XLS_Type_RANGEPROTECTION = 0x0868; const XLS_Type_SHEETLAYOUT = 0x0862; const XLS_Type_XFEXT = 0x087d; + const XLS_Type_PAGELAYOUTVIEW = 0x088b; const XLS_Type_UNKNOWN = 0xffff; - - /** - * Read data only? - * Identifies whether the Reader should only read data values for cells, and ignore any formatting information; - * or whether it should read both data and formatting - * - * @var boolean - */ - private $_readDataOnly = false; - - /** - * Restrict which sheets should be loaded? - * This property holds an array of worksheet names to be loaded. If null, then all worksheets will be loaded. - * - * @var array of string - */ - private $_loadSheetsOnly = null; - - /** - * PHPExcel_Reader_IReadFilter instance - * - * @var PHPExcel_Reader_IReadFilter - */ - private $_readFilter = null; + // Encryption type + const MS_BIFF_CRYPTO_NONE = 0; + const MS_BIFF_CRYPTO_XOR = 1; + const MS_BIFF_CRYPTO_RC4 = 2; + + // Size of stream blocks when using RC4 encryption + const REKEY_BLOCK = 0x400; /** * Summary Information stream data. @@ -402,6 +386,40 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader */ private $_sharedFormulaParts; + /** + * The type of encryption in use + * + * @var int + */ + private $_encryption = 0; + + /** + * The position in the stream after which contents are encrypted + * + * @var int + */ + private $_encryptionStartPos = false; + + /** + * The current RC4 decryption object + * + * @var PHPExcel_Reader_Excel5_RC4 + */ + private $_rc4Key = null; + + /** + * The position in the stream that the RC4 decryption object was left at + * + * @var int + */ + private $_rc4Pos = 0; + + /** + * The current MD5 context state + * + * @var string + */ + private $_md5Ctxt = null; /** * Create a new PHPExcel_Reader_Excel5 instance @@ -411,112 +429,18 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader } - /** - * Read data only? - * If this is true, then the Reader will only read data values for cells, it will not read any formatting information. - * If false (the default) it will read data and formatting. - * - * @return boolean - */ - public function getReadDataOnly() - { - return $this->_readDataOnly; - } - - - /** - * Set read data only - * Set to true, to advise the Reader only to read data values for cells, and to ignore any formatting information. - * Set to false (the default) to advise the Reader to read both data and formatting for cells. - * - * @param boolean $pValue - * - * @return PHPExcel_Reader_Excel5 - */ - public function setReadDataOnly($pValue = false) - { - $this->_readDataOnly = $pValue; - return $this; - } - - - /** - * Get which sheets to load - * Returns either an array of worksheet names (the list of worksheets that should be loaded), or a null - * indicating that all worksheets in the workbook should be loaded. - * - * @return mixed - */ - public function getLoadSheetsOnly() - { - return $this->_loadSheetsOnly; - } - - - /** - * Set which sheets to load - * - * @param mixed $value - * This should be either an array of worksheet names to be loaded, or a string containing a single worksheet name. - * If NULL, then it tells the Reader to read all worksheets in the workbook - * - * @return PHPExcel_Reader_Excel5 - */ - public function setLoadSheetsOnly($value = null) - { - $this->_loadSheetsOnly = is_array($value) ? - $value : array($value); - return $this; - } - - - /** - * Set all sheets to load - * Tells the Reader to load all worksheets from the workbook. - * - * @return PHPExcel_Reader_Excel5 - */ - public function setLoadAllSheets() - { - $this->_loadSheetsOnly = null; - return $this; - } - - - /** - * Read filter - * - * @return PHPExcel_Reader_IReadFilter - */ - public function getReadFilter() { - return $this->_readFilter; - } - - - /** - * Set read filter - * - * @param PHPExcel_Reader_IReadFilter $pValue - * @return PHPExcel_Reader_Excel5 - */ - public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) { - $this->_readFilter = $pValue; - return $this; - } - - /** * Can the current PHPExcel_Reader_IReader read the file? * - * @param string $pFileName + * @param string $pFilename * @return boolean - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function canRead($pFilename) { // Check if file exists if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); } try { @@ -526,8 +450,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // get excel data $res = $ole->read($pFilename); return true; - - } catch (Exception $e) { + } catch (PHPExcel_Exception $e) { return false; } } @@ -537,13 +460,13 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object * * @param string $pFilename - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function listWorksheetNames($pFilename) { // Check if file exists if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); } $worksheetNames = array(); @@ -586,13 +509,13 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) * * @param string $pFilename - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function listWorksheetInfo($pFilename) { // Check if file exists if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); } $worksheetInfo = array(); @@ -649,7 +572,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case self::XLS_Type_BOOLERR: case self::XLS_Type_LABEL: $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -681,7 +604,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader * * @param string $pFilename * @return PHPExcel - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function load($pFilename) { @@ -903,6 +826,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case self::XLS_Type_MSODRAWING: $this->_readMsoDrawing(); break; case self::XLS_Type_OBJ: $this->_readObj(); break; case self::XLS_Type_WINDOW2: $this->_readWindow2(); break; + case self::XLS_Type_PAGELAYOUTVIEW: $this->_readPageLayoutView(); break; case self::XLS_Type_SCL: $this->_readScl(); break; case self::XLS_Type_PANE: $this->_readPane(); break; case self::XLS_Type_SELECTION: $this->_readSelection(); break; @@ -1073,7 +997,6 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case pack('C', 0x06): // print area // in general, formula looks like this: Foo!$C$7:$J$66,Bar!$A$1:$IV$2 - $ranges = explode(',', $definedName['formula']); // FIXME: what if sheetname contains comma? $extractedRanges = array(); @@ -1083,9 +1006,12 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // Bar!$A$1:$IV$2 $explodes = explode('!', $range); // FIXME: what if sheetname contains exclamation mark? - $sheetName = $explodes[0]; + $sheetName = trim($explodes[0], "'"); if (count($explodes) == 2) { + if (strpos($explodes[1], ':') === FALSE) { + $explodes[1] = $explodes[1] . ':' . $explodes[1]; + } $extractedRanges[] = str_replace('$', '', $explodes[1]); // C7:J66 } } @@ -1166,7 +1092,63 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader return $this->_phpExcel; } + + /** + * Read record data from stream, decrypting as required + * + * @param string $data Data stream to read from + * @param int $pos Position to start reading from + * @param int $length Record data length + * + * @return string Record data + */ + private function _readRecordData($data, $pos, $len) + { + $data = substr($data, $pos, $len); + + // File not encrypted, or record before encryption start point + if ($this->_encryption == self::MS_BIFF_CRYPTO_NONE || $pos < $this->_encryptionStartPos) { + return $data; + } + + $recordData = ''; + if ($this->_encryption == self::MS_BIFF_CRYPTO_RC4) { + $oldBlock = floor($this->_rc4Pos / self::REKEY_BLOCK); + $block = floor($pos / self::REKEY_BLOCK); + $endBlock = floor(($pos + $len) / self::REKEY_BLOCK); + + // Spin an RC4 decryptor to the right spot. If we have a decryptor sitting + // at a point earlier in the current block, re-use it as we can save some time. + if ($block != $oldBlock || $pos < $this->_rc4Pos || !$this->_rc4Key) { + $this->_rc4Key = $this->_makeKey($block, $this->_md5Ctxt); + $step = $pos % self::REKEY_BLOCK; + } else { + $step = $pos - $this->_rc4Pos; + } + $this->_rc4Key->RC4(str_repeat("\0", $step)); + + // Decrypt record data (re-keying at the end of every block) + while ($block != $endBlock) { + $step = self::REKEY_BLOCK - ($pos % self::REKEY_BLOCK); + $recordData .= $this->_rc4Key->RC4(substr($data, 0, $step)); + $data = substr($data, $step); + $pos += $step; + $len -= $step; + $block++; + $this->_rc4Key = $this->_makeKey($block, $this->_md5Ctxt); + } + $recordData .= $this->_rc4Key->RC4(substr($data, 0, $len)); + + // Keep track of the position of this decryptor. + // We'll try and re-use it later if we can to speed things up + $this->_rc4Pos = $pos + $len; + + } elseif ($this->_encryption == self::MS_BIFF_CRYPTO_XOR) { + throw new PHPExcel_Reader_Exception('XOr encryption not supported'); + } + return $recordData; + } /** * Use OLE reader to extract the relevant data streams from the OLE file @@ -1519,7 +1501,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readDefault() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); -// $recordData = substr($this->_data, $this->_pos + 4, $length); +// $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -1534,7 +1516,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader { // echo 'Read Cell Annotation
'; $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -1596,7 +1578,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readTextObject() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -1648,7 +1630,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case self::XLS_WorkbookGlobals: $version = self::_GetInt2d($recordData, 0); if (($version != self::XLS_BIFF8) && ($version != self::XLS_BIFF7)) { - throw new Exception('Cannot read this Excel file. Version is too old.'); + throw new PHPExcel_Reader_Exception('Cannot read this Excel file. Version is too old.'); } $this->_version = $version; break; @@ -1680,18 +1662,156 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader * * -- "OpenOffice.org's Documentation of the Microsoft * Excel File Format" + * + * The decryption functions and objects used from here on in + * are based on the source of Spreadsheet-ParseExcel: + * http://search.cpan.org/~jmcnamara/Spreadsheet-ParseExcel/ */ private function _readFilepass() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); -// $recordData = substr($this->_data, $this->_pos + 4, $length); + if ($length != 54) { + throw new PHPExcel_Reader_Exception('Unexpected file pass record length'); + } + + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + // move stream pointer to next record $this->_pos += 4 + $length; + + if (!$this->_verifyPassword( + 'VelvetSweatshop', + substr($recordData, 6, 16), + substr($recordData, 22, 16), + substr($recordData, 38, 16), + $this->_md5Ctxt + )) { + throw new PHPExcel_Reader_Exception('Decryption password incorrect'); + } + + $this->_encryption = self::MS_BIFF_CRYPTO_RC4; - throw new Exception('Cannot read encrypted file'); + // Decryption required from the record after next onwards + $this->_encryptionStartPos = $this->_pos + self::_GetInt2d($this->_data, $this->_pos + 2); } + /** + * Make an RC4 decryptor for the given block + * + * @var int $block Block for which to create decrypto + * @var string $valContext MD5 context state + * + * @return PHPExcel_Reader_Excel5_RC4 + */ + private function _makeKey($block, $valContext) + { + $pwarray = str_repeat("\0", 64); + + for ($i = 0; $i < 5; $i++) { + $pwarray[$i] = $valContext[$i]; + } + + $pwarray[5] = chr($block & 0xff); + $pwarray[6] = chr(($block >> 8) & 0xff); + $pwarray[7] = chr(($block >> 16) & 0xff); + $pwarray[8] = chr(($block >> 24) & 0xff); + + $pwarray[9] = "\x80"; + $pwarray[56] = "\x48"; + + $md5 = new PHPExcel_Reader_Excel5_MD5(); + $md5->add($pwarray); + + $s = $md5->getContext(); + return new PHPExcel_Reader_Excel5_RC4($s); + } + + /** + * Verify RC4 file password + * + * @var string $password Password to check + * @var string $docid Document id + * @var string $salt_data Salt data + * @var string $hashedsalt_data Hashed salt data + * @var string &$valContext Set to the MD5 context of the value + * + * @return bool Success + */ + private function _verifyPassword($password, $docid, $salt_data, $hashedsalt_data, &$valContext) + { + $pwarray = str_repeat("\0", 64); + + for ($i = 0; $i < strlen($password); $i++) { + $o = ord(substr($password, $i, 1)); + $pwarray[2 * $i] = chr($o & 0xff); + $pwarray[2 * $i + 1] = chr(($o >> 8) & 0xff); + } + $pwarray[2 * $i] = chr(0x80); + $pwarray[56] = chr(($i << 4) & 0xff); + + $md5 = new PHPExcel_Reader_Excel5_MD5(); + $md5->add($pwarray); + + $mdContext1 = $md5->getContext(); + + $offset = 0; + $keyoffset = 0; + $tocopy = 5; + + $md5->reset(); + + while ($offset != 16) { + if ((64 - $offset) < 5) { + $tocopy = 64 - $offset; + } + + for ($i = 0; $i <= $tocopy; $i++) { + $pwarray[$offset + $i] = $mdContext1[$keyoffset + $i]; + } + + $offset += $tocopy; + + if ($offset == 64) { + $md5->add($pwarray); + $keyoffset = $tocopy; + $tocopy = 5 - $tocopy; + $offset = 0; + continue; + } + + $keyoffset = 0; + $tocopy = 5; + for ($i = 0; $i < 16; $i++) { + $pwarray[$offset + $i] = $docid[$i]; + } + $offset += 16; + } + + $pwarray[16] = "\x80"; + for ($i = 0; $i < 47; $i++) { + $pwarray[17 + $i] = "\0"; + } + $pwarray[56] = "\x80"; + $pwarray[57] = "\x0a"; + + $md5->add($pwarray); + $valContext = $md5->getContext(); + + $key = $this->_makeKey(0, $valContext); + + $salt = $key->RC4($salt_data); + $hashedsalt = $key->RC4($hashedsalt_data); + + $salt .= "\x80" . str_repeat("\0", 47); + $salt[56] = "\x80"; + + $md5->reset(); + $md5->add($salt); + $mdContext2 = $md5->getContext(); + + return $mdContext2 == $hashedsalt; + } /** * CODEPAGE @@ -1705,7 +1825,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readCodepage() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -1732,7 +1852,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readDateMode() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -1751,7 +1871,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readFont() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -1849,7 +1969,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readFormat() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -1887,7 +2007,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readXf() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -1951,6 +2071,9 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case 3: $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_RIGHT); break; + case 4: + $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_FILL); + break; case 5: $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY); break; @@ -2170,7 +2293,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readXfExt() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -2347,7 +2470,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readStyle() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -2388,7 +2511,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readPalette() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -2421,14 +2544,15 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readSheet() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // offset: 0; size: 4; absolute stream position of the BOF record of the sheet + // NOTE: not encrypted + $rec_offset = self::_GetInt4d($this->_data, $this->_pos + 4); // move stream pointer to next record $this->_pos += 4 + $length; - // offset: 0; size: 4; absolute stream position of the BOF record of the sheet - $rec_offset = self::_GetInt4d($recordData, 0); - // offset: 4; size: 1; sheet state switch (ord($recordData{4})) { case 0x00: $sheetState = PHPExcel_Worksheet::SHEETSTATE_VISIBLE; break; @@ -2464,7 +2588,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readExternalBook() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -2528,7 +2652,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readExternName() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -2563,7 +2687,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readExternSheet() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -2600,7 +2724,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readDefinedName() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -2635,7 +2759,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader try { $formula = $this->_getFormulaFromStructure($formulaStructure); - } catch (Exception $e) { + } catch (PHPExcel_Exception $e) { $formula = ''; } @@ -2862,7 +2986,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readPrintGridlines() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -2881,7 +3005,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readDefaultRowHeight() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -2899,7 +3023,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readSheetPr() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -2926,7 +3050,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readHorizontalPageBreaks() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -2955,7 +3079,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readVerticalPageBreaks() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -2983,7 +3107,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readHeader() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3011,7 +3135,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readFooter() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3038,7 +3162,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readHcenter() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3058,7 +3182,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readVcenter() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3078,7 +3202,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readLeftMargin() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3096,7 +3220,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readRightMargin() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3114,7 +3238,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readTopMargin() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3132,7 +3256,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readBottomMargin() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3150,7 +3274,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readPageSetup() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3208,7 +3332,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readProtect() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3231,7 +3355,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readScenProtect() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3255,7 +3379,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readObjectProtect() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3279,7 +3403,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readPassword() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3298,7 +3422,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readDefColWidth() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3317,7 +3441,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readColInfo() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3376,7 +3500,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readRow() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3446,7 +3570,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readRk() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3491,7 +3615,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readLabelSst() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3569,7 +3693,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readMulRk() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3624,7 +3748,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readNumber() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3666,7 +3790,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readFormula() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3777,12 +3901,12 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // add cell value. If we can read formula, populate with formula, otherwise just used cached value try { if ($this->_version != self::XLS_BIFF8) { - throw new Exception('Not BIFF8. Can only read BIFF8 formulas'); + throw new PHPExcel_Reader_Exception('Not BIFF8. Can only read BIFF8 formulas'); } $formula = $this->_getFormulaFromStructure($formulaStructure); // get formula in human language $cell->setValueExplicit('=' . $formula, PHPExcel_Cell_DataType::TYPE_FORMULA); - } catch (Exception $e) { + } catch (PHPExcel_Exception $e) { $cell->setValueExplicit($value, $dataType); } } else { @@ -3807,7 +3931,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readSharedFmla() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3840,7 +3964,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readString() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3868,7 +3992,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readBoolErr() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3927,7 +4051,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readMulBlank() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -3969,7 +4093,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readLabel() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -4012,7 +4136,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readBlank() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -4059,7 +4183,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readObj() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -4104,7 +4228,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readWindow2() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -4112,6 +4236,22 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // offset: 0; size: 2; option flags $options = self::_GetInt2d($recordData, 0); + // offset: 2; size: 2; index to first visible row + $firstVisibleRow = self::_GetInt2d($recordData, 2); + + // offset: 4; size: 2; index to first visible colum + $firstVisibleColumn = self::_GetInt2d($recordData, 4); + if ($this->_version === self::XLS_BIFF8) { + // offset: 8; size: 2; not used + // offset: 10; size: 2; cached magnification factor in page break preview (in percent); 0 = Default (60%) + // offset: 12; size: 2; cached magnification factor in normal view (in percent); 0 = Default (100%) + // offset: 14; size: 4; not used + $zoomscaleInPageBreakPreview = self::_GetInt2d($recordData, 10); + if ($zoomscaleInPageBreakPreview === 0) $zoomscaleInPageBreakPreview = 60; + $zoomscaleInNormalView = self::_GetInt2d($recordData, 12); + if ($zoomscaleInNormalView === 0) $zoomscaleInNormalView = 100; + } + // bit: 1; mask: 0x0002; 0 = do not show gridlines, 1 = show gridlines $showGridlines = (bool) ((0x0002 & $options) >> 1); $this->_phpSheet->setShowGridlines($showGridlines); @@ -4131,8 +4271,62 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader if ($isActive) { $this->_phpExcel->setActiveSheetIndex($this->_phpExcel->getIndex($this->_phpSheet)); } + + // bit: 11; mask: 0x0800; 0 = normal view, 1 = page break view + $isPageBreakPreview = (bool) ((0x0800 & $options) >> 11); + + //FIXME: set $firstVisibleRow and $firstVisibleColumn + + if ($this->_phpSheet->getSheetView()->getView() !== PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_LAYOUT) { + //NOTE: this setting is inferior to page layout view(Excel2007-) + $view = $isPageBreakPreview? PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_BREAK_PREVIEW : + PHPExcel_Worksheet_SheetView::SHEETVIEW_NORMAL; + $this->_phpSheet->getSheetView()->setView($view); + if ($this->_version === self::XLS_BIFF8) { + $zoomScale = $isPageBreakPreview? $zoomscaleInPageBreakPreview : $zoomscaleInNormalView; + $this->_phpSheet->getSheetView()->setZoomScale($zoomScale); + $this->_phpSheet->getSheetView()->setZoomScaleNormal($zoomscaleInNormalView); + } + } } + /** + * Read PLV Record(Created by Excel2007 or upper) + */ + private function _readPageLayoutView(){ + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + //var_dump(unpack("vrt/vgrbitFrt/V2reserved/vwScalePLV/vgrbit", $recordData)); + + // offset: 0; size: 2; rt + //->ignore + $rt = self::_GetInt2d($recordData, 0); + // offset: 2; size: 2; grbitfr + //->ignore + $grbitFrt = self::_GetInt2d($recordData, 2); + // offset: 4; size: 8; reserved + //->ignore + + // offset: 12; size 2; zoom scale + $wScalePLV = self::_GetInt2d($recordData, 12); + // offset: 14; size 2; grbit + $grbit = self::_GetInt2d($recordData, 14); + + // decomprise grbit + $fPageLayoutView = $grbit & 0x01; + $fRulerVisible = ($grbit >> 1) & 0x01; //no support + $fWhitespaceHidden = ($grbit >> 3) & 0x01; //no support + + if ($fPageLayoutView === 1) { + $this->_phpSheet->getSheetView()->setView(PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_LAYOUT); + $this->_phpSheet->getSheetView()->setZoomScale($wScalePLV); //set by Excel2007 only if SHEETVIEW_PAGE_LAYOUT + } + //otherwise, we cannot know whether SHEETVIEW_PAGE_LAYOUT or SHEETVIEW_PAGE_BREAK_PREVIEW. + } /** * Read SCL record @@ -4140,7 +4334,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readScl() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -4162,7 +4356,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readPane() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -4190,7 +4384,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readSelection() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -4267,7 +4461,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readMergedCells() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -4290,7 +4484,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readHyperLink() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer forward to next record $this->_pos += 4 + $length; @@ -4299,7 +4493,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // offset: 0; size: 8; cell range address of all cells containing this hyperlink try { $cellRange = $this->_readBIFF8CellRangeAddressFixed($recordData, 0, 8); - } catch (Exception $e) { + } catch (PHPExcel_Exception $e) { return; } @@ -4466,7 +4660,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readDataValidations() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer forward to next record $this->_pos += 4 + $length; @@ -4479,7 +4673,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readDataValidation() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer forward to next record $this->_pos += 4 + $length; @@ -4583,7 +4777,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader if ($type == PHPExcel_Cell_DataValidation::TYPE_LIST) { $formula1 = str_replace(chr(0), ',', $formula1); } - } catch (Exception $e) { + } catch (PHPExcel_Exception $e) { return; } $offset += $sz1; @@ -4600,7 +4794,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $formula2 = pack('v', $sz2) . $formula2; // prepend the length try { $formula2 = $this->_getFormulaFromStructure($formula2); - } catch (Exception $e) { + } catch (PHPExcel_Exception $e) { return; } $offset += $sz2; @@ -4639,7 +4833,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readSheetLayout() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -4679,7 +4873,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readSheetProtection() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -4780,7 +4974,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readRangeProtection() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // move stream pointer to next record $this->_pos += 4 + $length; @@ -4812,7 +5006,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader for ($i = 0; $i < $cref; ++$i) { try { $cellRange = $this->_readBIFF8CellRangeAddressFixed(substr($recordData, 27 + 8 * $i, 8)); - } catch (Exception $e) { + } catch (PHPExcel_Exception $e) { return; } $cellRanges[] = $cellRange; @@ -4924,7 +5118,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader private function _readContinue() { $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $recordData = substr($this->_data, $this->_pos + 4, $length); + $recordData = $this->_readRecordData($this->_data, $this->_pos + 4, $length); // check if we are reading drawing data // this is in case a free CONTINUE record occurs in other circumstances we are unaware of @@ -4989,7 +5183,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $identifier = self::_GetInt2d($this->_data, $this->_pos); // offset: 2; size: 2; length $length = self::_GetInt2d($this->_data, $this->_pos + 2); - $data .= substr($this->_data, $this->_pos + 4, $length); + $data .= $this->_readRecordData($this->_data, $this->_pos + 4, $length); $spliceOffsets[$i] = $spliceOffsets[$i - 1] + $length; @@ -5244,7 +5438,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader * @param string Formula data * @param string $baseCell Base cell, only needed when formula contains tRefN tokens, e.g. with shared formulas * @return array - * @throws Exception + * @throws PHPExcel_Reader_Exception */ private function _getNextToken($formulaData, $baseCell = 'A1') { @@ -5345,7 +5539,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $spacetype = 'type5'; break; default: - throw new Exception('Unrecognized space type in tAttrSpace token'); + throw new PHPExcel_Reader_Exception('Unrecognized space type in tAttrSpace token'); break; } // offset: 3; size: 1; number of inserted spaces/carriage returns @@ -5354,7 +5548,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $data = array('spacetype' => $spacetype, 'spacecount' => $spacecount); break; default: - throw new Exception('Unrecognized attribute flag in tAttr token'); + throw new PHPExcel_Reader_Exception('Unrecognized attribute flag in tAttr token'); break; } break; @@ -5559,7 +5753,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case 360: $function = 'PHONETIC'; $args = 1; break; case 368: $function = 'BAHTTEXT'; $args = 1; break; default: - throw new Exception('Unrecognized function in formula'); + throw new PHPExcel_Reader_Exception('Unrecognized function in formula'); break; } $data = array('function' => $function, 'args' => $args); @@ -5663,7 +5857,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case 366: $function = 'STDEVA'; break; case 367: $function = 'VARA'; break; default: - throw new Exception('Unrecognized function in formula'); + throw new PHPExcel_Reader_Exception('Unrecognized function in formula'); break; } $data = array('function' => $function, 'args' => $args); @@ -5764,7 +5958,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $cellAddress = $this->_readBIFF8CellAddress(substr($formulaData, 3, 4)); $data = "$sheetRange!$cellAddress"; - } catch (Exception $e) { + } catch (PHPExcel_Exception $e) { // deleted sheet reference $data = '#REF!'; } @@ -5783,7 +5977,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader $cellRangeAddress = $this->_readBIFF8CellRangeAddress(substr($formulaData, 3, 8)); $data = "$sheetRange!$cellRangeAddress"; - } catch (Exception $e) { + } catch (PHPExcel_Exception $e) { // deleted sheet reference $data = '#REF!'; } @@ -5791,7 +5985,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader break; // Unknown cases // don't know how to deal with default: - throw new Exception('Unrecognized token ' . sprintf('%02X', $id) . ' in formula'); + throw new PHPExcel_Reader_Exception('Unrecognized token ' . sprintf('%02X', $id) . ' in formula'); break; } @@ -5885,7 +6079,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader * * @param string $subData * @return string - * @throws Exception + * @throws PHPExcel_Reader_Exception */ private function _readBIFF5CellRangeAddressFixed($subData) { @@ -5903,7 +6097,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // check values if ($fr > $lr || $fc > $lc) { - throw new Exception('Not a cell range address'); + throw new PHPExcel_Reader_Exception('Not a cell range address'); } // column index to letter @@ -5924,7 +6118,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader * * @param string $subData * @return string - * @throws Exception + * @throws PHPExcel_Reader_Exception */ private function _readBIFF8CellRangeAddressFixed($subData) { @@ -5942,7 +6136,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader // check values if ($fr > $lr || $fc > $lc) { - throw new Exception('Not a cell range address'); + throw new PHPExcel_Reader_Exception('Not a cell range address'); } // column index to letter @@ -6152,11 +6346,11 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader * Get a sheet range like Sheet1:Sheet3 from REF index * Note: If there is only one sheet in the range, one gets e.g Sheet1 * It can also happen that the REF structure uses the -1 (FFFF) code to indicate deleted sheets, - * in which case an exception is thrown + * in which case an PHPExcel_Reader_Exception is thrown * * @param int $index * @return string|false - * @throws Exception + * @throws PHPExcel_Reader_Exception */ private function _readSheetRangeByRefIndex($index) { @@ -6168,7 +6362,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader case 'internal': // check if we have a deleted 3d reference if ($this->_ref[$index]['firstSheetIndex'] == 0xFFFF or $this->_ref[$index]['lastSheetIndex'] == 0xFFFF) { - throw new Exception('Deleted sheet reference'); + throw new PHPExcel_Reader_Exception('Deleted sheet reference'); } // we have normal sheet range (collapsed or uncollapsed) @@ -6198,7 +6392,7 @@ class PHPExcel_Reader_Excel5 implements PHPExcel_Reader_IReader default: // TODO: external sheet support - throw new Exception('Excel5 reader only supports internal sheets in fomulas'); + throw new PHPExcel_Reader_Exception('Excel5 reader only supports internal sheets in fomulas'); break; } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Reader/Excel5/Escher.php b/htdocs/includes/phpexcel/PHPExcel/Reader/Excel5/Escher.php index e167655ffd6..3ed82c62ae6 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Reader/Excel5/Escher.php +++ b/htdocs/includes/phpexcel/PHPExcel/Reader/Excel5/Escher.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader_Excel5 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Reader_Excel5 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Reader_Excel5_Escher { diff --git a/htdocs/includes/phpexcel/PHPExcel/Reader/Excel5/MD5.php b/htdocs/includes/phpexcel/PHPExcel/Reader/Excel5/MD5.php new file mode 100644 index 00000000000..946d5a0da70 --- /dev/null +++ b/htdocs/includes/phpexcel/PHPExcel/Reader/Excel5/MD5.php @@ -0,0 +1,221 @@ +reset(); + } + + + /** + * Reset the MD5 stream context + */ + public function reset() + { + $this->a = 0x67452301; + $this->b = 0xEFCDAB89; + $this->c = 0x98BADCFE; + $this->d = 0x10325476; + } + + + /** + * Get MD5 stream context + * + * @return string + */ + public function getContext() + { + $s = ''; + foreach (array('a', 'b', 'c', 'd') as $i) { + $v = $this->{$i}; + $s .= chr($v & 0xff); + $s .= chr(($v >> 8) & 0xff); + $s .= chr(($v >> 16) & 0xff); + $s .= chr(($v >> 24) & 0xff); + } + + return $s; + } + + + /** + * Add data to context + * + * @param string $data Data to add + */ + public function add($data) + { + $words = array_values(unpack('V16', $data)); + + $A = $this->a; + $B = $this->b; + $C = $this->c; + $D = $this->d; + + $F = array('PHPExcel_Reader_Excel5_MD5','F'); + $G = array('PHPExcel_Reader_Excel5_MD5','G'); + $H = array('PHPExcel_Reader_Excel5_MD5','H'); + $I = array('PHPExcel_Reader_Excel5_MD5','I'); + + /* ROUND 1 */ + self::step($F, $A, $B, $C, $D, $words[0], 7, 0xd76aa478); + self::step($F, $D, $A, $B, $C, $words[1], 12, 0xe8c7b756); + self::step($F, $C, $D, $A, $B, $words[2], 17, 0x242070db); + self::step($F, $B, $C, $D, $A, $words[3], 22, 0xc1bdceee); + self::step($F, $A, $B, $C, $D, $words[4], 7, 0xf57c0faf); + self::step($F, $D, $A, $B, $C, $words[5], 12, 0x4787c62a); + self::step($F, $C, $D, $A, $B, $words[6], 17, 0xa8304613); + self::step($F, $B, $C, $D, $A, $words[7], 22, 0xfd469501); + self::step($F, $A, $B, $C, $D, $words[8], 7, 0x698098d8); + self::step($F, $D, $A, $B, $C, $words[9], 12, 0x8b44f7af); + self::step($F, $C, $D, $A, $B, $words[10], 17, 0xffff5bb1); + self::step($F, $B, $C, $D, $A, $words[11], 22, 0x895cd7be); + self::step($F, $A, $B, $C, $D, $words[12], 7, 0x6b901122); + self::step($F, $D, $A, $B, $C, $words[13], 12, 0xfd987193); + self::step($F, $C, $D, $A, $B, $words[14], 17, 0xa679438e); + self::step($F, $B, $C, $D, $A, $words[15], 22, 0x49b40821); + + /* ROUND 2 */ + self::step($G, $A, $B, $C, $D, $words[1], 5, 0xf61e2562); + self::step($G, $D, $A, $B, $C, $words[6], 9, 0xc040b340); + self::step($G, $C, $D, $A, $B, $words[11], 14, 0x265e5a51); + self::step($G, $B, $C, $D, $A, $words[0], 20, 0xe9b6c7aa); + self::step($G, $A, $B, $C, $D, $words[5], 5, 0xd62f105d); + self::step($G, $D, $A, $B, $C, $words[10], 9, 0x02441453); + self::step($G, $C, $D, $A, $B, $words[15], 14, 0xd8a1e681); + self::step($G, $B, $C, $D, $A, $words[4], 20, 0xe7d3fbc8); + self::step($G, $A, $B, $C, $D, $words[9], 5, 0x21e1cde6); + self::step($G, $D, $A, $B, $C, $words[14], 9, 0xc33707d6); + self::step($G, $C, $D, $A, $B, $words[3], 14, 0xf4d50d87); + self::step($G, $B, $C, $D, $A, $words[8], 20, 0x455a14ed); + self::step($G, $A, $B, $C, $D, $words[13], 5, 0xa9e3e905); + self::step($G, $D, $A, $B, $C, $words[2], 9, 0xfcefa3f8); + self::step($G, $C, $D, $A, $B, $words[7], 14, 0x676f02d9); + self::step($G, $B, $C, $D, $A, $words[12], 20, 0x8d2a4c8a); + + /* ROUND 3 */ + self::step($H, $A, $B, $C, $D, $words[5], 4, 0xfffa3942); + self::step($H, $D, $A, $B, $C, $words[8], 11, 0x8771f681); + self::step($H, $C, $D, $A, $B, $words[11], 16, 0x6d9d6122); + self::step($H, $B, $C, $D, $A, $words[14], 23, 0xfde5380c); + self::step($H, $A, $B, $C, $D, $words[1], 4, 0xa4beea44); + self::step($H, $D, $A, $B, $C, $words[4], 11, 0x4bdecfa9); + self::step($H, $C, $D, $A, $B, $words[7], 16, 0xf6bb4b60); + self::step($H, $B, $C, $D, $A, $words[10], 23, 0xbebfbc70); + self::step($H, $A, $B, $C, $D, $words[13], 4, 0x289b7ec6); + self::step($H, $D, $A, $B, $C, $words[0], 11, 0xeaa127fa); + self::step($H, $C, $D, $A, $B, $words[3], 16, 0xd4ef3085); + self::step($H, $B, $C, $D, $A, $words[6], 23, 0x04881d05); + self::step($H, $A, $B, $C, $D, $words[9], 4, 0xd9d4d039); + self::step($H, $D, $A, $B, $C, $words[12], 11, 0xe6db99e5); + self::step($H, $C, $D, $A, $B, $words[15], 16, 0x1fa27cf8); + self::step($H, $B, $C, $D, $A, $words[2], 23, 0xc4ac5665); + + /* ROUND 4 */ + self::step($I, $A, $B, $C, $D, $words[0], 6, 0xf4292244); + self::step($I, $D, $A, $B, $C, $words[7], 10, 0x432aff97); + self::step($I, $C, $D, $A, $B, $words[14], 15, 0xab9423a7); + self::step($I, $B, $C, $D, $A, $words[5], 21, 0xfc93a039); + self::step($I, $A, $B, $C, $D, $words[12], 6, 0x655b59c3); + self::step($I, $D, $A, $B, $C, $words[3], 10, 0x8f0ccc92); + self::step($I, $C, $D, $A, $B, $words[10], 15, 0xffeff47d); + self::step($I, $B, $C, $D, $A, $words[1], 21, 0x85845dd1); + self::step($I, $A, $B, $C, $D, $words[8], 6, 0x6fa87e4f); + self::step($I, $D, $A, $B, $C, $words[15], 10, 0xfe2ce6e0); + self::step($I, $C, $D, $A, $B, $words[6], 15, 0xa3014314); + self::step($I, $B, $C, $D, $A, $words[13], 21, 0x4e0811a1); + self::step($I, $A, $B, $C, $D, $words[4], 6, 0xf7537e82); + self::step($I, $D, $A, $B, $C, $words[11], 10, 0xbd3af235); + self::step($I, $C, $D, $A, $B, $words[2], 15, 0x2ad7d2bb); + self::step($I, $B, $C, $D, $A, $words[9], 21, 0xeb86d391); + + $this->a = ($this->a + $A) & 0xffffffff; + $this->b = ($this->b + $B) & 0xffffffff; + $this->c = ($this->c + $C) & 0xffffffff; + $this->d = ($this->d + $D) & 0xffffffff; + } + + + private static function F($X, $Y, $Z) + { + return (($X & $Y) | ((~ $X) & $Z)); // X AND Y OR NOT X AND Z + } + + + private static function G($X, $Y, $Z) + { + return (($X & $Z) | ($Y & (~ $Z))); // X AND Z OR Y AND NOT Z + } + + + private static function H($X, $Y, $Z) + { + return ($X ^ $Y ^ $Z); // X XOR Y XOR Z + } + + + private static function I($X, $Y, $Z) + { + return ($Y ^ ($X | (~ $Z))) ; // Y XOR (X OR NOT Z) + } + + + private static function step($func, &$A, $B, $C, $D, $M, $s, $t) + { + $A = ($A + call_user_func($func, $B, $C, $D) + $M + $t) & 0xffffffff; + $A = self::rotate($A, $s); + $A = ($B + $A) & 0xffffffff; + } + + + private static function rotate($decimal, $bits) + { + $binary = str_pad(decbin($decimal), 32, "0", STR_PAD_LEFT); + return bindec(substr($binary, $bits).substr($binary, 0, $bits)); + } +} \ No newline at end of file diff --git a/htdocs/includes/phpexcel/PHPExcel/Reader/Excel5/RC4.php b/htdocs/includes/phpexcel/PHPExcel/Reader/Excel5/RC4.php new file mode 100644 index 00000000000..dc6327c0490 --- /dev/null +++ b/htdocs/includes/phpexcel/PHPExcel/Reader/Excel5/RC4.php @@ -0,0 +1,88 @@ +i = 0; $this->i < 256; $this->i++) { + $this->s[$this->i] = $this->i; + } + + $this->j = 0; + for ($this->i = 0; $this->i < 256; $this->i++) { + $this->j = ($this->j + $this->s[$this->i] + ord($key[$this->i % $len])) % 256; + $t = $this->s[$this->i]; + $this->s[$this->i] = $this->s[$this->j]; + $this->s[$this->j] = $t; + } + $this->i = $this->j = 0; + } + + /** + * Symmetric decryption/encryption function + * + * @param string $data Data to encrypt/decrypt + * + * @return string + */ + public function RC4($data) + { + $len = strlen($data); + for ($c = 0; $c < $len; $c++) { + $this->i = ($this->i + 1) % 256; + $this->j = ($this->j + $this->s[$this->i]) % 256; + $t = $this->s[$this->i]; + $this->s[$this->i] = $this->s[$this->j]; + $this->s[$this->j] = $t; + + $t = ($this->s[$this->i] + $this->s[$this->j]) % 256; + + $data[$c] = chr(ord($data[$c]) ^ $this->s[$t]); + } + return $data; + } +} diff --git a/htdocs/includes/phpexcel/PHPExcel/Reader/Exception.php b/htdocs/includes/phpexcel/PHPExcel/Reader/Exception.php new file mode 100644 index 00000000000..f42a1aafca2 --- /dev/null +++ b/htdocs/includes/phpexcel/PHPExcel/Reader/Exception.php @@ -0,0 +1,52 @@ +line = $line; + $e->file = $file; + throw $e; + } +} diff --git a/htdocs/includes/phpexcel/PHPExcel/Reader/Gnumeric.php b/htdocs/includes/phpexcel/PHPExcel/Reader/Gnumeric.php index 5d82f22924f..6db7c4969ee 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Reader/Gnumeric.php +++ b/htdocs/includes/phpexcel/PHPExcel/Reader/Gnumeric.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -40,27 +40,10 @@ if (!defined('PHPEXCEL_ROOT')) { * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Reader_Gnumeric implements PHPExcel_Reader_IReader +class PHPExcel_Reader_Gnumeric extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader { - /** - * Read data only? - * Identifies whether the Reader should only read data values for cells, and ignore any formatting information; - * or whether it should read both data and formatting - * - * @var boolean - */ - private $_readDataOnly = false; - - /** - * Restrict which sheets should be loaded? - * This property holds an array of worksheet names to be loaded. If null, then all worksheets will be loaded. - * - * @var array of string - */ - private $_loadSheetsOnly = null; - /** * Formats * @@ -77,13 +60,6 @@ class PHPExcel_Reader_Gnumeric implements PHPExcel_Reader_IReader private $_referenceHelper = null; - /** - * PHPExcel_Reader_IReadFilter instance - * - * @var PHPExcel_Reader_IReadFilter - */ - private $_readFilter = null; - /** * Create a new PHPExcel_Reader_Gnumeric @@ -94,115 +70,23 @@ class PHPExcel_Reader_Gnumeric implements PHPExcel_Reader_IReader } - /** - * Read data only? - * If this is true, then the Reader will only read data values for cells, it will not read any formatting information. - * If false (the default) it will read data and formatting. - * - * @return boolean - */ - public function getReadDataOnly() { - return $this->_readDataOnly; - } - - - /** - * Set read data only - * Set to true, to advise the Reader only to read data values for cells, and to ignore any formatting information. - * Set to false (the default) to advise the Reader to read both data and formatting for cells. - * - * @param boolean $pValue - * - * @return PHPExcel_Reader_Gnumeric - */ - public function setReadDataOnly($pValue = false) { - $this->_readDataOnly = $pValue; - return $this; - } - - - /** - * Get which sheets to load - * Returns either an array of worksheet names (the list of worksheets that should be loaded), or a null - * indicating that all worksheets in the workbook should be loaded. - * - * @return mixed - */ - public function getLoadSheetsOnly() - { - return $this->_loadSheetsOnly; - } - - - /** - * Set which sheets to load - * - * @param mixed $value - * This should be either an array of worksheet names to be loaded, or a string containing a single worksheet name. - * If NULL, then it tells the Reader to read all worksheets in the workbook - * - * @return PHPExcel_Reader_Gnumeric - */ - public function setLoadSheetsOnly($value = null) - { - $this->_loadSheetsOnly = is_array($value) ? - $value : array($value); - return $this; - } - - - /** - * Set all sheets to load - * Tells the Reader to load all worksheets from the workbook. - * - * @return PHPExcel_Reader_Gnumeric - */ - public function setLoadAllSheets() - { - $this->_loadSheetsOnly = null; - return $this; - } - - - /** - * Read filter - * - * @return PHPExcel_Reader_IReadFilter - */ - public function getReadFilter() { - return $this->_readFilter; - } - - - /** - * Set read filter - * - * @param PHPExcel_Reader_IReadFilter $pValue - * @return PHPExcel_Reader_Gnumeric - */ - public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) { - $this->_readFilter = $pValue; - return $this; - } - - /** * Can the current PHPExcel_Reader_IReader read the file? * - * @param string $pFileName + * @param string $pFilename * @return boolean - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function canRead($pFilename) { // Check if file exists if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); } // Check if gzlib functions are available if (!function_exists('gzread')) { - throw new Exception("gzlib library is not enabled"); + throw new PHPExcel_Reader_Exception("gzlib library is not enabled"); } // Read signature data (first 3 bytes) @@ -218,50 +102,87 @@ class PHPExcel_Reader_Gnumeric implements PHPExcel_Reader_IReader } + /** + * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetNames($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $xml = new XMLReader(); + $xml->open( + 'compress.zlib://'.realpath($pFilename), null, PHPExcel_Settings::getLibXmlLoaderOptions() + ); + $xml->setParserProperty(2,true); + + $worksheetNames = array(); + while ($xml->read()) { + if ($xml->name == 'gnm:SheetName' && $xml->nodeType == XMLReader::ELEMENT) { + $xml->read(); // Move onto the value node + $worksheetNames[] = (string) $xml->value; + } elseif ($xml->name == 'gnm:Sheets') { + // break out of the loop once we've got our sheet names rather than parse the entire file + break; + } + } + + return $worksheetNames; + } + + /** * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) * * @param string $pFilename - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function listWorksheetInfo($pFilename) { // Check if file exists if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); } - $gFileData = $this->_gzfileGetContents($pFilename); - - $xml = simplexml_load_string($gFileData); - $namespacesMeta = $xml->getNamespaces(true); - - $gnmXML = $xml->children($namespacesMeta['gnm']); + $xml = new XMLReader(); + $xml->open( + 'compress.zlib://'.realpath($pFilename), null, PHPExcel_Settings::getLibXmlLoaderOptions() + ); + $xml->setParserProperty(2,true); $worksheetInfo = array(); + while ($xml->read()) { + if ($xml->name == 'gnm:Sheet' && $xml->nodeType == XMLReader::ELEMENT) { + $tmpInfo = array( + 'worksheetName' => '', + 'lastColumnLetter' => 'A', + 'lastColumnIndex' => 0, + 'totalRows' => 0, + 'totalColumns' => 0, + ); - foreach ($gnmXML->Sheets->Sheet as $sheet) { - $tmpInfo = array(); - $tmpInfo['worksheetName'] = (string) $sheet->Name; - $tmpInfo['lastColumnLetter'] = 'A'; - $tmpInfo['lastColumnIndex'] = 0; - $tmpInfo['totalRows'] = 0; - $tmpInfo['totalColumns'] = 0; - - foreach ($sheet->Cells->Cell as $cell) { - $cellAttributes = $cell->attributes(); - - $rowIndex = (int) $cellAttributes->Row + 1; - $columnIndex = (int) $cellAttributes->Col; - - $tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex); - $tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex); + while ($xml->read()) { + if ($xml->name == 'gnm:Name' && $xml->nodeType == XMLReader::ELEMENT) { + $xml->read(); // Move onto the value node + $tmpInfo['worksheetName'] = (string) $xml->value; + } elseif ($xml->name == 'gnm:MaxCol' && $xml->nodeType == XMLReader::ELEMENT) { + $xml->read(); // Move onto the value node + $tmpInfo['lastColumnIndex'] = (int) $xml->value; + $tmpInfo['totalColumns'] = (int) $xml->value + 1; + } elseif ($xml->name == 'gnm:MaxRow' && $xml->nodeType == XMLReader::ELEMENT) { + $xml->read(); // Move onto the value node + $tmpInfo['totalRows'] = (int) $xml->value + 1; + break; + } + } + $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); + $worksheetInfo[] = $tmpInfo; } - - $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); - $tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1; - - $worksheetInfo[] = $tmpInfo; } return $worksheetInfo; @@ -286,7 +207,7 @@ class PHPExcel_Reader_Gnumeric implements PHPExcel_Reader_IReader * * @param string $pFilename * @return PHPExcel - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function load($pFilename) { @@ -298,49 +219,19 @@ class PHPExcel_Reader_Gnumeric implements PHPExcel_Reader_IReader } - /** - * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object - * - * @param string $pFilename - * @throws Exception - */ - public function listWorksheetNames($pFilename) - { - // Check if file exists - if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } - - $gFileData = $this->_gzfileGetContents($pFilename); - - $xml = simplexml_load_string($gFileData); - $namespacesMeta = $xml->getNamespaces(true); - - $gnmXML = $xml->children($namespacesMeta['gnm']); - - $worksheetNames = array(); - - foreach($gnmXML->Sheets->Sheet as $sheet) { - $worksheetNames[] = (string) $sheet->Name; - } - - return $worksheetNames; - } - - /** * Loads PHPExcel from file into PHPExcel instance * * @param string $pFilename * @param PHPExcel $objPHPExcel * @return PHPExcel - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) { // Check if file exists if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); } $timezoneObj = new DateTimeZone('Europe/London'); @@ -352,7 +243,7 @@ class PHPExcel_Reader_Gnumeric implements PHPExcel_Reader_IReader // echo htmlentities($gFileData,ENT_QUOTES,'UTF-8'); // echo '
'; // - $xml = simplexml_load_string($gFileData); + $xml = simplexml_load_string($gFileData, 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); $namespacesMeta = $xml->getNamespaces(true); // var_dump($namespacesMeta); @@ -620,7 +511,7 @@ class PHPExcel_Reader_Gnumeric implements PHPExcel_Reader_IReader // We still set the number format mask for date/time values, even if _readDataOnly is true if ((!$this->_readDataOnly) || - (PHPExcel_Shared_Date::isDateTimeFormatCode($styleArray['numberformat']['code']))) { + (PHPExcel_Shared_Date::isDateTimeFormatCode((string) $styleAttributes['Format']))) { $styleArray = array(); $styleArray['numberformat']['code'] = (string) $styleAttributes['Format']; // If _readDataOnly is false, we set all formatting information diff --git a/htdocs/includes/phpexcel/PHPExcel/Reader/HTML.php b/htdocs/includes/phpexcel/PHPExcel/Reader/HTML.php index d6068eaa4f4..1696471029d 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Reader/HTML.php +++ b/htdocs/includes/phpexcel/PHPExcel/Reader/HTML.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -40,9 +40,9 @@ if (!defined('PHPEXCEL_ROOT')) { * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Reader_HTML implements PHPExcel_Reader_IReader +class PHPExcel_Reader_HTML extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader { /** * Input encoding @@ -100,13 +100,6 @@ class PHPExcel_Reader_HTML implements PHPExcel_Reader_IReader ), // Bottom border ); - /** - * PHPExcel_Reader_IReadFilter instance - * - * @var PHPExcel_Reader_IReadFilter - */ - private $_readFilter = null; - /** * Create a new PHPExcel_Reader_HTML @@ -116,25 +109,20 @@ class PHPExcel_Reader_HTML implements PHPExcel_Reader_IReader } /** - * Can the current PHPExcel_Reader_IReader read the file? + * Validate that the current file is an HTML file * - * @param string $pFileName - * @return boolean - * @throws Exception + * @return boolean */ - public function canRead($pFilename) + protected function _isValidFormat() { - // Check if file exists - if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + // Reading 2048 bytes should be enough to validate that the format is HTML + $data = fread($this->_fileHandle, 2048); + if ((strpos($data, '<') !== FALSE) && + (strlen($data) !== strlen(strip_tags($data)))) { + return TRUE; } - // Read sample data (first 2 KB will do) - $fh = fopen($pFilename, 'r'); - $data = fread($fh, 2048); - fclose($fh); - - return true; + return FALSE; } /** @@ -142,7 +130,7 @@ class PHPExcel_Reader_HTML implements PHPExcel_Reader_IReader * * @param string $pFilename * @return PHPExcel - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function load($pFilename) { @@ -153,25 +141,6 @@ class PHPExcel_Reader_HTML implements PHPExcel_Reader_IReader return $this->loadIntoExisting($pFilename, $objPHPExcel); } - /** - * Read filter - * - * @return PHPExcel_Reader_IReadFilter - */ - public function getReadFilter() { - return $this->_readFilter; - } - - /** - * Set read filter - * - * @param PHPExcel_Reader_IReadFilter $pValue - */ - public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) { - $this->_readFilter = $pValue; - return $this; - } - /** * Set input encoding * @@ -222,7 +191,7 @@ class PHPExcel_Reader_HTML implements PHPExcel_Reader_IReader // Simple String content if (trim($cellContent) > '') { // Only actually write it if there's content in the string - echo 'FLUSH CELL: ' , $column , $row , ' => ' , $cellContent , '
'; +// echo 'FLUSH CELL: ' , $column , $row , ' => ' , $cellContent , '
'; // Write to worksheet to be done here... // ... we return the cell so we can mess about with styles more easily $cell = $sheet->setCellValue($column.$row,$cellContent,true); @@ -238,7 +207,7 @@ class PHPExcel_Reader_HTML implements PHPExcel_Reader_IReader private function _processDomElement(DOMNode $element, $sheet, &$row, &$column, &$cellContent){ foreach($element->childNodes as $child){ - if ($child instanceOf DOMText) { + if ($child instanceof DOMText) { $domText = preg_replace('/\s+/',' ',trim($child->nodeValue)); if (is_string($cellContent)) { // simply append the text if the cell content is a plain text string @@ -247,12 +216,12 @@ class PHPExcel_Reader_HTML implements PHPExcel_Reader_IReader // but if we have a rich text run instead, we need to append it correctly // TODO } - } elseif($child instanceOf DOMElement) { - echo 'DOM ELEMENT: ' , strtoupper($child->nodeName) , '
'; + } elseif($child instanceof DOMElement) { +// echo 'DOM ELEMENT: ' , strtoupper($child->nodeName) , '
'; $attributeArray = array(); foreach($child->attributes as $attribute) { - echo 'ATTRIBUTE: ' , $attribute->name , ' => ' , $attribute->value , '
'; +// echo 'ATTRIBUTE: ' , $attribute->name , ' => ' , $attribute->value , '
'; $attributeArray[$attribute->name] = $attribute->value; } @@ -280,13 +249,13 @@ class PHPExcel_Reader_HTML implements PHPExcel_Reader_IReader case 'em' : case 'strong': case 'b' : - echo 'STYLING, SPAN OR DIV
'; +// echo 'STYLING, SPAN OR DIV
'; if ($cellContent > '') $cellContent .= ' '; $this->_processDomElement($child,$sheet,$row,$column,$cellContent); if ($cellContent > '') $cellContent .= ' '; - echo 'END OF STYLING, SPAN OR DIV
'; +// echo 'END OF STYLING, SPAN OR DIV
'; break; case 'hr' : $this->_flushCell($sheet,$column,$row,$cellContent); @@ -307,14 +276,14 @@ class PHPExcel_Reader_HTML implements PHPExcel_Reader_IReader $this->_flushCell($sheet,$column,$row,$cellContent); ++$row; } - echo 'HARD LINE BREAK: ' , '
'; +// echo 'HARD LINE BREAK: ' , '
'; break; case 'a' : - echo 'START OF HYPERLINK: ' , '
'; +// echo 'START OF HYPERLINK: ' , '
'; foreach($attributeArray as $attributeName => $attributeValue) { switch($attributeName) { case 'href': - echo 'Link to ' , $attributeValue , '
'; +// echo 'Link to ' , $attributeValue , '
'; $sheet->getCell($column.$row)->getHyperlink()->setUrl($attributeValue); if (isset($this->_formats[$child->nodeName])) { $sheet->getStyle($column.$row)->applyFromArray($this->_formats[$child->nodeName]); @@ -324,7 +293,7 @@ class PHPExcel_Reader_HTML implements PHPExcel_Reader_IReader } $cellContent .= ' '; $this->_processDomElement($child,$sheet,$row,$column,$cellContent); - echo 'END OF HYPERLINK:' , '
'; +// echo 'END OF HYPERLINK:' , '
'; break; case 'h1' : case 'h2' : @@ -338,17 +307,17 @@ class PHPExcel_Reader_HTML implements PHPExcel_Reader_IReader if ($this->_tableLevel > 0) { // If we're inside a table, replace with a \n $cellContent .= "\n"; - echo 'LIST ENTRY: ' , '
'; +// echo 'LIST ENTRY: ' , '
'; $this->_processDomElement($child,$sheet,$row,$column,$cellContent); - echo 'END OF LIST ENTRY:' , '
'; +// echo 'END OF LIST ENTRY:' , '
'; } else { if ($cellContent > '') { $this->_flushCell($sheet,$column,$row,$cellContent); $row += 2; } - echo 'START OF PARAGRAPH: ' , '
'; +// echo 'START OF PARAGRAPH: ' , '
'; $this->_processDomElement($child,$sheet,$row,$column,$cellContent); - echo 'END OF PARAGRAPH:' , '
'; +// echo 'END OF PARAGRAPH:' , '
'; $this->_flushCell($sheet,$column,$row,$cellContent); if (isset($this->_formats[$child->nodeName])) { @@ -363,17 +332,17 @@ class PHPExcel_Reader_HTML implements PHPExcel_Reader_IReader if ($this->_tableLevel > 0) { // If we're inside a table, replace with a \n $cellContent .= "\n"; - echo 'LIST ENTRY: ' , '
'; +// echo 'LIST ENTRY: ' , '
'; $this->_processDomElement($child,$sheet,$row,$column,$cellContent); - echo 'END OF LIST ENTRY:' , '
'; +// echo 'END OF LIST ENTRY:' , '
'; } else { if ($cellContent > '') { $this->_flushCell($sheet,$column,$row,$cellContent); } ++$row; - echo 'LIST ENTRY: ' , '
'; +// echo 'LIST ENTRY: ' , '
'; $this->_processDomElement($child,$sheet,$row,$column,$cellContent); - echo 'END OF LIST ENTRY:' , '
'; +// echo 'END OF LIST ENTRY:' , '
'; $this->_flushCell($sheet,$column,$row,$cellContent); $column = 'A'; } @@ -381,11 +350,11 @@ class PHPExcel_Reader_HTML implements PHPExcel_Reader_IReader case 'table' : $this->_flushCell($sheet,$column,$row,$cellContent); $column = $this->_setTableStartColumn($column); - echo 'START OF TABLE LEVEL ' , $this->_tableLevel , '
'; +// echo 'START OF TABLE LEVEL ' , $this->_tableLevel , '
'; if ($this->_tableLevel > 1) --$row; $this->_processDomElement($child,$sheet,$row,$column,$cellContent); - echo 'END OF TABLE LEVEL ' , $this->_tableLevel , '
'; +// echo 'END OF TABLE LEVEL ' , $this->_tableLevel , '
'; $column = $this->_releaseTableStartColumn(); if ($this->_tableLevel > 1) { ++$column; @@ -401,15 +370,15 @@ class PHPExcel_Reader_HTML implements PHPExcel_Reader_IReader ++$row; $column = $this->_getTableStartColumn(); $cellContent = ''; - echo 'START OF TABLE ' , $this->_tableLevel , ' ROW
'; +// echo 'START OF TABLE ' , $this->_tableLevel , ' ROW
'; $this->_processDomElement($child,$sheet,$row,$column,$cellContent); - echo 'END OF TABLE ' , $this->_tableLevel , ' ROW
'; +// echo 'END OF TABLE ' , $this->_tableLevel , ' ROW
'; break; case 'th' : case 'td' : - echo 'START OF TABLE ' , $this->_tableLevel , ' CELL
'; +// echo 'START OF TABLE ' , $this->_tableLevel , ' CELL
'; $this->_processDomElement($child,$sheet,$row,$column,$cellContent); - echo 'END OF TABLE ' , $this->_tableLevel , ' CELL
'; +// echo 'END OF TABLE ' , $this->_tableLevel , ' CELL
'; $this->_flushCell($sheet,$column,$row,$cellContent); ++$column; break; @@ -433,18 +402,18 @@ class PHPExcel_Reader_HTML implements PHPExcel_Reader_IReader * @param string $pFilename * @param PHPExcel $objPHPExcel * @return PHPExcel - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) { - // Check if file exists - if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } - - if (!is_file($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! The given file is not a regular file."); + // Open file to validate + $this->_openFile($pFilename); + if (!$this->_isValidFormat()) { + fclose ($this->_fileHandle); + throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid HTML file."); } + // Close after validating + fclose ($this->_fileHandle); // Create new PHPExcel while ($objPHPExcel->getSheetCount() <= $this->_sheetIndex) { @@ -454,10 +423,10 @@ class PHPExcel_Reader_HTML implements PHPExcel_Reader_IReader // Create a new DOM object $dom = new domDocument; - // Load the HTML file into the DOM object - $loaded = $dom->loadHTMLFile($pFilename); - if ($loaded === false) { - throw new Exception('Failed to load ',$pFilename,' as a DOM Document'); + // Reload the HTML file into the DOM object + $loaded = $dom->loadHTMLFile($pFilename, PHPExcel_Settings::getLibXmlLoaderOptions()); + if ($loaded === FALSE) { + throw new PHPExcel_Reader_Exception('Failed to load ',$pFilename,' as a DOM Document'); } // Discard white space @@ -469,8 +438,8 @@ class PHPExcel_Reader_HTML implements PHPExcel_Reader_IReader $content = ''; $this->_processDomElement($dom,$objPHPExcel->getActiveSheet(),$row,$column,$content); - echo '
'; - var_dump($this->_dataArray); +// echo '
'; +// var_dump($this->_dataArray); // Return return $objPHPExcel; diff --git a/htdocs/includes/phpexcel/PHPExcel/Reader/IReadFilter.php b/htdocs/includes/phpexcel/PHPExcel/Reader/IReadFilter.php index 50e92c8045a..5a691a5fb77 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Reader/IReadFilter.php +++ b/htdocs/includes/phpexcel/PHPExcel/Reader/IReadFilter.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ interface PHPExcel_Reader_IReadFilter { diff --git a/htdocs/includes/phpexcel/PHPExcel/Reader/IReader.php b/htdocs/includes/phpexcel/PHPExcel/Reader/IReader.php index 1c9884730b8..6c3e878e9f6 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Reader/IReader.php +++ b/htdocs/includes/phpexcel/PHPExcel/Reader/IReader.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,14 +31,14 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ interface PHPExcel_Reader_IReader { /** * Can the current PHPExcel_Reader_IReader read the file? * - * @param string $pFileName + * @param string $pFilename * @return boolean */ public function canRead($pFilename); @@ -46,8 +46,8 @@ interface PHPExcel_Reader_IReader /** * Loads PHPExcel from file * - * @param string $pFileName - * @throws Exception + * @param string $pFilename + * @throws PHPExcel_Reader_Exception */ public function load($pFilename); } diff --git a/htdocs/includes/phpexcel/PHPExcel/Reader/OOCalc.php b/htdocs/includes/phpexcel/PHPExcel/Reader/OOCalc.php index 22ad1173b4f..8ad7061ce90 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Reader/OOCalc.php +++ b/htdocs/includes/phpexcel/PHPExcel/Reader/OOCalc.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -40,27 +40,10 @@ if (!defined('PHPEXCEL_ROOT')) { * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Reader_OOCalc implements PHPExcel_Reader_IReader +class PHPExcel_Reader_OOCalc extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader { - /** - * Read data only? - * Identifies whether the Reader should only read data values for cells, and ignore any formatting information; - * or whether it should read both data and formatting - * - * @var boolean - */ - private $_readDataOnly = false; - - /** - * Restrict which sheets should be loaded? - * This property holds an array of worksheet names to be loaded. If null, then all worksheets will be loaded. - * - * @var array of string - */ - private $_loadSheetsOnly = null; - /** * Formats * @@ -68,13 +51,6 @@ class PHPExcel_Reader_OOCalc implements PHPExcel_Reader_IReader */ private $_styles = array(); - /** - * PHPExcel_Reader_IReadFilter instance - * - * @var PHPExcel_Reader_IReadFilter - */ - private $_readFilter = null; - /** * Create a new PHPExcel_Reader_OOCalc @@ -84,126 +60,48 @@ class PHPExcel_Reader_OOCalc implements PHPExcel_Reader_IReader } - /** - * Read data only? - * If this is true, then the Reader will only read data values for cells, it will not read any formatting information. - * If false (the default) it will read data and formatting. - * - * @return boolean - */ - public function getReadDataOnly() { - return $this->_readDataOnly; - } - - - /** - * Set read data only - * Set to true, to advise the Reader only to read data values for cells, and to ignore any formatting information. - * Set to false (the default) to advise the Reader to read both data and formatting for cells. - * - * @param boolean $pValue - * @return PHPExcel_Reader_OOCalc - */ - public function setReadDataOnly($pValue = false) { - $this->_readDataOnly = $pValue; - return $this; - } - - - /** - * Get which sheets to load - * Returns either an array of worksheet names (the list of worksheets that should be loaded), or a null - * indicating that all worksheets in the workbook should be loaded. - * - * @return mixed - */ - public function getLoadSheetsOnly() - { - return $this->_loadSheetsOnly; - } - - - /** - * Set which sheets to load - * - * @param mixed $value - * This should be either an array of worksheet names to be loaded, or a string containing a single worksheet name. - * If NULL, then it tells the Reader to read all worksheets in the workbook - * - * @return PHPExcel_Reader_OOCalc - */ - public function setLoadSheetsOnly($value = null) - { - $this->_loadSheetsOnly = is_array($value) ? - $value : array($value); - return $this; - } - - - /** - * Set all sheets to load - * Tells the Reader to load all worksheets from the workbook. - * - * @return PHPExcel_Reader_OOCalc - */ - public function setLoadAllSheets() - { - $this->_loadSheetsOnly = null; - return $this; - } - - - /** - * Read filter - * - * @return PHPExcel_Reader_IReadFilter - */ - public function getReadFilter() { - return $this->_readFilter; - } - - - /** - * Set read filter - * - * @param PHPExcel_Reader_IReadFilter $pValue - * @return PHPExcel_Reader_OOCalc - */ - public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) { - $this->_readFilter = $pValue; - return $this; - } - - /** * Can the current PHPExcel_Reader_IReader read the file? * - * @param string $pFileName + * @param string $pFilename * @return boolean - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function canRead($pFilename) { // Check if file exists if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); } + $zipClass = PHPExcel_Settings::getZipClass(); + // Check if zip class exists - if (!class_exists('ZipArchive',FALSE)) { - throw new Exception("ZipArchive library is not enabled"); - } +// if (!class_exists($zipClass, FALSE)) { +// throw new PHPExcel_Reader_Exception($zipClass . " library is not enabled"); +// } + $mimeType = 'UNKNOWN'; // Load file - $zip = new ZipArchive; + $zip = new $zipClass; if ($zip->open($pFilename) === true) { // check if it is an OOXML archive $stat = $zip->statName('mimetype'); if ($stat && ($stat['size'] <= 255)) { $mimeType = $zip->getFromName($stat['name']); - } else { - $zip->close(); - return FALSE; + } elseif($stat = $zip->statName('META-INF/manifest.xml')) { + $xml = simplexml_load_string($zip->getFromName('META-INF/manifest.xml'), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + $namespacesContent = $xml->getNamespaces(true); + if (isset($namespacesContent['manifest'])) { + $manifest = $xml->children($namespacesContent['manifest']); + foreach($manifest as $manifestDataSet) { + $manifestAttributes = $manifestDataSet->attributes($namespacesContent['manifest']); + if ($manifestAttributes->{'full-path'} == '/') { + $mimeType = (string) $manifestAttributes->{'media-type'}; + break; + } + } + } } $zip->close(); @@ -219,30 +117,46 @@ class PHPExcel_Reader_OOCalc implements PHPExcel_Reader_IReader * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object * * @param string $pFilename - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function listWorksheetNames($pFilename) { // Check if file exists if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $zipClass = PHPExcel_Settings::getZipClass(); + + $zip = new $zipClass; + if (!$zip->open($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! Error opening file."); } $worksheetNames = array(); - $zip = new ZipArchive; - if ($zip->open($pFilename) === true) { + $xml = new XMLReader(); + $res = $xml->open('zip://'.realpath($pFilename).'#content.xml', null, PHPExcel_Settings::getLibXmlLoaderOptions()); + $xml->setParserProperty(2,true); - $xml = simplexml_load_string($zip->getFromName("content.xml")); - $namespacesContent = $xml->getNamespaces(true); - - $workbook = $xml->children($namespacesContent['office']); - foreach($workbook->body->spreadsheet as $workbookData) { - $workbookData = $workbookData->children($namespacesContent['table']); - foreach($workbookData->table as $worksheetDataSet) { - $worksheetDataAttributes = $worksheetDataSet->attributes($namespacesContent['table']); - - $worksheetNames[] = $worksheetDataAttributes['name']; + // Step into the first level of content of the XML + $xml->read(); + while ($xml->read()) { + // Quickly jump through to the office:body node + while ($xml->name !== 'office:body') { + if ($xml->isEmptyElement) + $xml->read(); + else + $xml->next(); + } + // Now read each node until we find our first table:table node + while ($xml->read()) { + if ($xml->name == 'table:table' && $xml->nodeType == XMLReader::ELEMENT) { + // Loop through each table:table node reading the table:name attribute for each worksheet name + do { + $worksheetNames[] = $xml->getAttribute('table:name'); + $xml->next(); + } while ($xml->name == 'table:table' && $xml->nodeType == XMLReader::ELEMENT); } } } @@ -251,12 +165,137 @@ class PHPExcel_Reader_OOCalc implements PHPExcel_Reader_IReader } + /** + * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetInfo($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $worksheetInfo = array(); + + $zipClass = PHPExcel_Settings::getZipClass(); + + $zip = new $zipClass; + if (!$zip->open($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! Error opening file."); + } + + $xml = new XMLReader(); + $res = $xml->open('zip://'.realpath($pFilename).'#content.xml', null, PHPExcel_Settings::getLibXmlLoaderOptions()); + $xml->setParserProperty(2,true); + + // Step into the first level of content of the XML + $xml->read(); + while ($xml->read()) { + // Quickly jump through to the office:body node + while ($xml->name !== 'office:body') { + if ($xml->isEmptyElement) + $xml->read(); + else + $xml->next(); + } + // Now read each node until we find our first table:table node + while ($xml->read()) { + if ($xml->name == 'table:table' && $xml->nodeType == XMLReader::ELEMENT) { + $worksheetNames[] = $xml->getAttribute('table:name'); + + $tmpInfo = array( + 'worksheetName' => $xml->getAttribute('table:name'), + 'lastColumnLetter' => 'A', + 'lastColumnIndex' => 0, + 'totalRows' => 0, + 'totalColumns' => 0, + ); + + // Loop through each child node of the table:table element reading + $currCells = 0; + do { + $xml->read(); + if ($xml->name == 'table:table-row' && $xml->nodeType == XMLReader::ELEMENT) { + $rowspan = $xml->getAttribute('table:number-rows-repeated'); + $rowspan = empty($rowspan) ? 1 : $rowspan; + $tmpInfo['totalRows'] += $rowspan; + $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'],$currCells); + $currCells = 0; + // Step into the row + $xml->read(); + do { + if ($xml->name == 'table:table-cell' && $xml->nodeType == XMLReader::ELEMENT) { + if (!$xml->isEmptyElement) { + $currCells++; + $xml->next(); + } else { + $xml->read(); + } + } elseif ($xml->name == 'table:covered-table-cell' && $xml->nodeType == XMLReader::ELEMENT) { + $mergeSize = $xml->getAttribute('table:number-columns-repeated'); + $currCells += $mergeSize; + $xml->read(); + } + } while ($xml->name != 'table:table-row'); + } + } while ($xml->name != 'table:table'); + + $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'],$currCells); + $tmpInfo['lastColumnIndex'] = $tmpInfo['totalColumns'] - 1; + $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); + $worksheetInfo[] = $tmpInfo; + } + } + +// foreach($workbookData->table as $worksheetDataSet) { +// $worksheetData = $worksheetDataSet->children($namespacesContent['table']); +// $worksheetDataAttributes = $worksheetDataSet->attributes($namespacesContent['table']); +// +// $rowIndex = 0; +// foreach ($worksheetData as $key => $rowData) { +// switch ($key) { +// case 'table-row' : +// $rowDataTableAttributes = $rowData->attributes($namespacesContent['table']); +// $rowRepeats = (isset($rowDataTableAttributes['number-rows-repeated'])) ? +// $rowDataTableAttributes['number-rows-repeated'] : 1; +// $columnIndex = 0; +// +// foreach ($rowData as $key => $cellData) { +// $cellDataTableAttributes = $cellData->attributes($namespacesContent['table']); +// $colRepeats = (isset($cellDataTableAttributes['number-columns-repeated'])) ? +// $cellDataTableAttributes['number-columns-repeated'] : 1; +// $cellDataOfficeAttributes = $cellData->attributes($namespacesContent['office']); +// if (isset($cellDataOfficeAttributes['value-type'])) { +// $tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex + $colRepeats - 1); +// $tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex + $rowRepeats); +// } +// $columnIndex += $colRepeats; +// } +// $rowIndex += $rowRepeats; +// break; +// } +// } +// +// $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); +// $tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1; +// +// } +// } + } + + return $worksheetInfo; + } + + /** * Loads PHPExcel from file * * @param string $pFilename * @return PHPExcel - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function load($pFilename) { @@ -280,441 +319,376 @@ class PHPExcel_Reader_OOCalc implements PHPExcel_Reader_IReader } - /** - * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) - * - * @param string $pFilename - * @throws Exception - */ - public function listWorksheetInfo($pFilename) - { - // Check if file exists - if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } - - $worksheetInfo = array(); - - $zip = new ZipArchive; - if ($zip->open($pFilename) === true) { - - $xml = simplexml_load_string($zip->getFromName("content.xml")); - $namespacesContent = $xml->getNamespaces(true); - - $workbook = $xml->children($namespacesContent['office']); - foreach($workbook->body->spreadsheet as $workbookData) { - $workbookData = $workbookData->children($namespacesContent['table']); - foreach($workbookData->table as $worksheetDataSet) { - $worksheetData = $worksheetDataSet->children($namespacesContent['table']); - $worksheetDataAttributes = $worksheetDataSet->attributes($namespacesContent['table']); - - $tmpInfo = array(); - $tmpInfo['worksheetName'] = (string) $worksheetDataAttributes['name']; - $tmpInfo['lastColumnLetter'] = 'A'; - $tmpInfo['lastColumnIndex'] = 0; - $tmpInfo['totalRows'] = 0; - $tmpInfo['totalColumns'] = 0; - - $rowIndex = 0; - foreach ($worksheetData as $key => $rowData) { - switch ($key) { - case 'table-row' : - $rowDataTableAttributes = $rowData->attributes($namespacesContent['table']); - $rowRepeats = (isset($rowDataTableAttributes['number-rows-repeated'])) ? - $rowDataTableAttributes['number-rows-repeated'] : 1; - $columnIndex = 0; - - foreach ($rowData as $key => $cellData) { - $cellDataTableAttributes = $cellData->attributes($namespacesContent['table']); - $colRepeats = (isset($cellDataTableAttributes['number-columns-repeated'])) ? - $cellDataTableAttributes['number-columns-repeated'] : 1; - $cellDataOfficeAttributes = $cellData->attributes($namespacesContent['office']); - if (isset($cellDataOfficeAttributes['value-type'])) { - $tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex + $colRepeats - 1); - $tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex + $rowRepeats); - } - $columnIndex += $colRepeats; - } - $rowIndex += $rowRepeats; - break; - } - } - - $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); - $tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1; - - $worksheetInfo[] = $tmpInfo; - } - } - } - - return $worksheetInfo; - } - - /** * Loads PHPExcel from file into PHPExcel instance * * @param string $pFilename * @param PHPExcel $objPHPExcel * @return PHPExcel - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) { // Check if file exists if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); } $timezoneObj = new DateTimeZone('Europe/London'); $GMT = new DateTimeZone('UTC'); - $zip = new ZipArchive; - if ($zip->open($pFilename) === true) { -// echo '

Meta Information

'; - $xml = simplexml_load_string($zip->getFromName("meta.xml")); - $namespacesMeta = $xml->getNamespaces(true); -// echo '
';
-//			print_r($namespacesMeta);
-//			echo '

'; + $zipClass = PHPExcel_Settings::getZipClass(); - $docProps = $objPHPExcel->getProperties(); - $officeProperty = $xml->children($namespacesMeta['office']); - foreach($officeProperty as $officePropertyData) { - $officePropertyDC = array(); - if (isset($namespacesMeta['dc'])) { - $officePropertyDC = $officePropertyData->children($namespacesMeta['dc']); - } - foreach($officePropertyDC as $propertyName => $propertyValue) { - switch ($propertyName) { - case 'title' : - $docProps->setTitle($propertyValue); - break; - case 'subject' : - $docProps->setSubject($propertyValue); - break; - case 'creator' : - $docProps->setCreator($propertyValue); - $docProps->setLastModifiedBy($propertyValue); - break; - case 'date' : - $creationDate = strtotime($propertyValue); - $docProps->setCreated($creationDate); - $docProps->setModified($creationDate); - break; - case 'description' : - $docProps->setDescription($propertyValue); - break; - } - } - $officePropertyMeta = array(); - if (isset($namespacesMeta['dc'])) { - $officePropertyMeta = $officePropertyData->children($namespacesMeta['meta']); - } - foreach($officePropertyMeta as $propertyName => $propertyValue) { - $propertyValueAttributes = $propertyValue->attributes($namespacesMeta['meta']); - switch ($propertyName) { - case 'initial-creator' : - $docProps->setCreator($propertyValue); - break; - case 'keyword' : - $docProps->setKeywords($propertyValue); - break; - case 'creation-date' : - $creationDate = strtotime($propertyValue); - $docProps->setCreated($creationDate); - break; - case 'user-defined' : - $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_STRING; - foreach ($propertyValueAttributes as $key => $value) { - if ($key == 'name') { - $propertyValueName = (string) $value; - } elseif($key == 'value-type') { - switch ($value) { - case 'date' : - $propertyValue = PHPExcel_DocumentProperties::convertProperty($propertyValue,'date'); - $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_DATE; - break; - case 'boolean' : - $propertyValue = PHPExcel_DocumentProperties::convertProperty($propertyValue,'bool'); - $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_BOOLEAN; - break; - case 'float' : - $propertyValue = PHPExcel_DocumentProperties::convertProperty($propertyValue,'r4'); - $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_FLOAT; - break; - default : - $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_STRING; - } - } - } - $docProps->setCustomProperty($propertyValueName,$propertyValue,$propertyValueType); - break; - } + $zip = new $zipClass; + if (!$zip->open($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! Error opening file."); + } + +// echo '

Meta Information

'; + $xml = simplexml_load_string($zip->getFromName("meta.xml"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + $namespacesMeta = $xml->getNamespaces(true); +// echo '
';
+//		print_r($namespacesMeta);
+//		echo '

'; + + $docProps = $objPHPExcel->getProperties(); + $officeProperty = $xml->children($namespacesMeta['office']); + foreach($officeProperty as $officePropertyData) { + $officePropertyDC = array(); + if (isset($namespacesMeta['dc'])) { + $officePropertyDC = $officePropertyData->children($namespacesMeta['dc']); + } + foreach($officePropertyDC as $propertyName => $propertyValue) { + $propertyValue = (string) $propertyValue; + switch ($propertyName) { + case 'title' : + $docProps->setTitle($propertyValue); + break; + case 'subject' : + $docProps->setSubject($propertyValue); + break; + case 'creator' : + $docProps->setCreator($propertyValue); + $docProps->setLastModifiedBy($propertyValue); + break; + case 'date' : + $creationDate = strtotime($propertyValue); + $docProps->setCreated($creationDate); + $docProps->setModified($creationDate); + break; + case 'description' : + $docProps->setDescription($propertyValue); + break; } } - - -// echo '

Workbook Content

'; - $xml = simplexml_load_string($zip->getFromName("content.xml")); - $namespacesContent = $xml->getNamespaces(true); -// echo '
';
-//			print_r($namespacesContent);
-//			echo '

'; - - $workbook = $xml->children($namespacesContent['office']); - foreach($workbook->body->spreadsheet as $workbookData) { - $workbookData = $workbookData->children($namespacesContent['table']); - $worksheetID = 0; - foreach($workbookData->table as $worksheetDataSet) { - $worksheetData = $worksheetDataSet->children($namespacesContent['table']); -// print_r($worksheetData); -// echo '
'; - $worksheetDataAttributes = $worksheetDataSet->attributes($namespacesContent['table']); -// print_r($worksheetDataAttributes); -// echo '
'; - if ((isset($this->_loadSheetsOnly)) && (isset($worksheetDataAttributes['name'])) && - (!in_array($worksheetDataAttributes['name'], $this->_loadSheetsOnly))) { - continue; - } - -// echo '

Worksheet '.$worksheetDataAttributes['name'].'

'; - // Create new Worksheet - $objPHPExcel->createSheet(); - $objPHPExcel->setActiveSheetIndex($worksheetID); - if (isset($worksheetDataAttributes['name'])) { - $worksheetName = (string) $worksheetDataAttributes['name']; - // Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in - // formula cells... during the load, all formulae should be correct, and we're simply - // bringing the worksheet name in line with the formula, not the reverse - $objPHPExcel->getActiveSheet()->setTitle($worksheetName,false); - } - - $rowID = 1; - foreach($worksheetData as $key => $rowData) { -// echo ''.$key.'
'; - switch ($key) { - case 'table-header-rows': - foreach ($rowData as $key=>$cellData) { - $rowData = $cellData; - break; + $officePropertyMeta = array(); + if (isset($namespacesMeta['dc'])) { + $officePropertyMeta = $officePropertyData->children($namespacesMeta['meta']); + } + foreach($officePropertyMeta as $propertyName => $propertyValue) { + $propertyValueAttributes = $propertyValue->attributes($namespacesMeta['meta']); + $propertyValue = (string) $propertyValue; + switch ($propertyName) { + case 'initial-creator' : + $docProps->setCreator($propertyValue); + break; + case 'keyword' : + $docProps->setKeywords($propertyValue); + break; + case 'creation-date' : + $creationDate = strtotime($propertyValue); + $docProps->setCreated($creationDate); + break; + case 'user-defined' : + $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_STRING; + foreach ($propertyValueAttributes as $key => $value) { + if ($key == 'name') { + $propertyValueName = (string) $value; + } elseif($key == 'value-type') { + switch ($value) { + case 'date' : + $propertyValue = PHPExcel_DocumentProperties::convertProperty($propertyValue,'date'); + $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_DATE; + break; + case 'boolean' : + $propertyValue = PHPExcel_DocumentProperties::convertProperty($propertyValue,'bool'); + $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_BOOLEAN; + break; + case 'float' : + $propertyValue = PHPExcel_DocumentProperties::convertProperty($propertyValue,'r4'); + $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_FLOAT; + break; + default : + $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_STRING; + } } - case 'table-row' : - $rowDataTableAttributes = $rowData->attributes($namespacesContent['table']); - $rowRepeats = (isset($rowDataTableAttributes['number-rows-repeated'])) ? - $rowDataTableAttributes['number-rows-repeated'] : 1; - $columnID = 'A'; - foreach($rowData as $key => $cellData) { - if ($this->getReadFilter() !== NULL) { - if (!$this->getReadFilter()->readCell($columnID, $rowID, $worksheetName)) { - continue; - } + } + $docProps->setCustomProperty($propertyValueName,$propertyValue,$propertyValueType); + break; + } + } + } + + +// echo '

Workbook Content

'; + $xml = simplexml_load_string($zip->getFromName("content.xml"), 'SimpleXMLElement', PHPExcel_Settings::getLibXmlLoaderOptions()); + $namespacesContent = $xml->getNamespaces(true); +// echo '
';
+//		print_r($namespacesContent);
+//		echo '

'; + + $workbook = $xml->children($namespacesContent['office']); + foreach($workbook->body->spreadsheet as $workbookData) { + $workbookData = $workbookData->children($namespacesContent['table']); + $worksheetID = 0; + foreach($workbookData->table as $worksheetDataSet) { + $worksheetData = $worksheetDataSet->children($namespacesContent['table']); +// print_r($worksheetData); +// echo '
'; + $worksheetDataAttributes = $worksheetDataSet->attributes($namespacesContent['table']); +// print_r($worksheetDataAttributes); +// echo '
'; + if ((isset($this->_loadSheetsOnly)) && (isset($worksheetDataAttributes['name'])) && + (!in_array($worksheetDataAttributes['name'], $this->_loadSheetsOnly))) { + continue; + } + +// echo '

Worksheet '.$worksheetDataAttributes['name'].'

'; + // Create new Worksheet + $objPHPExcel->createSheet(); + $objPHPExcel->setActiveSheetIndex($worksheetID); + if (isset($worksheetDataAttributes['name'])) { + $worksheetName = (string) $worksheetDataAttributes['name']; + // Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in + // formula cells... during the load, all formulae should be correct, and we're simply + // bringing the worksheet name in line with the formula, not the reverse + $objPHPExcel->getActiveSheet()->setTitle($worksheetName,false); + } + + $rowID = 1; + foreach($worksheetData as $key => $rowData) { +// echo ''.$key.'
'; + switch ($key) { + case 'table-header-rows': + foreach ($rowData as $key=>$cellData) { + $rowData = $cellData; + break; + } + case 'table-row' : + $rowDataTableAttributes = $rowData->attributes($namespacesContent['table']); + $rowRepeats = (isset($rowDataTableAttributes['number-rows-repeated'])) ? + $rowDataTableAttributes['number-rows-repeated'] : 1; + $columnID = 'A'; + foreach($rowData as $key => $cellData) { + if ($this->getReadFilter() !== NULL) { + if (!$this->getReadFilter()->readCell($columnID, $rowID, $worksheetName)) { + continue; } + } -// echo ''.$columnID.$rowID.'
'; - $cellDataText = (isset($namespacesContent['text'])) ? - $cellData->children($namespacesContent['text']) : - ''; - $cellDataOffice = $cellData->children($namespacesContent['office']); - $cellDataOfficeAttributes = $cellData->attributes($namespacesContent['office']); - $cellDataTableAttributes = $cellData->attributes($namespacesContent['table']); +// echo ''.$columnID.$rowID.'
'; + $cellDataText = (isset($namespacesContent['text'])) ? + $cellData->children($namespacesContent['text']) : + ''; + $cellDataOffice = $cellData->children($namespacesContent['office']); + $cellDataOfficeAttributes = $cellData->attributes($namespacesContent['office']); + $cellDataTableAttributes = $cellData->attributes($namespacesContent['table']); -// echo 'Office Attributes: '; -// print_r($cellDataOfficeAttributes); -// echo '
Table Attributes: '; -// print_r($cellDataTableAttributes); -// echo '
Cell Data Text'; -// print_r($cellDataText); -// echo '
'; +// echo 'Office Attributes: '; +// print_r($cellDataOfficeAttributes); +// echo '
Table Attributes: '; +// print_r($cellDataTableAttributes); +// echo '
Cell Data Text'; +// print_r($cellDataText); +// echo '
'; // - $type = $formatting = $hyperlink = null; - $hasCalculatedValue = false; - $cellDataFormula = ''; - if (isset($cellDataTableAttributes['formula'])) { - $cellDataFormula = $cellDataTableAttributes['formula']; - $hasCalculatedValue = true; - } + $type = $formatting = $hyperlink = null; + $hasCalculatedValue = false; + $cellDataFormula = ''; + if (isset($cellDataTableAttributes['formula'])) { + $cellDataFormula = $cellDataTableAttributes['formula']; + $hasCalculatedValue = true; + } - if (isset($cellDataOffice->annotation)) { -// echo 'Cell has comment
'; - $annotationText = $cellDataOffice->annotation->children($namespacesContent['text']); - $textArray = array(); - foreach($annotationText as $t) { - foreach($t->span as $text) { - $textArray[] = (string)$text; - } + if (isset($cellDataOffice->annotation)) { +// echo 'Cell has comment
'; + $annotationText = $cellDataOffice->annotation->children($namespacesContent['text']); + $textArray = array(); + foreach($annotationText as $t) { + foreach($t->span as $text) { + $textArray[] = (string)$text; } - $text = implode("\n",$textArray); -// echo $text,'
'; - $objPHPExcel->getActiveSheet()->getComment( $columnID.$rowID ) -// ->setAuthor( $author ) - ->setText($this->_parseRichText($text) ); } + $text = implode("\n",$textArray); +// echo $text,'
'; + $objPHPExcel->getActiveSheet()->getComment( $columnID.$rowID ) +// ->setAuthor( $author ) + ->setText($this->_parseRichText($text) ); + } if (isset($cellDataText->p)) { - // Consolidate if there are multiple p records (maybe with spans as well) - $dataArray = array(); - // Text can have multiple text:p and within those, multiple text:span. - // text:p newlines, but text:span does not. - // Also, here we assume there is no text data is span fields are specified, since - // we have no way of knowing proper positioning anyway. - foreach ($cellDataText->p as $pData) { - if (isset($pData->span)) { - // span sections do not newline, so we just create one large string here - $spanSection = ""; - foreach ($pData->span as $spanData) { - $spanSection .= $spanData; + // Consolidate if there are multiple p records (maybe with spans as well) + $dataArray = array(); + // Text can have multiple text:p and within those, multiple text:span. + // text:p newlines, but text:span does not. + // Also, here we assume there is no text data is span fields are specified, since + // we have no way of knowing proper positioning anyway. + foreach ($cellDataText->p as $pData) { + if (isset($pData->span)) { + // span sections do not newline, so we just create one large string here + $spanSection = ""; + foreach ($pData->span as $spanData) { + $spanSection .= $spanData; + } + array_push($dataArray, $spanSection); + } else { + array_push($dataArray, $pData); + } + } + $allCellDataText = implode($dataArray, "\n"); + +// echo 'Value Type is '.$cellDataOfficeAttributes['value-type'].'
'; + switch ($cellDataOfficeAttributes['value-type']) { + case 'string' : + $type = PHPExcel_Cell_DataType::TYPE_STRING; + $dataValue = $allCellDataText; + if (isset($dataValue->a)) { + $dataValue = $dataValue->a; + $cellXLinkAttributes = $dataValue->attributes($namespacesContent['xlink']); + $hyperlink = $cellXLinkAttributes['href']; } - array_push($dataArray, $spanSection); - } else { - array_push($dataArray, $pData); - } - } - $allCellDataText = implode($dataArray, "\n"); - -// echo 'Value Type is '.$cellDataOfficeAttributes['value-type'].'
'; - switch ($cellDataOfficeAttributes['value-type']) { - case 'string' : - $type = PHPExcel_Cell_DataType::TYPE_STRING; - $dataValue = $allCellDataText; - if (isset($dataValue->a)) { - $dataValue = $dataValue->a; - $cellXLinkAttributes = $dataValue->attributes($namespacesContent['xlink']); - $hyperlink = $cellXLinkAttributes['href']; - } - break; - case 'boolean' : - $type = PHPExcel_Cell_DataType::TYPE_BOOL; - $dataValue = ($allCellDataText == 'TRUE') ? True : False; - break; - case 'percentage' : - $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; - $dataValue = (float) $cellDataOfficeAttributes['value']; - if (floor($dataValue) == $dataValue) { - $dataValue = (integer) $dataValue; - } - $formatting = PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE_00; - break; - case 'currency' : - $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; - $dataValue = (float) $cellDataOfficeAttributes['value']; - if (floor($dataValue) == $dataValue) { - $dataValue = (integer) $dataValue; - } - $formatting = PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_USD_SIMPLE; - break; - case 'float' : - $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; - $dataValue = (float) $cellDataOfficeAttributes['value']; - if (floor($dataValue) == $dataValue) { - if ($dataValue = (integer) $dataValue) - $dataValue = (integer) $dataValue; - else - $dataValue = (float) $dataValue; - } - break; - case 'date' : - $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; - $dateObj = new DateTime($cellDataOfficeAttributes['date-value'], $GMT); - $dateObj->setTimeZone($timezoneObj); - list($year,$month,$day,$hour,$minute,$second) = explode(' ',$dateObj->format('Y m d H i s')); - $dataValue = PHPExcel_Shared_Date::FormattedPHPToExcel($year,$month,$day,$hour,$minute,$second); - if ($dataValue != floor($dataValue)) { - $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15.' '.PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4; - } else { - $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15; - } - break; - case 'time' : - $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; - $dataValue = PHPExcel_Shared_Date::PHPToExcel(strtotime('01-01-1970 '.implode(':',sscanf($cellDataOfficeAttributes['time-value'],'PT%dH%dM%dS')))); - $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4; - break; - } -// echo 'Data value is '.$dataValue.'
'; -// if ($hyperlink !== NULL) { -// echo 'Hyperlink is '.$hyperlink.'
'; -// } - } else { - $type = PHPExcel_Cell_DataType::TYPE_NULL; - $dataValue = NULL; - } - - if ($hasCalculatedValue) { - $type = PHPExcel_Cell_DataType::TYPE_FORMULA; -// echo 'Formula: '.$cellDataFormula.'
'; - $cellDataFormula = substr($cellDataFormula,strpos($cellDataFormula,':=')+1); - $temp = explode('"',$cellDataFormula); - $tKey = false; - foreach($temp as &$value) { - // Only replace in alternate array entries (i.e. non-quoted blocks) - if ($tKey = !$tKey) { - $value = preg_replace('/\[\.(.*):\.(.*)\]/Ui','$1:$2',$value); - $value = preg_replace('/\[\.(.*)\]/Ui','$1',$value); - $value = PHPExcel_Calculation::_translateSeparator(';',',',$value,$inBraces); - } - } - unset($value); - // Then rebuild the formula string - $cellDataFormula = implode('"',$temp); -// echo 'Adjusted Formula: '.$cellDataFormula.'
'; - } - - $colRepeats = (isset($cellDataTableAttributes['number-columns-repeated'])) ? - $cellDataTableAttributes['number-columns-repeated'] : 1; - if ($type !== NULL) { - for ($i = 0; $i < $colRepeats; ++$i) { - if ($i > 0) { - ++$columnID; - } - if ($type !== PHPExcel_Cell_DataType::TYPE_NULL) { - for ($rowAdjust = 0; $rowAdjust < $rowRepeats; ++$rowAdjust) { - $rID = $rowID + $rowAdjust; - $objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $dataValue),$type); - if ($hasCalculatedValue) { -// echo 'Forumla result is '.$dataValue.'
'; - $objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->setCalculatedValue($dataValue); - } - if ($formatting !== NULL) { - $objPHPExcel->getActiveSheet()->getStyle($columnID.$rID)->getNumberFormat()->setFormatCode($formatting); - } else { - $objPHPExcel->getActiveSheet()->getStyle($columnID.$rID)->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_GENERAL); - } - if ($hyperlink !== NULL) { - $objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->getHyperlink()->setUrl($hyperlink); - } + break; + case 'boolean' : + $type = PHPExcel_Cell_DataType::TYPE_BOOL; + $dataValue = ($allCellDataText == 'TRUE') ? True : False; + break; + case 'percentage' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $dataValue = (float) $cellDataOfficeAttributes['value']; + if (floor($dataValue) == $dataValue) { + $dataValue = (integer) $dataValue; } - } - } + $formatting = PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE_00; + break; + case 'currency' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $dataValue = (float) $cellDataOfficeAttributes['value']; + if (floor($dataValue) == $dataValue) { + $dataValue = (integer) $dataValue; + } + $formatting = PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_USD_SIMPLE; + break; + case 'float' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $dataValue = (float) $cellDataOfficeAttributes['value']; + if (floor($dataValue) == $dataValue) { + if ($dataValue == (integer) $dataValue) + $dataValue = (integer) $dataValue; + else + $dataValue = (float) $dataValue; + } + break; + case 'date' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $dateObj = new DateTime($cellDataOfficeAttributes['date-value'], $GMT); + $dateObj->setTimeZone($timezoneObj); + list($year,$month,$day,$hour,$minute,$second) = explode(' ',$dateObj->format('Y m d H i s')); + $dataValue = PHPExcel_Shared_Date::FormattedPHPToExcel($year,$month,$day,$hour,$minute,$second); + if ($dataValue != floor($dataValue)) { + $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15.' '.PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4; + } else { + $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15; + } + break; + case 'time' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $dataValue = PHPExcel_Shared_Date::PHPToExcel(strtotime('01-01-1970 '.implode(':',sscanf($cellDataOfficeAttributes['time-value'],'PT%dH%dM%dS')))); + $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4; + break; } - - // Merged cells - if ((isset($cellDataTableAttributes['number-columns-spanned'])) || (isset($cellDataTableAttributes['number-rows-spanned']))) { - if (($type !== PHPExcel_Cell_DataType::TYPE_NULL) || (!$this->_readDataOnly)) { - $columnTo = $columnID; - if (isset($cellDataTableAttributes['number-columns-spanned'])) { - $columnTo = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cellDataTableAttributes['number-columns-spanned'] -2); - } - $rowTo = $rowID; - if (isset($cellDataTableAttributes['number-rows-spanned'])) { - $rowTo = $rowTo + $cellDataTableAttributes['number-rows-spanned'] - 1; - } - $cellRange = $columnID.$rowID.':'.$columnTo.$rowTo; - $objPHPExcel->getActiveSheet()->mergeCells($cellRange); - } - } - - ++$columnID; +// echo 'Data value is '.$dataValue.'
'; +// if ($hyperlink !== NULL) { +// echo 'Hyperlink is '.$hyperlink.'
'; +// } + } else { + $type = PHPExcel_Cell_DataType::TYPE_NULL; + $dataValue = NULL; } - $rowID += $rowRepeats; - break; - } - } - ++$worksheetID; - } - } + if ($hasCalculatedValue) { + $type = PHPExcel_Cell_DataType::TYPE_FORMULA; +// echo 'Formula: ', $cellDataFormula, PHP_EOL; + $cellDataFormula = substr($cellDataFormula,strpos($cellDataFormula,':=')+1); + $temp = explode('"',$cellDataFormula); + $tKey = false; + foreach($temp as &$value) { + // Only replace in alternate array entries (i.e. non-quoted blocks) + if ($tKey = !$tKey) { + $value = preg_replace('/\[([^\.]+)\.([^\.]+):\.([^\.]+)\]/Ui','$1!$2:$3',$value); // Cell range reference in another sheet + $value = preg_replace('/\[([^\.]+)\.([^\.]+)\]/Ui','$1!$2',$value); // Cell reference in another sheet + $value = preg_replace('/\[\.([^\.]+):\.([^\.]+)\]/Ui','$1:$2',$value); // Cell range reference + $value = preg_replace('/\[\.([^\.]+)\]/Ui','$1',$value); // Simple cell reference + $value = PHPExcel_Calculation::_translateSeparator(';',',',$value,$inBraces); + } + } + unset($value); + // Then rebuild the formula string + $cellDataFormula = implode('"',$temp); +// echo 'Adjusted Formula: ', $cellDataFormula, PHP_EOL; + } + + $colRepeats = (isset($cellDataTableAttributes['number-columns-repeated'])) ? + $cellDataTableAttributes['number-columns-repeated'] : 1; + if ($type !== NULL) { + for ($i = 0; $i < $colRepeats; ++$i) { + if ($i > 0) { + ++$columnID; + } + if ($type !== PHPExcel_Cell_DataType::TYPE_NULL) { + for ($rowAdjust = 0; $rowAdjust < $rowRepeats; ++$rowAdjust) { + $rID = $rowID + $rowAdjust; + $objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $dataValue),$type); + if ($hasCalculatedValue) { +// echo 'Forumla result is '.$dataValue.'
'; + $objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->setCalculatedValue($dataValue); + } + if ($formatting !== NULL) { + $objPHPExcel->getActiveSheet()->getStyle($columnID.$rID)->getNumberFormat()->setFormatCode($formatting); + } else { + $objPHPExcel->getActiveSheet()->getStyle($columnID.$rID)->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_GENERAL); + } + if ($hyperlink !== NULL) { + $objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->getHyperlink()->setUrl($hyperlink); + } + } + } + } + } + + // Merged cells + if ((isset($cellDataTableAttributes['number-columns-spanned'])) || (isset($cellDataTableAttributes['number-rows-spanned']))) { + if (($type !== PHPExcel_Cell_DataType::TYPE_NULL) || (!$this->_readDataOnly)) { + $columnTo = $columnID; + if (isset($cellDataTableAttributes['number-columns-spanned'])) { + $columnTo = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cellDataTableAttributes['number-columns-spanned'] -2); + } + $rowTo = $rowID; + if (isset($cellDataTableAttributes['number-rows-spanned'])) { + $rowTo = $rowTo + $cellDataTableAttributes['number-rows-spanned'] - 1; + } + $cellRange = $columnID.$rowID.':'.$columnTo.$rowTo; + $objPHPExcel->getActiveSheet()->mergeCells($cellRange); + } + } + + ++$columnID; + } + $rowID += $rowRepeats; + break; + } + } + ++$worksheetID; + } } // Return diff --git a/htdocs/includes/phpexcel/PHPExcel/Reader/SYLK.php b/htdocs/includes/phpexcel/PHPExcel/Reader/SYLK.php index 47d5703f56b..cd87ce56c10 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Reader/SYLK.php +++ b/htdocs/includes/phpexcel/PHPExcel/Reader/SYLK.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -40,9 +40,9 @@ if (!defined('PHPEXCEL_ROOT')) { * * @category PHPExcel * @package PHPExcel_Reader - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Reader_SYLK implements PHPExcel_Reader_IReader +class PHPExcel_Reader_SYLK extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader { /** * Input encoding @@ -72,14 +72,6 @@ class PHPExcel_Reader_SYLK implements PHPExcel_Reader_IReader */ private $_format = 0; - /** - * PHPExcel_Reader_IReadFilter instance - * - * @var PHPExcel_Reader_IReadFilter - */ - private $_readFilter = null; - - /** * Create a new PHPExcel_Reader_SYLK */ @@ -87,63 +79,31 @@ class PHPExcel_Reader_SYLK implements PHPExcel_Reader_IReader $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); } - /** - * Can the current PHPExcel_Reader_IReader read the file? + * Validate that the current file is a SYLK file * - * @param string $pFileName - * @return boolean - * @throws Exception + * @return boolean */ - public function canRead($pFilename) + protected function _isValidFormat() { - // Check if file exists - if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } - // Read sample data (first 2 KB will do) - $fh = fopen($pFilename, 'r'); - $data = fread($fh, 2048); - fclose($fh); + $data = fread($this->_fileHandle, 2048); // Count delimiters in file $delimiterCount = substr_count($data, ';'); if ($delimiterCount < 1) { - return false; + return FALSE; } // Analyze first line looking for ID; signature $lines = explode("\n", $data); if (substr($lines[0],0,4) != 'ID;P') { - return false; + return FALSE; } - return true; + return TRUE; } - - /** - * Read filter - * - * @return PHPExcel_Reader_IReadFilter - */ - public function getReadFilter() { - return $this->_readFilter; - } - - - /** - * Set read filter - * - * @param PHPExcel_Reader_IReadFilter $pValue - */ - public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) { - $this->_readFilter = $pValue; - return $this; - } - - /** * Set input encoding * @@ -155,7 +115,6 @@ class PHPExcel_Reader_SYLK implements PHPExcel_Reader_IReader return $this; } - /** * Get input encoding * @@ -166,25 +125,22 @@ class PHPExcel_Reader_SYLK implements PHPExcel_Reader_IReader return $this->_inputEncoding; } - /** * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) * * @param string $pFilename - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function listWorksheetInfo($pFilename) { - // Check if file exists - if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); - } - // Open file - $fileHandle = fopen($pFilename, 'r'); - if ($fileHandle === false) { - throw new Exception("Could not open file " . $pFilename . " for reading."); + $this->_openFile($pFilename); + if (!$this->_isValidFormat()) { + fclose ($this->_fileHandle); + throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); } + $fileHandle = $this->_fileHandle; + rewind($fileHandle); $worksheetInfo = array(); $worksheetInfo[0]['worksheetName'] = 'Worksheet'; @@ -206,7 +162,7 @@ class PHPExcel_Reader_SYLK implements PHPExcel_Reader_IReader // explode each row at semicolons while taking into account that literal semicolon (;) // is escaped like this (;;) - $rowData = explode("\t",str_replace('?',';',str_replace(';',"\t",str_replace(';;','?',rtrim($rowData))))); + $rowData = explode("\t",str_replace('¤',';',str_replace(';',"\t",str_replace(';;','¤',rtrim($rowData))))); $dataType = array_shift($rowData); if ($dataType == 'C') { @@ -238,13 +194,12 @@ class PHPExcel_Reader_SYLK implements PHPExcel_Reader_IReader return $worksheetInfo; } - /** * Loads PHPExcel from file * * @param string $pFilename * @return PHPExcel - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function load($pFilename) { @@ -255,21 +210,24 @@ class PHPExcel_Reader_SYLK implements PHPExcel_Reader_IReader return $this->loadIntoExisting($pFilename, $objPHPExcel); } - /** * Loads PHPExcel from file into PHPExcel instance * * @param string $pFilename * @param PHPExcel $objPHPExcel * @return PHPExcel - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) { - // Check if file exists - if (!file_exists($pFilename)) { - throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + // Open file + $this->_openFile($pFilename); + if (!$this->_isValidFormat()) { + fclose ($this->_fileHandle); + throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); } + $fileHandle = $this->_fileHandle; + rewind($fileHandle); // Create new PHPExcel while ($objPHPExcel->getSheetCount() <= $this->_sheetIndex) { @@ -280,12 +238,6 @@ class PHPExcel_Reader_SYLK implements PHPExcel_Reader_IReader $fromFormats = array('\-', '\ '); $toFormats = array('-', ' '); - // Open file - $fileHandle = fopen($pFilename, 'r'); - if ($fileHandle === false) { - throw new Exception("Could not open file $pFilename for reading."); - } - // Loop through file $rowData = array(); $column = $row = ''; @@ -433,7 +385,9 @@ class PHPExcel_Reader_SYLK implements PHPExcel_Reader_IReader } if (($formatStyle > '') && ($column > '') && ($row > '')) { $columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1); - $objPHPExcel->getActiveSheet()->getStyle($columnLetter.$row)->applyFromArray($this->_formats[$formatStyle]); + if (isset($this->_formats[$formatStyle])) { + $objPHPExcel->getActiveSheet()->getStyle($columnLetter.$row)->applyFromArray($this->_formats[$formatStyle]); + } } if ((!empty($styleData)) && ($column > '') && ($row > '')) { $columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1); @@ -473,7 +427,6 @@ class PHPExcel_Reader_SYLK implements PHPExcel_Reader_IReader return $objPHPExcel; } - /** * Get sheet index * @@ -483,7 +436,6 @@ class PHPExcel_Reader_SYLK implements PHPExcel_Reader_IReader return $this->_sheetIndex; } - /** * Set sheet index * diff --git a/htdocs/includes/phpexcel/PHPExcel/ReferenceHelper.php b/htdocs/includes/phpexcel/PHPExcel/ReferenceHelper.php index 9113591297a..402f2b472a6 100644 --- a/htdocs/includes/phpexcel/PHPExcel/ReferenceHelper.php +++ b/htdocs/includes/phpexcel/PHPExcel/ReferenceHelper.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_ReferenceHelper { @@ -69,30 +69,336 @@ class PHPExcel_ReferenceHelper } /** - * Insert a new column, updating all possible related data + * Compare two column addresses + * Intended for use as a Callback function for sorting column addresses by column * - * @param int $pBefore Insert before this one - * @param int $pNumCols Number of columns to insert - * @param int $pNumRows Number of rows to insert - * @throws Exception + * @param string $a First column to test (e.g. 'AA') + * @param string $b Second column to test (e.g. 'Z') + * @return integer */ - public function insertNewBefore($pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, PHPExcel_Worksheet $pSheet = null) { + public static function columnSort($a, $b) { + return strcasecmp(strlen($a) . $a, strlen($b) . $b); + } + + /** + * Compare two column addresses + * Intended for use as a Callback function for reverse sorting column addresses by column + * + * @param string $a First column to test (e.g. 'AA') + * @param string $b Second column to test (e.g. 'Z') + * @return integer + */ + public static function columnReverseSort($a, $b) { + return 1 - strcasecmp(strlen($a) . $a, strlen($b) . $b); + } + + /** + * Compare two cell addresses + * Intended for use as a Callback function for sorting cell addresses by column and row + * + * @param string $a First cell to test (e.g. 'AA1') + * @param string $b Second cell to test (e.g. 'Z1') + * @return integer + */ + public static function cellSort($a, $b) { + sscanf($a,'%[A-Z]%d', $ac, $ar); + sscanf($b,'%[A-Z]%d', $bc, $br); + + if ($ar == $br) { + return strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc); + } + return ($ar < $br) ? -1 : 1; + } + + /** + * Compare two cell addresses + * Intended for use as a Callback function for sorting cell addresses by column and row + * + * @param string $a First cell to test (e.g. 'AA1') + * @param string $b Second cell to test (e.g. 'Z1') + * @return integer + */ + public static function cellReverseSort($a, $b) { + sscanf($a,'%[A-Z]%d', $ac, $ar); + sscanf($b,'%[A-Z]%d', $bc, $br); + + if ($ar == $br) { + return 1 - strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc); + } + return ($ar < $br) ? 1 : -1; + } + + /** + * Test whether a cell address falls within a defined range of cells + * + * @param string $cellAddress Address of the cell we're testing + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @return boolean + */ + private static function cellAddressInDeleteRange($cellAddress, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols) { + list($cellColumn, $cellRow) = PHPExcel_Cell::coordinateFromString($cellAddress); + $cellColumnIndex = PHPExcel_Cell::columnIndexFromString($cellColumn); + // Is cell within the range of rows/columns if we're deleting + if ($pNumRows < 0 && + ($cellRow >= ($beforeRow + $pNumRows)) && + ($cellRow < $beforeRow)) { + return TRUE; + } elseif ($pNumCols < 0 && + ($cellColumnIndex >= ($beforeColumnIndex + $pNumCols)) && + ($cellColumnIndex < $beforeColumnIndex)) { + return TRUE; + } + return FALSE; + } + + /** + * Update page breaks when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustPageBreaks(PHPExcel_Worksheet $pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aBreaks = $pSheet->getBreaks(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellSort')); + + foreach ($aBreaks as $key => $value) { + if (self::cellAddressInDeleteRange($key, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols)) { + // If we're deleting, then clear any defined breaks that are within the range + // of rows/columns that we're deleting + $pSheet->setBreak($key, PHPExcel_Worksheet::BREAK_NONE); + } else { + // Otherwise update any affected breaks by inserting a new break at the appropriate point + // and removing the old affected break + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + if ($key != $newReference) { + $pSheet->setBreak($newReference, $value) + ->setBreak($key, PHPExcel_Worksheet::BREAK_NONE); + } + } + } + } + + /** + * Update cell comments when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustComments($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aComments = $pSheet->getComments(); + $aNewComments = array(); // the new array of all comments + + foreach ($aComments as $key => &$value) { + // Any comments inside a deleted range will be ignored + if (!self::cellAddressInDeleteRange($key, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols)) { + // Otherwise build a new array of comments indexed by the adjusted cell reference + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + $aNewComments[$newReference] = $value; + } + } + // Replace the comments array with the new set of comments + $pSheet->setComments($aNewComments); + } + + /** + * Update hyperlinks when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustHyperlinks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aHyperlinkCollection = $pSheet->getHyperlinkCollection(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellSort')); + + foreach ($aHyperlinkCollection as $key => $value) { + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + if ($key != $newReference) { + $pSheet->setHyperlink( $newReference, $value ); + $pSheet->setHyperlink( $key, null ); + } + } + } + + /** + * Update data validations when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustDataValidations($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aDataValidationCollection = $pSheet->getDataValidationCollection(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellSort')); + foreach ($aDataValidationCollection as $key => $value) { + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + if ($key != $newReference) { + $pSheet->setDataValidation( $newReference, $value ); + $pSheet->setDataValidation( $key, null ); + } + } + } + + /** + * Update merged cells when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustMergeCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aMergeCells = $pSheet->getMergeCells(); + $aNewMergeCells = array(); // the new array of all merge cells + foreach ($aMergeCells as $key => &$value) { + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + $aNewMergeCells[$newReference] = $newReference; + } + $pSheet->setMergeCells($aNewMergeCells); // replace the merge cells array + } + + /** + * Update protected cells when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustProtectedCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aProtectedCells = $pSheet->getProtectedCells(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellSort')); + foreach ($aProtectedCells as $key => $value) { + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + if ($key != $newReference) { + $pSheet->protectCells( $newReference, $value, true ); + $pSheet->unprotectCells( $key ); + } + } + } + + /** + * Update column dimensions when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustColumnDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aColumnDimensions = array_reverse($pSheet->getColumnDimensions(), true); + if (!empty($aColumnDimensions)) { + foreach ($aColumnDimensions as $objColumnDimension) { + $newReference = $this->updateCellReference($objColumnDimension->getColumnIndex() . '1', $pBefore, $pNumCols, $pNumRows); + list($newReference) = PHPExcel_Cell::coordinateFromString($newReference); + if ($objColumnDimension->getColumnIndex() != $newReference) { + $objColumnDimension->setColumnIndex($newReference); + } + } + $pSheet->refreshColumnDimensions(); + } + } + + /** + * Update row dimensions when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustRowDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aRowDimensions = array_reverse($pSheet->getRowDimensions(), true); + if (!empty($aRowDimensions)) { + foreach ($aRowDimensions as $objRowDimension) { + $newReference = $this->updateCellReference('A' . $objRowDimension->getRowIndex(), $pBefore, $pNumCols, $pNumRows); + list(, $newReference) = PHPExcel_Cell::coordinateFromString($newReference); + if ($objRowDimension->getRowIndex() != $newReference) { + $objRowDimension->setRowIndex($newReference); + } + } + $pSheet->refreshRowDimensions(); + + $copyDimension = $pSheet->getRowDimension($beforeRow - 1); + for ($i = $beforeRow; $i <= $beforeRow - 1 + $pNumRows; ++$i) { + $newDimension = $pSheet->getRowDimension($i); + $newDimension->setRowHeight($copyDimension->getRowHeight()); + $newDimension->setVisible($copyDimension->getVisible()); + $newDimension->setOutlineLevel($copyDimension->getOutlineLevel()); + $newDimension->setCollapsed($copyDimension->getCollapsed()); + } + } + } + + /** + * Insert a new column or row, updating all possible related data + * + * @param string $pBefore Insert before this cell address (e.g. 'A1') + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @throws PHPExcel_Exception + */ + public function insertNewBefore($pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, PHPExcel_Worksheet $pSheet = NULL) + { + $remove = ($pNumCols < 0 || $pNumRows < 0); $aCellCollection = $pSheet->getCellCollection(); // Get coordinates of $pBefore $beforeColumn = 'A'; $beforeRow = 1; - list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString( $pBefore ); - + list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString($pBefore); + $beforeColumnIndex = PHPExcel_Cell::columnIndexFromString($beforeColumn); // Clear cells if we are removing columns or rows $highestColumn = $pSheet->getHighestColumn(); $highestRow = $pSheet->getHighestRow(); // 1. Clear column strips if we are removing columns - if ($pNumCols < 0 && PHPExcel_Cell::columnIndexFromString($beforeColumn) - 2 + $pNumCols > 0) { + if ($pNumCols < 0 && $beforeColumnIndex - 2 + $pNumCols > 0) { for ($i = 1; $i <= $highestRow - 1; ++$i) { - for ($j = PHPExcel_Cell::columnIndexFromString($beforeColumn) - 1 + $pNumCols; $j <= PHPExcel_Cell::columnIndexFromString($beforeColumn) - 2; ++$j) { + for ($j = $beforeColumnIndex - 1 + $pNumCols; $j <= $beforeColumnIndex - 2; ++$j) { $coordinate = PHPExcel_Cell::stringFromColumnIndex($j) . $i; $pSheet->removeConditionalStyles($coordinate); if ($pSheet->cellExists($coordinate)) { @@ -105,7 +411,7 @@ class PHPExcel_ReferenceHelper // 2. Clear row strips if we are removing rows if ($pNumRows < 0 && $beforeRow - 1 + $pNumRows > 0) { - for ($i = PHPExcel_Cell::columnIndexFromString($beforeColumn) - 1; $i <= PHPExcel_Cell::columnIndexFromString($highestColumn) - 1; ++$i) { + for ($i = $beforeColumnIndex - 1; $i <= PHPExcel_Cell::columnIndexFromString($highestColumn) - 1; ++$i) { for ($j = $beforeRow + $pNumRows; $j <= $beforeRow - 1; ++$j) { $coordinate = PHPExcel_Cell::stringFromColumnIndex($i) . $j; $pSheet->removeConditionalStyles($coordinate); @@ -117,21 +423,28 @@ class PHPExcel_ReferenceHelper } } - // Loop through cells, bottom-up, and change cell coordinates - while (($cellID = ($pNumCols < 0 || $pNumRows < 0) ? array_shift($aCellCollection) : array_pop($aCellCollection))) { + if($remove) { + // It's faster to reverse and pop than to use unshift, especially with large cell collections + $aCellCollection = array_reverse($aCellCollection); + } + while ($cellID = array_pop($aCellCollection)) { $cell = $pSheet->getCell($cellID); + $cellIndex = PHPExcel_Cell::columnIndexFromString($cell->getColumn()); + + if ($cellIndex-1 + $pNumCols < 0) { + continue; + } // New coordinates - $newCoordinates = PHPExcel_Cell::stringFromColumnIndex( PHPExcel_Cell::columnIndexFromString($cell->getColumn()) - 1 + $pNumCols ) . ($cell->getRow() + $pNumRows); + $newCoordinates = PHPExcel_Cell::stringFromColumnIndex($cellIndex-1 + $pNumCols) . ($cell->getRow() + $pNumRows); // Should the cell be updated? Move value and cellXf index from one cell to another. - if ((PHPExcel_Cell::columnIndexFromString( $cell->getColumn() ) >= PHPExcel_Cell::columnIndexFromString($beforeColumn)) && + if (($cellIndex >= $beforeColumnIndex) && ($cell->getRow() >= $beforeRow)) { // Update cell styles $pSheet->getCell($newCoordinates)->setXfIndex($cell->getXfIndex()); - $cell->setXfIndex(0); // Insert this cell at its new location if ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA) { @@ -145,7 +458,7 @@ class PHPExcel_ReferenceHelper } // Clear the original cell - $pSheet->getCell($cell->getCoordinate())->setValue(''); + $pSheet->getCellCacheController()->deleteCacheData($cellID); } else { /* We don't need to update styles for rows/columns before our insertion position, @@ -159,21 +472,20 @@ class PHPExcel_ReferenceHelper } } - // Duplicate styles for the newly inserted cells $highestColumn = $pSheet->getHighestColumn(); $highestRow = $pSheet->getHighestRow(); - if ($pNumCols > 0 && PHPExcel_Cell::columnIndexFromString($beforeColumn) - 2 > 0) { + if ($pNumCols > 0 && $beforeColumnIndex - 2 > 0) { for ($i = $beforeRow; $i <= $highestRow - 1; ++$i) { // Style - $coordinate = PHPExcel_Cell::stringFromColumnIndex( PHPExcel_Cell::columnIndexFromString($beforeColumn) - 2 ) . $i; + $coordinate = PHPExcel_Cell::stringFromColumnIndex( $beforeColumnIndex - 2 ) . $i; if ($pSheet->cellExists($coordinate)) { $xfIndex = $pSheet->getCell($coordinate)->getXfIndex(); $conditionalStyles = $pSheet->conditionalStylesExists($coordinate) ? $pSheet->getConditionalStyles($coordinate) : false; - for ($j = PHPExcel_Cell::columnIndexFromString($beforeColumn) - 1; $j <= PHPExcel_Cell::columnIndexFromString($beforeColumn) - 2 + $pNumCols; ++$j) { + for ($j = $beforeColumnIndex - 1; $j <= $beforeColumnIndex - 2 + $pNumCols; ++$j) { $pSheet->getCellByColumnAndRow($j, $i)->setXfIndex($xfIndex); if ($conditionalStyles) { $cloned = array(); @@ -189,7 +501,7 @@ class PHPExcel_ReferenceHelper } if ($pNumRows > 0 && $beforeRow - 1 > 0) { - for ($i = PHPExcel_Cell::columnIndexFromString($beforeColumn) - 1; $i <= PHPExcel_Cell::columnIndexFromString($highestColumn) - 1; ++$i) { + for ($i = $beforeColumnIndex - 1; $i <= PHPExcel_Cell::columnIndexFromString($highestColumn) - 1; ++$i) { // Style $coordinate = PHPExcel_Cell::stringFromColumnIndex($i) . ($beforeRow - 1); @@ -211,105 +523,29 @@ class PHPExcel_ReferenceHelper } } - // Update worksheet: column dimensions - $aColumnDimensions = array_reverse($pSheet->getColumnDimensions(), true); - if (!empty($aColumnDimensions)) { - foreach ($aColumnDimensions as $objColumnDimension) { - $newReference = $this->updateCellReference($objColumnDimension->getColumnIndex() . '1', $pBefore, $pNumCols, $pNumRows); - list($newReference) = PHPExcel_Cell::coordinateFromString($newReference); - if ($objColumnDimension->getColumnIndex() != $newReference) { - $objColumnDimension->setColumnIndex($newReference); - } - } - $pSheet->refreshColumnDimensions(); - } - + $this->_adjustColumnDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); // Update worksheet: row dimensions - $aRowDimensions = array_reverse($pSheet->getRowDimensions(), true); - if (!empty($aRowDimensions)) { - foreach ($aRowDimensions as $objRowDimension) { - $newReference = $this->updateCellReference('A' . $objRowDimension->getRowIndex(), $pBefore, $pNumCols, $pNumRows); - list(, $newReference) = PHPExcel_Cell::coordinateFromString($newReference); - if ($objRowDimension->getRowIndex() != $newReference) { - $objRowDimension->setRowIndex($newReference); - } - } - $pSheet->refreshRowDimensions(); + $this->_adjustRowDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); - $copyDimension = $pSheet->getRowDimension($beforeRow - 1); - for ($i = $beforeRow; $i <= $beforeRow - 1 + $pNumRows; ++$i) { - $newDimension = $pSheet->getRowDimension($i); - $newDimension->setRowHeight($copyDimension->getRowHeight()); - $newDimension->setVisible($copyDimension->getVisible()); - $newDimension->setOutlineLevel($copyDimension->getOutlineLevel()); - $newDimension->setCollapsed($copyDimension->getCollapsed()); - } - } + // Update worksheet: page breaks + $this->_adjustPageBreaks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); - - // Update worksheet: breaks - $aBreaks = array_reverse($pSheet->getBreaks(), true); - foreach ($aBreaks as $key => $value) { - $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); - if ($key != $newReference) { - $pSheet->setBreak( $newReference, $value ); - $pSheet->setBreak( $key, PHPExcel_Worksheet::BREAK_NONE ); - } - } - - // Update worksheet: comments - $aComments = $pSheet->getComments(); - $aNewComments = array(); // the new array of all comments - foreach ($aComments as $key => &$value) { - $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); - $aNewComments[$newReference] = $value; - } - $pSheet->setComments($aNewComments); // replace the comments array + // Update worksheet: comments + $this->_adjustComments($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); // Update worksheet: hyperlinks - $aHyperlinkCollection = array_reverse($pSheet->getHyperlinkCollection(), true); - foreach ($aHyperlinkCollection as $key => $value) { - $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); - if ($key != $newReference) { - $pSheet->setHyperlink( $newReference, $value ); - $pSheet->setHyperlink( $key, null ); - } - } - + $this->_adjustHyperlinks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); // Update worksheet: data validations - $aDataValidationCollection = array_reverse($pSheet->getDataValidationCollection(), true); - foreach ($aDataValidationCollection as $key => $value) { - $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); - if ($key != $newReference) { - $pSheet->setDataValidation( $newReference, $value ); - $pSheet->setDataValidation( $key, null ); - } - } - + $this->_adjustDataValidations($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); // Update worksheet: merge cells - $aMergeCells = $pSheet->getMergeCells(); - $aNewMergeCells = array(); // the new array of all merge cells - foreach ($aMergeCells as $key => &$value) { - $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); - $aNewMergeCells[$newReference] = $newReference; - } - $pSheet->setMergeCells($aNewMergeCells); // replace the merge cells array - + $this->_adjustMergeCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); // Update worksheet: protected cells - $aProtectedCells = array_reverse($pSheet->getProtectedCells(), true); - foreach ($aProtectedCells as $key => $value) { - $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); - if ($key != $newReference) { - $pSheet->protectCells( $newReference, $value, true ); - $pSheet->unprotectCells( $key ); - } - } - + $this->_adjustProtectedCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); // Update worksheet: autofilter $autoFilter = $pSheet->getAutoFilter(); @@ -318,7 +554,7 @@ class PHPExcel_ReferenceHelper if ($pNumCols != 0) { $autoFilterColumns = array_keys($autoFilter->getColumns()); if (count($autoFilterColumns) > 0) { - list($column,$row) = sscanf($pBefore,'%[A-Z]%d'); + sscanf($pBefore,'%[A-Z]%d', $column, $row); $columnIndex = PHPExcel_Cell::columnIndexFromString($column); list($rangeStart,$rangeEnd) = PHPExcel_Cell::rangeBoundaries($autoFilterRange); if ($columnIndex <= $rangeEnd[0]) { @@ -369,19 +605,16 @@ class PHPExcel_ReferenceHelper $pSheet->setAutoFilter( $this->updateCellReference($autoFilterRange, $pBefore, $pNumCols, $pNumRows) ); } - // Update worksheet: freeze pane if ($pSheet->getFreezePane() != '') { $pSheet->freezePane( $this->updateCellReference($pSheet->getFreezePane(), $pBefore, $pNumCols, $pNumRows) ); } - // Page setup if ($pSheet->getPageSetup()->isPrintAreaSet()) { $pSheet->getPageSetup()->setPrintArea( $this->updateCellReference($pSheet->getPageSetup()->getPrintArea(), $pBefore, $pNumCols, $pNumRows) ); } - // Update worksheet: drawings $aDrawings = $pSheet->getDrawingCollection(); foreach ($aDrawings as $objDrawing) { @@ -391,7 +624,6 @@ class PHPExcel_ReferenceHelper } } - // Update workbook: named ranges if (count($pSheet->getParent()->getNamedRanges()) > 0) { foreach ($pSheet->getParent()->getNamedRanges() as $namedRange) { @@ -414,8 +646,9 @@ class PHPExcel_ReferenceHelper * @param int $pBefore Insert before this one * @param int $pNumCols Number of columns to insert * @param int $pNumRows Number of rows to insert + * @param string $sheetName Worksheet name/title * @return string Updated formula - * @throws Exception + * @throws PHPExcel_Exception */ public function updateFormulaReferences($pFormula = '', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, $sheetName = '') { // Update cell references in the formula @@ -445,7 +678,7 @@ class PHPExcel_ReferenceHelper $cellIndex = $column.$row; $newCellTokens[$cellIndex] = preg_quote($toString); - $cellTokens[$cellIndex] = '/(? 0) { foreach($matches as $match) { $fromString = ($match[2] > '') ? $match[2].'!' : ''; $fromString .= $match[3]; - $modified3 = $this->updateCellReference($match[3],$pBefore,$pNumCols,$pNumRows); + $modified3 = $this->updateCellReference($match[3],$pBefore,$pNumCols,$pNumRows); if ($match[3] !== $modified3) { if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) { $toString = ($match[2] > '') ? $match[2].'!' : ''; @@ -518,19 +752,23 @@ class PHPExcel_ReferenceHelper // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more $column = PHPExcel_Cell::columnIndexFromString(trim($column,'$')) + 100000; $row = trim($row,'$') + 10000000; - $cellIndex = $column.$row; + $cellIndex = $row . $column; $newCellTokens[$cellIndex] = preg_quote($toString); - $cellTokens[$cellIndex] = '/(? 0) { - krsort($cellTokens); - krsort($newCellTokens); - // Update cell references in the formula + if ($pNumCols > 0 || $pNumRows > 0) { + krsort($cellTokens); + krsort($newCellTokens); + } else { + ksort($cellTokens); + ksort($newCellTokens); + } // Update cell references in the formula $formulaBlock = str_replace('\\','',preg_replace($cellTokens,$newCellTokens,$formulaBlock)); } } @@ -549,7 +787,7 @@ class PHPExcel_ReferenceHelper * @param int $pNumCols Number of columns to increment * @param int $pNumRows Number of rows to increment * @return string Updated cell range - * @throws Exception + * @throws PHPExcel_Exception */ public function updateCellReference($pCellRange = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { // Is it in another worksheet? Will not have to update anything. @@ -603,7 +841,7 @@ class PHPExcel_ReferenceHelper * @param int $pNumCols Number of columns to increment * @param int $pNumRows Number of rows to increment * @return string Updated cell range - * @throws Exception + * @throws PHPExcel_Exception */ private function _updateCellRange($pCellRange = 'A1:A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { if (strpos($pCellRange,':') !== false || strpos($pCellRange, ',') !== false) { @@ -628,7 +866,7 @@ class PHPExcel_ReferenceHelper // Recreate range string return PHPExcel_Cell::buildRange($range); } else { - throw new Exception("Only cell ranges may be passed to this method."); + throw new PHPExcel_Exception("Only cell ranges may be passed to this method."); } } @@ -640,7 +878,7 @@ class PHPExcel_ReferenceHelper * @param int $pNumCols Number of columns to increment * @param int $pNumRows Number of rows to increment * @return string Updated cell reference - * @throws Exception + * @throws PHPExcel_Exception */ private function _updateSingleCellReference($pCellReference = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { if (strpos($pCellReference, ':') === false && strpos($pCellReference, ',') === false) { @@ -653,7 +891,6 @@ class PHPExcel_ReferenceHelper // Verify which parts should be updated $updateColumn = (($newColumn{0} != '$') && ($beforeColumn{0} != '$') && PHPExcel_Cell::columnIndexFromString($newColumn) >= PHPExcel_Cell::columnIndexFromString($beforeColumn)); - $updateRow = (($newRow{0} != '$') && ($beforeRow{0} != '$') && $newRow >= $beforeRow); @@ -670,16 +907,16 @@ class PHPExcel_ReferenceHelper // Return new reference return $newColumn . $newRow; } else { - throw new Exception("Only single cell references may be passed to this method."); + throw new PHPExcel_Exception("Only single cell references may be passed to this method."); } } /** * __clone implementation. Cloning should not be allowed in a Singleton! * - * @throws Exception + * @throws PHPExcel_Exception */ public final function __clone() { - throw new Exception("Cloning a Singleton is not allowed!"); + throw new PHPExcel_Exception("Cloning a Singleton is not allowed!"); } } diff --git a/htdocs/includes/phpexcel/PHPExcel/RichText.php b/htdocs/includes/phpexcel/PHPExcel/RichText.php index 17af169cdd6..2f172a0512b 100644 --- a/htdocs/includes/phpexcel/PHPExcel/RichText.php +++ b/htdocs/includes/phpexcel/PHPExcel/RichText.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.8.0, 2014-03-02 */ @@ -31,81 +31,81 @@ * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_RichText implements PHPExcel_IComparable { - /** - * Rich text elements - * - * @var PHPExcel_RichText_ITextElement[] - */ - private $_richTextElements; + /** + * Rich text elements + * + * @var PHPExcel_RichText_ITextElement[] + */ + private $_richTextElements; /** * Create a new PHPExcel_RichText instance * - * @param PHPExcel_Cell $pParent - * @throws Exception + * @param PHPExcel_Cell $pCell + * @throws PHPExcel_Exception */ public function __construct(PHPExcel_Cell $pCell = null) { - // Initialise variables - $this->_richTextElements = array(); + // Initialise variables + $this->_richTextElements = array(); - // Rich-Text string attached to cell? - if ($pCell !== NULL) { - // Add cell text and style - if ($pCell->getValue() != "") { - $objRun = new PHPExcel_RichText_Run($pCell->getValue()); - $objRun->setFont(clone $pCell->getParent()->getStyle($pCell->getCoordinate())->getFont()); - $this->addText($objRun); - } + // Rich-Text string attached to cell? + if ($pCell !== NULL) { + // Add cell text and style + if ($pCell->getValue() != "") { + $objRun = new PHPExcel_RichText_Run($pCell->getValue()); + $objRun->setFont(clone $pCell->getParent()->getStyle($pCell->getCoordinate())->getFont()); + $this->addText($objRun); + } - // Set parent value - $pCell->setValueExplicit($this, PHPExcel_Cell_DataType::TYPE_STRING); - } + // Set parent value + $pCell->setValueExplicit($this, PHPExcel_Cell_DataType::TYPE_STRING); + } } /** * Add text * - * @param PHPExcel_RichText_ITextElement $pText Rich text element - * @throws Exception + * @param PHPExcel_RichText_ITextElement $pText Rich text element + * @throws PHPExcel_Exception * @return PHPExcel_RichText */ public function addText(PHPExcel_RichText_ITextElement $pText = null) { - $this->_richTextElements[] = $pText; - return $this; + $this->_richTextElements[] = $pText; + return $this; } /** * Create text * - * @param string $pText Text - * @return PHPExcel_RichText_TextElement - * @throws Exception + * @param string $pText Text + * @return PHPExcel_RichText_TextElement + * @throws PHPExcel_Exception */ public function createText($pText = '') { - $objText = new PHPExcel_RichText_TextElement($pText); - $this->addText($objText); - return $objText; + $objText = new PHPExcel_RichText_TextElement($pText); + $this->addText($objText); + return $objText; } /** * Create text run * - * @param string $pText Text - * @return PHPExcel_RichText_Run - * @throws Exception + * @param string $pText Text + * @return PHPExcel_RichText_Run + * @throws PHPExcel_Exception */ public function createTextRun($pText = '') { - $objText = new PHPExcel_RichText_Run($pText); - $this->addText($objText); - return $objText; + $objText = new PHPExcel_RichText_Run($pText); + $this->addText($objText); + return $objText; } /** @@ -115,16 +115,16 @@ class PHPExcel_RichText implements PHPExcel_IComparable */ public function getPlainText() { - // Return value - $returnValue = ''; + // Return value + $returnValue = ''; - // Loop through all PHPExcel_RichText_ITextElement - foreach ($this->_richTextElements as $text) { - $returnValue .= $text->getText(); - } + // Loop through all PHPExcel_RichText_ITextElement + foreach ($this->_richTextElements as $text) { + $returnValue .= $text->getText(); + } - // Return - return $returnValue; + // Return + return $returnValue; } /** @@ -132,8 +132,9 @@ class PHPExcel_RichText implements PHPExcel_IComparable * * @return string */ - public function __toString() { - return $this->getPlainText(); + public function __toString() + { + return $this->getPlainText(); } /** @@ -143,54 +144,56 @@ class PHPExcel_RichText implements PHPExcel_IComparable */ public function getRichTextElements() { - return $this->_richTextElements; + return $this->_richTextElements; } /** * Set Rich Text elements * - * @param PHPExcel_RichText_ITextElement[] $pElements Array of elements - * @throws Exception + * @param PHPExcel_RichText_ITextElement[] $pElements Array of elements + * @throws PHPExcel_Exception * @return PHPExcel_RichText */ public function setRichTextElements($pElements = null) { - if (is_array($pElements)) { - $this->_richTextElements = $pElements; - } else { - throw new Exception("Invalid PHPExcel_RichText_ITextElement[] array passed."); - } - return $this; + if (is_array($pElements)) { + $this->_richTextElements = $pElements; + } else { + throw new PHPExcel_Exception("Invalid PHPExcel_RichText_ITextElement[] array passed."); + } + return $this; } - /** - * Get hash code - * - * @return string Hash code - */ - public function getHashCode() { - $hashElements = ''; - foreach ($this->_richTextElements as $element) { - $hashElements .= $element->getHashCode(); - } + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() + { + $hashElements = ''; + foreach ($this->_richTextElements as $element) { + $hashElements .= $element->getHashCode(); + } - return md5( - $hashElements - . __CLASS__ - ); + return md5( + $hashElements + . __CLASS__ + ); } - /** - * Implement PHP __clone to create a deep clone, not just a shallow copy. - */ - public function __clone() { - $vars = get_object_vars($this); - foreach ($vars as $key => $value) { - if (is_object($value)) { - $this->$key = clone $value; - } else { - $this->$key = $value; - } - } - } + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() + { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } } diff --git a/htdocs/includes/phpexcel/PHPExcel/RichText/ITextElement.php b/htdocs/includes/phpexcel/PHPExcel/RichText/ITextElement.php index 4c658637f62..ec19498d06c 100644 --- a/htdocs/includes/phpexcel/PHPExcel/RichText/ITextElement.php +++ b/htdocs/includes/phpexcel/PHPExcel/RichText/ITextElement.php @@ -18,9 +18,9 @@ * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -29,7 +29,7 @@ * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ interface PHPExcel_RichText_ITextElement { diff --git a/htdocs/includes/phpexcel/PHPExcel/RichText/Run.php b/htdocs/includes/phpexcel/PHPExcel/RichText/Run.php index 9e33786c195..71545fc2e39 100644 --- a/htdocs/includes/phpexcel/PHPExcel/RichText/Run.php +++ b/htdocs/includes/phpexcel/PHPExcel/RichText/Run.php @@ -18,9 +18,9 @@ * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -29,7 +29,7 @@ * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_RichText_Run extends PHPExcel_RichText_TextElement implements PHPExcel_RichText_ITextElement { @@ -65,7 +65,7 @@ class PHPExcel_RichText_Run extends PHPExcel_RichText_TextElement implements PHP * Set font * * @param PHPExcel_Style_Font $pFont Font - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_RichText_ITextElement */ public function setFont(PHPExcel_Style_Font $pFont = null) { diff --git a/htdocs/includes/phpexcel/PHPExcel/RichText/TextElement.php b/htdocs/includes/phpexcel/PHPExcel/RichText/TextElement.php index 5b9edd07ee4..3593c6e19c0 100644 --- a/htdocs/includes/phpexcel/PHPExcel/RichText/TextElement.php +++ b/htdocs/includes/phpexcel/PHPExcel/RichText/TextElement.php @@ -18,9 +18,9 @@ * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -29,7 +29,7 @@ * * @category PHPExcel * @package PHPExcel_RichText - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_RichText_TextElement implements PHPExcel_RichText_ITextElement { diff --git a/htdocs/includes/phpexcel/PHPExcel/Settings.php b/htdocs/includes/phpexcel/PHPExcel/Settings.php index 6659b90e956..b89961320e4 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Settings.php +++ b/htdocs/includes/phpexcel/PHPExcel/Settings.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,313 +20,368 @@ * * @category PHPExcel * @package PHPExcel_Settings - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.8.0, 2014-03-02 */ /** PHPExcel root directory */ if (!defined('PHPEXCEL_ROOT')) { - /** - * @ignore - */ - define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../'); - require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); } class PHPExcel_Settings { - /** constants */ - /** Available Zip library classes */ - const PCLZIP = 'PHPExcel_Shared_ZipArchive'; - const ZIPARCHIVE = 'ZipArchive'; + /** constants */ + /** Available Zip library classes */ + const PCLZIP = 'PHPExcel_Shared_ZipArchive'; + const ZIPARCHIVE = 'ZipArchive'; - /** Optional Chart Rendering libraries */ - const CHART_RENDERER_JPGRAPH = 'jpgraph'; + /** Optional Chart Rendering libraries */ + const CHART_RENDERER_JPGRAPH = 'jpgraph'; - /** Optional PDF Rendering libraries */ + /** Optional PDF Rendering libraries */ const PDF_RENDERER_TCPDF = 'tcPDF'; const PDF_RENDERER_DOMPDF = 'DomPDF'; - const PDF_RENDERER_MPDF = 'mPDF'; + const PDF_RENDERER_MPDF = 'mPDF'; - private static $_chartRenderers = array( - self::CHART_RENDERER_JPGRAPH, - ); + private static $_chartRenderers = array( + self::CHART_RENDERER_JPGRAPH, + ); - private static $_pdfRenderers = array( - self::PDF_RENDERER_TCPDF, - self::PDF_RENDERER_DOMPDF, - self::PDF_RENDERER_MPDF, - ); + private static $_pdfRenderers = array( + self::PDF_RENDERER_TCPDF, + self::PDF_RENDERER_DOMPDF, + self::PDF_RENDERER_MPDF, + ); - /** - * Name of the class used for Zip file management - * e.g. - * ZipArchive - * - * @var string - */ - private static $_zipClass = self::ZIPARCHIVE; + /** + * Name of the class used for Zip file management + * e.g. + * ZipArchive + * + * @var string + */ + private static $_zipClass = self::ZIPARCHIVE; - /** - * Name of the external Library used for rendering charts - * e.g. - * jpgraph - * - * @var string - */ - private static $_chartRendererName = NULL; + /** + * Name of the external Library used for rendering charts + * e.g. + * jpgraph + * + * @var string + */ + private static $_chartRendererName = NULL; - /** - * Directory Path to the external Library used for rendering charts - * - * @var string - */ - private static $_chartRendererPath = NULL; + /** + * Directory Path to the external Library used for rendering charts + * + * @var string + */ + private static $_chartRendererPath = NULL; - /** - * Name of the external Library used for rendering PDF files - * e.g. - * mPDF - * - * @var string - */ - private static $_pdfRendererName = NULL; + /** + * Name of the external Library used for rendering PDF files + * e.g. + * mPDF + * + * @var string + */ + private static $_pdfRendererName = NULL; - /** - * Directory Path to the external Library used for rendering PDF files - * - * @var string - */ - private static $_pdfRendererPath = NULL; + /** + * Directory Path to the external Library used for rendering PDF files + * + * @var string + */ + private static $_pdfRendererPath = NULL; + + /** + * Default options for libxml loader + * + * @var int + */ + private static $_libXmlLoaderOptions = null; + + /** + * Set the Zip handler Class that PHPExcel should use for Zip file management (PCLZip or ZipArchive) + * + * @param string $zipClass The Zip handler class that PHPExcel should use for Zip file management + * e.g. PHPExcel_Settings::PCLZip or PHPExcel_Settings::ZipArchive + * @return boolean Success or failure + */ + public static function setZipClass($zipClass) + { + if (($zipClass === self::PCLZIP) || + ($zipClass === self::ZIPARCHIVE)) { + self::$_zipClass = $zipClass; + return TRUE; + } + return FALSE; + } // function setZipClass() - /** - * Set the Zip handler Class that PHPExcel should use for Zip file management (PCLZip or ZipArchive) - * - * @param string $zipClass The Zip handler class that PHPExcel should use for Zip file management - * e.g. PHPExcel_Settings::PCLZip or PHPExcel_Settings::ZipArchive - * @return boolean Success or failure - */ - public static function setZipClass($zipClass) { - if (($zipClass === self::PCLZIP) || - ($zipClass === self::ZIPARCHIVE)) { - self::$_zipClass = $zipClass; - return TRUE; - } - return FALSE; - } // function setZipClass() + /** + * Return the name of the Zip handler Class that PHPExcel is configured to use (PCLZip or ZipArchive) + * or Zip file management + * + * @return string Name of the Zip handler Class that PHPExcel is configured to use + * for Zip file management + * e.g. PHPExcel_Settings::PCLZip or PHPExcel_Settings::ZipArchive + */ + public static function getZipClass() + { + return self::$_zipClass; + } // function getZipClass() - /** - * Return the name of the Zip handler Class that PHPExcel is configured to use (PCLZip or ZipArchive) - * for Zip file management - * - * @return string Name of the Zip handler Class that PHPExcel is configured to use - * for Zip file management - * e.g. PHPExcel_Settings::PCLZip or PHPExcel_Settings::ZipArchive - */ - public static function getZipClass() { - return self::$_zipClass; - } // function getZipClass() + /** + * Return the name of the method that is currently configured for cell cacheing + * + * @return string Name of the cacheing method + */ + public static function getCacheStorageMethod() + { + return PHPExcel_CachedObjectStorageFactory::getCacheStorageMethod(); + } // function getCacheStorageMethod() - /** - * Return the name of the method that is currently configured for cell cacheing - * - * @return string Name of the cacheing method - */ - public static function getCacheStorageMethod() { - return PHPExcel_CachedObjectStorageFactory::getCacheStorageMethod(); - } // function getCacheStorageMethod() + /** + * Return the name of the class that is currently being used for cell cacheing + * + * @return string Name of the class currently being used for cacheing + */ + public static function getCacheStorageClass() + { + return PHPExcel_CachedObjectStorageFactory::getCacheStorageClass(); + } // function getCacheStorageClass() - /** - * Return the name of the class that is currently being used for cell cacheing - * - * @return string Name of the class currently being used for cacheing - */ - public static function getCacheStorageClass() { - return PHPExcel_CachedObjectStorageFactory::getCacheStorageClass(); - } // function getCacheStorageClass() + /** + * Set the method that should be used for cell cacheing + * + * @param string $method Name of the cacheing method + * @param array $arguments Optional configuration arguments for the cacheing method + * @return boolean Success or failure + */ + public static function setCacheStorageMethod( + $method = PHPExcel_CachedObjectStorageFactory::cache_in_memory, + $arguments = array() + ) + { + return PHPExcel_CachedObjectStorageFactory::initialize($method, $arguments); + } // function setCacheStorageMethod() - /** - * Set the method that should be used for cell cacheing - * - * @param string $method Name of the cacheing method - * @param array $arguments Optional configuration arguments for the cacheing method - * @return boolean Success or failure - */ - public static function setCacheStorageMethod($method = PHPExcel_CachedObjectStorageFactory::cache_in_memory, - $arguments = array()) { - return PHPExcel_CachedObjectStorageFactory::initialize($method, $arguments); - } // function setCacheStorageMethod() + /** + * Set the locale code to use for formula translations and any special formatting + * + * @param string $locale The locale code to use (e.g. "fr" or "pt_br" or "en_uk") + * @return boolean Success or failure + */ + public static function setLocale($locale='en_us') + { + return PHPExcel_Calculation::getInstance()->setLocale($locale); + } // function setLocale() - /** - * Set the locale code to use for formula translations and any special formatting - * - * @param string $locale The locale code to use (e.g. "fr" or "pt_br" or "en_uk") - * @return boolean Success or failure - */ - public static function setLocale($locale='en_us') { - return PHPExcel_Calculation::getInstance()->setLocale($locale); - } // function setLocale() + /** + * Set details of the external library that PHPExcel should use for rendering charts + * + * @param string $libraryName Internal reference name of the library + * e.g. PHPExcel_Settings::CHART_RENDERER_JPGRAPH + * @param string $libraryBaseDir Directory path to the library's base folder + * + * @return boolean Success or failure + */ + public static function setChartRenderer($libraryName, $libraryBaseDir) + { + if (!self::setChartRendererName($libraryName)) + return FALSE; + return self::setChartRendererPath($libraryBaseDir); + } // function setChartRenderer() - /** - * Set details of the external library that PHPExcel should use for rendering charts - * - * @param string $libraryName Internal reference name of the library - * e.g. PHPExcel_Settings::CHART_RENDERER_JPGRAPH - * @param string $libraryBaseDir Directory path to the library's base folder - * @return boolean Success or failure - */ - public static function setChartRenderer($libraryName, $libraryBaseDir) { - if (!self::setChartRendererName($libraryName)) - return FALSE; - return self::setChartRendererPath($libraryBaseDir); - } // function setChartRenderer() + /** + * Identify to PHPExcel the external library to use for rendering charts + * + * @param string $libraryName Internal reference name of the library + * e.g. PHPExcel_Settings::CHART_RENDERER_JPGRAPH + * + * @return boolean Success or failure + */ + public static function setChartRendererName($libraryName) + { + if (!in_array($libraryName,self::$_chartRenderers)) { + return FALSE; + } + + self::$_chartRendererName = $libraryName; + + return TRUE; + } // function setChartRendererName() - /** - * Identify to PHPExcel the external library to use for rendering charts - * - * @param string $libraryName Internal reference name of the library - * e.g. PHPExcel_Settings::CHART_RENDERER_JPGRAPH - * @return boolean Success or failure - */ - public static function setChartRendererName($libraryName) { - if (!in_array($libraryName,self::$_chartRenderers)) { - return FALSE; - } + /** + * Tell PHPExcel where to find the external library to use for rendering charts + * + * @param string $libraryBaseDir Directory path to the library's base folder + * @return boolean Success or failure + */ + public static function setChartRendererPath($libraryBaseDir) + { + if ((file_exists($libraryBaseDir) === false) || (is_readable($libraryBaseDir) === false)) { + return FALSE; + } + self::$_chartRendererPath = $libraryBaseDir; - self::$_chartRendererName = $libraryName; - - return TRUE; - } // function setChartRendererName() + return TRUE; + } // function setChartRendererPath() - /** - * Tell PHPExcel where to find the external library to use for rendering charts - * - * @param string $libraryBaseDir Directory path to the library's base folder - * @return boolean Success or failure - */ - public static function setChartRendererPath($libraryBaseDir) { - if ((file_exists($libraryBaseDir) === false) || (is_readable($libraryBaseDir) === false)) { - return FALSE; - } - self::$_chartRendererPath = $libraryBaseDir; - - return TRUE; - } // function setChartRendererPath() + /** + * Return the Chart Rendering Library that PHPExcel is currently configured to use (e.g. jpgraph) + * + * @return string|NULL Internal reference name of the Chart Rendering Library that PHPExcel is + * currently configured to use + * e.g. PHPExcel_Settings::CHART_RENDERER_JPGRAPH + */ + public static function getChartRendererName() + { + return self::$_chartRendererName; + } // function getChartRendererName() - /** - * Return the Chart Rendering Library that PHPExcel is currently configured to use (e.g. jpgraph) - * - * @return string|NULL Internal reference name of the Chart Rendering Library that PHPExcel is - * currently configured to use - * e.g. PHPExcel_Settings::CHART_RENDERER_JPGRAPH - */ - public static function getChartRendererName() { - return self::$_chartRendererName; - } // function getChartRendererName() + /** + * Return the directory path to the Chart Rendering Library that PHPExcel is currently configured to use + * + * @return string|NULL Directory Path to the Chart Rendering Library that PHPExcel is + * currently configured to use + */ + public static function getChartRendererPath() + { + return self::$_chartRendererPath; + } // function getChartRendererPath() - /** - * Return the directory path to the Chart Rendering Library that PHPExcel is currently configured to use - * - * @return string|NULL Directory Path to the Chart Rendering Library that PHPExcel is - * currently configured to use - */ - public static function getChartRendererPath() { - return self::$_chartRendererPath; - } // function getChartRendererPath() + /** + * Set details of the external library that PHPExcel should use for rendering PDF files + * + * @param string $libraryName Internal reference name of the library + * e.g. PHPExcel_Settings::PDF_RENDERER_TCPDF, + * PHPExcel_Settings::PDF_RENDERER_DOMPDF + * or PHPExcel_Settings::PDF_RENDERER_MPDF + * @param string $libraryBaseDir Directory path to the library's base folder + * + * @return boolean Success or failure + */ + public static function setPdfRenderer($libraryName, $libraryBaseDir) + { + if (!self::setPdfRendererName($libraryName)) + return FALSE; + return self::setPdfRendererPath($libraryBaseDir); + } // function setPdfRenderer() - /** - * Set details of the external library that PHPExcel should use for rendering PDF files - * - * @param string $libraryName Internal reference name of the library - * e.g. PHPExcel_Settings::PDF_RENDERER_TCPDF, - * PHPExcel_Settings::PDF_RENDERER_DOMPDF - * or PHPExcel_Settings::PDF_RENDERER_MPDF - * @param string $libraryBaseDir Directory path to the library's base folder - * @return boolean Success or failure - */ - public static function setPdfRenderer($libraryName, $libraryBaseDir) { - if (!self::setPdfRendererName($libraryName)) - return FALSE; - return self::setPdfRendererPath($libraryBaseDir); - } // function setPdfRenderer() + /** + * Identify to PHPExcel the external library to use for rendering PDF files + * + * @param string $libraryName Internal reference name of the library + * e.g. PHPExcel_Settings::PDF_RENDERER_TCPDF, + * PHPExcel_Settings::PDF_RENDERER_DOMPDF + * or PHPExcel_Settings::PDF_RENDERER_MPDF + * + * @return boolean Success or failure + */ + public static function setPdfRendererName($libraryName) + { + if (!in_array($libraryName,self::$_pdfRenderers)) { + return FALSE; + } + + self::$_pdfRendererName = $libraryName; + + return TRUE; + } // function setPdfRendererName() - /** - * Identify to PHPExcel the external library to use for rendering PDF files - * - * @param string $libraryName Internal reference name of the library - * e.g. PHPExcel_Settings::PDF_RENDERER_TCPDF, - * PHPExcel_Settings::PDF_RENDERER_DOMPDF - * or PHPExcel_Settings::PDF_RENDERER_MPDF - * @return boolean Success or failure - */ - public static function setPdfRendererName($libraryName) { - if (!in_array($libraryName,self::$_pdfRenderers)) { - return FALSE; - } + /** + * Tell PHPExcel where to find the external library to use for rendering PDF files + * + * @param string $libraryBaseDir Directory path to the library's base folder + * @return boolean Success or failure + */ + public static function setPdfRendererPath($libraryBaseDir) + { + if ((file_exists($libraryBaseDir) === false) || (is_readable($libraryBaseDir) === false)) { + return FALSE; + } + self::$_pdfRendererPath = $libraryBaseDir; - self::$_pdfRendererName = $libraryName; - - return TRUE; - } // function setPdfRendererName() + return TRUE; + } // function setPdfRendererPath() - /** - * Tell PHPExcel where to find the external library to use for rendering PDF files - * - * @param string $libraryBaseDir Directory path to the library's base folder - * @return boolean Success or failure - */ - public static function setPdfRendererPath($libraryBaseDir) { - if ((file_exists($libraryBaseDir) === false) || (is_readable($libraryBaseDir) === false)) { - return FALSE; - } - self::$_pdfRendererPath = $libraryBaseDir; + /** + * Return the PDF Rendering Library that PHPExcel is currently configured to use (e.g. dompdf) + * + * @return string|NULL Internal reference name of the PDF Rendering Library that PHPExcel is + * currently configured to use + * e.g. PHPExcel_Settings::PDF_RENDERER_TCPDF, + * PHPExcel_Settings::PDF_RENDERER_DOMPDF + * or PHPExcel_Settings::PDF_RENDERER_MPDF + */ + public static function getPdfRendererName() + { + return self::$_pdfRendererName; + } // function getPdfRendererName() - return TRUE; - } // function setPdfRendererPath() + /** + * Return the directory path to the PDF Rendering Library that PHPExcel is currently configured to use + * + * @return string|NULL Directory Path to the PDF Rendering Library that PHPExcel is + * currently configured to use + */ + public static function getPdfRendererPath() + { + return self::$_pdfRendererPath; + } // function getPdfRendererPath() + /** + * Set default options for libxml loader + * + * @param int $options Default options for libxml loader + */ + public static function setLibXmlLoaderOptions($options = null) + { + if (is_null($options)) { + $options = LIBXML_DTDLOAD | LIBXML_DTDATTR; + } + @libxml_disable_entity_loader($options == (LIBXML_DTDLOAD | LIBXML_DTDATTR)); + self::$_libXmlLoaderOptions = $options; + } // function setLibXmlLoaderOptions - /** - * Return the PDF Rendering Library that PHPExcel is currently configured to use (e.g. dompdf) - * - * @return string|NULL Internal reference name of the PDF Rendering Library that PHPExcel is - * currently configured to use - * e.g. PHPExcel_Settings::PDF_RENDERER_TCPDF, - * PHPExcel_Settings::PDF_RENDERER_DOMPDF - * or PHPExcel_Settings::PDF_RENDERER_MPDF - */ - public static function getPdfRendererName() { - return self::$_pdfRendererName; - } // function getPdfRendererName() - - - /** - * Return the directory path to the PDF Rendering Library that PHPExcel is currently configured to use - * - * @return string|NULL Directory Path to the PDF Rendering Library that PHPExcel is - * currently configured to use - */ - public static function getPdfRendererPath() { - return self::$_pdfRendererPath; - } // function getPdfRendererPath() - -} \ No newline at end of file + /** + * Get default options for libxml loader. + * Defaults to LIBXML_DTDLOAD | LIBXML_DTDATTR when not set explicitly. + * + * @return int Default options for libxml loader + */ + public static function getLibXmlLoaderOptions() + { + if (is_null(self::$_libXmlLoaderOptions)) { + self::setLibXmlLoaderOptions(LIBXML_DTDLOAD | LIBXML_DTDATTR); + } + @libxml_disable_entity_loader($options == (LIBXML_DTDLOAD | LIBXML_DTDATTR)); + return self::$_libXmlLoaderOptions; + } // function getLibXmlLoaderOptions +} diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/CodePage.php b/htdocs/includes/phpexcel/PHPExcel/Shared/CodePage.php index 5660e116ce0..2807ab37381 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/CodePage.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/CodePage.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_CodePage { @@ -39,16 +39,16 @@ class PHPExcel_Shared_CodePage * Convert Microsoft Code Page Identifier to Code Page Name which iconv * and mbstring understands * - * @param int $number Microsoft Code Page Indentifier + * @param integer $codePage Microsoft Code Page Indentifier * @return string Code Page Name - * @throws Exception + * @throws PHPExcel_Exception */ - public static function NumberToName($codePage = '1252') + public static function NumberToName($codePage = 1252) { switch ($codePage) { case 367: return 'ASCII'; break; // ASCII case 437: return 'CP437'; break; // OEM US - case 720: throw new Exception('Code page 720 not supported.'); + case 720: throw new PHPExcel_Exception('Code page 720 not supported.'); break; // OEM Arabic case 737: return 'CP737'; break; // OEM Greek case 775: return 'CP775'; break; // OEM Baltic @@ -85,17 +85,18 @@ class PHPExcel_Shared_CodePage case 10000: return 'MAC'; break; // Apple Roman case 10006: return 'MACGREEK'; break; // Macintosh Greek case 10007: return 'MACCYRILLIC'; break; // Macintosh Cyrillic + case 10008: return 'CP936'; break; // Macintosh - Simplified Chinese (GB 2312) case 10029: return 'MACCENTRALEUROPE'; break; // Macintosh Central Europe case 10079: return 'MACICELAND'; break; // Macintosh Icelandic case 10081: return 'MACTURKISH'; break; // Macintosh Turkish case 32768: return 'MAC'; break; // Apple Roman - case 32769: throw new Exception('Code page 32769 not supported.'); + case 32769: throw new PHPExcel_Exception('Code page 32769 not supported.'); break; // ANSI Latin I (BIFF2-BIFF3) case 65000: return 'UTF-7'; break; // Unicode (UTF-7) case 65001: return 'UTF-8'; break; // Unicode (UTF-8) } - throw new Exception('Unknown codepage: ' . $codePage); + throw new PHPExcel_Exception('Unknown codepage: ' . $codePage); } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/Date.php b/htdocs/includes/phpexcel/PHPExcel/Shared/Date.php index 2c1ab0088ba..7fe4f4207ef 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/Date.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/Date.php @@ -3,7 +3,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,9 +21,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -32,7 +32,7 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Date { @@ -58,36 +58,40 @@ class PHPExcel_Shared_Date 'Sep' => 'September', 'Oct' => 'October', 'Nov' => 'November', - 'Dec' => 'December' + 'Dec' => 'December', ); + /* + * Names of the months of the year, indexed by shortname + * Planned usage for locale settings + * + * @public + * @var string[] + */ + public static $_numberSuffixes = array( 'st', + 'nd', + 'rd', + 'th', + ); + /* * Base calendar year to use for calculations * * @private * @var int */ - private static $ExcelBaseDate = self::CALENDAR_WINDOWS_1900; - - /* - * Object type for PHP Date/Time values - * - * @private - * @var string - */ - public static $dateTimeObjectType = 'DateTime'; - + protected static $_excelBaseDate = self::CALENDAR_WINDOWS_1900; /** * Set the Excel calendar (Windows 1900 or Mac 1904) * - * @param integer $baseDate Excel base date + * @param integer $baseDate Excel base date (1900 or 1904) * @return boolean Success or failure */ public static function setExcelCalendar($baseDate) { if (($baseDate == self::CALENDAR_WINDOWS_1900) || ($baseDate == self::CALENDAR_MAC_1904)) { - self::$ExcelBaseDate = $baseDate; + self::$_excelBaseDate = $baseDate; return TRUE; } return FALSE; @@ -97,33 +101,36 @@ class PHPExcel_Shared_Date /** * Return the Excel calendar (Windows 1900 or Mac 1904) * - * @return integer $baseDate Excel base date + * @return integer Excel base date (1900 or 1904) */ public static function getExcelCalendar() { - return self::$ExcelBaseDate; + return self::$_excelBaseDate; } // function getExcelCalendar() /** - * Convert a date from Excel to PHP + * Convert a date from Excel to PHP * - * @param long $dateValue Excel date/time value - * @return long PHP serialized date/time + * @param long $dateValue Excel date/time value + * @param boolean $adjustToTimezone Flag indicating whether $dateValue should be treated as + * a UST timestamp, or adjusted to UST + * @param string $timezone The timezone for finding the adjustment from UST + * @return long PHP serialized date/time */ - public static function ExcelToPHP($dateValue = 0) { - if (self::$ExcelBaseDate == self::CALENDAR_WINDOWS_1900) { - $myExcelBaseDate = 25569; + public static function ExcelToPHP($dateValue = 0, $adjustToTimezone = FALSE, $timezone = NULL) { + if (self::$_excelBaseDate == self::CALENDAR_WINDOWS_1900) { + $my_excelBaseDate = 25569; // Adjust for the spurious 29-Feb-1900 (Day 60) if ($dateValue < 60) { - --$myExcelBaseDate; + --$my_excelBaseDate; } } else { - $myExcelBaseDate = 24107; + $my_excelBaseDate = 24107; } // Perform conversion if ($dateValue >= 1) { - $utcDays = $dateValue - $myExcelBaseDate; + $utcDays = $dateValue - $my_excelBaseDate; $returnValue = round($utcDays * 86400); if (($returnValue <= PHP_INT_MAX) && ($returnValue >= -PHP_INT_MAX)) { $returnValue = (integer) $returnValue; @@ -135,16 +142,20 @@ class PHPExcel_Shared_Date $returnValue = (integer) gmmktime($hours, $mins, $secs); } + $timezoneAdjustment = ($adjustToTimezone) ? + PHPExcel_Shared_TimeZone::getTimezoneAdjustment($timezone, $returnValue) : + 0; + // Return - return $returnValue; + return $returnValue + $timezoneAdjustment; } // function ExcelToPHP() /** * Convert a date from Excel to a PHP Date/Time object * - * @param long $dateValue Excel date/time value - * @return long PHP date/time object + * @param integer $dateValue Excel date/time value + * @return integer PHP date/time object */ public static function ExcelToPHPObject($dateValue = 0) { $dateTime = self::ExcelToPHP($dateValue); @@ -162,17 +173,20 @@ class PHPExcel_Shared_Date /** - * Convert a date from PHP to Excel + * Convert a date from PHP to Excel * - * @param mixed $dateValue PHP serialized date/time or date object - * @return mixed Excel date/time value - * or boolean FALSE on failure + * @param mixed $dateValue PHP serialized date/time or date object + * @param boolean $adjustToTimezone Flag indicating whether $dateValue should be treated as + * a UST timestamp, or adjusted to UST + * @param string $timezone The timezone for finding the adjustment from UST + * @return mixed Excel date/time value + * or boolean FALSE on failure */ - public static function PHPToExcel($dateValue = 0) { + public static function PHPToExcel($dateValue = 0, $adjustToTimezone = FALSE, $timezone = NULL) { $saveTimeZone = date_default_timezone_get(); date_default_timezone_set('UTC'); $retValue = FALSE; - if ((is_object($dateValue)) && ($dateValue instanceof self::$dateTimeObjectType)) { + if ((is_object($dateValue)) && ($dateValue instanceof DateTime)) { $retValue = self::FormattedPHPToExcel( $dateValue->format('Y'), $dateValue->format('m'), $dateValue->format('d'), $dateValue->format('H'), $dateValue->format('i'), $dateValue->format('s') ); @@ -199,16 +213,16 @@ class PHPExcel_Shared_Date * @return long Excel date/time value */ public static function FormattedPHPToExcel($year, $month, $day, $hours=0, $minutes=0, $seconds=0) { - if (self::$ExcelBaseDate == self::CALENDAR_WINDOWS_1900) { + if (self::$_excelBaseDate == self::CALENDAR_WINDOWS_1900) { // // Fudge factor for the erroneous fact that the year 1900 is treated as a Leap Year in MS Excel // This affects every date following 28th February 1900 // $excel1900isLeapYear = TRUE; if (($year == 1900) && ($month <= 2)) { $excel1900isLeapYear = FALSE; } - $myExcelBaseDate = 2415020; + $my_excelBaseDate = 2415020; } else { - $myExcelBaseDate = 2416481; + $my_excelBaseDate = 2416481; $excel1900isLeapYear = FALSE; } @@ -223,7 +237,7 @@ class PHPExcel_Shared_Date // Calculate the Julian Date, then subtract the Excel base date (JD 2415020 = 31-Dec-1899 Giving Excel Date of 0) $century = substr($year,0,2); $decade = substr($year,2,2); - $excelDate = floor((146097 * $century) / 4) + floor((1461 * $decade) / 4) + floor((153 * $month + 2) / 5) + $day + 1721119 - $myExcelBaseDate + $excel1900isLeapYear; + $excelDate = floor((146097 * $century) / 4) + floor((1461 * $decade) / 4) + floor((153 * $month + 2) / 5) + $day + 1721119 - $my_excelBaseDate + $excel1900isLeapYear; $excelTime = (($hours * 3600) + ($minutes * 60) + $seconds) / 86400; @@ -239,7 +253,7 @@ class PHPExcel_Shared_Date */ public static function isDateTime(PHPExcel_Cell $pCell) { return self::isDateTimeFormat( - $pCell->getParent()->getStyle( + $pCell->getWorksheet()->getStyle( $pCell->getCoordinate() )->getNumberFormat() ); @@ -266,11 +280,14 @@ class PHPExcel_Shared_Date * @return boolean */ public static function isDateTimeFormatCode($pFormatCode = '') { + if (strtolower($pFormatCode) === strtolower(PHPExcel_Style_NumberFormat::FORMAT_GENERAL)) + // "General" contains an epoch letter 'e', so we trap for it explicitly here (case-insensitive check) + return FALSE; + if (preg_match('/[0#]E[+-]0/i', $pFormatCode)) + // Scientific format + return FALSE; // Switch on formatcode switch ($pFormatCode) { - // General contains an epoch letter 'e', so we trap for it explicitly here - case PHPExcel_Style_NumberFormat::FORMAT_GENERAL: - return FALSE; // Explicitly defined date formats case PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD: case PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD2: @@ -306,10 +323,11 @@ class PHPExcel_Shared_Date // We might also have a format mask containing quoted strings... // we don't want to test for any of our characters within the quoted blocks if (strpos($pFormatCode,'"') !== FALSE) { - $i = FALSE; + $segMatcher = FALSE; foreach(explode('"',$pFormatCode) as $subVal) { // Only test in alternate array entries (the non-quoted blocks) - if (($i = !$i) && (preg_match('/(^|\])[^\[]*['.self::$possibleDateFormatCharacters.']/i',$subVal))) { + if (($segMatcher = !$segMatcher) && + (preg_match('/(^|\])[^\[]*['.self::$possibleDateFormatCharacters.']/i',$subVal))) { return TRUE; } } @@ -353,4 +371,23 @@ class PHPExcel_Shared_Date } + public static function monthStringToNumber($month) { + $monthIndex = 1; + foreach(self::$_monthNames as $shortMonthName => $longMonthName) { + if (($month === $longMonthName) || ($month === $shortMonthName)) { + return $monthIndex; + } + ++$monthIndex; + } + return $month; + } + + public static function dayStringToNumber($day) { + $strippedDayValue = (str_replace(self::$_numberSuffixes,'',$day)); + if (is_numeric($strippedDayValue)) { + return $strippedDayValue; + } + return $day; + } + } diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/Drawing.php b/htdocs/includes/phpexcel/PHPExcel/Shared/Drawing.php index 9401000dd8a..1d7af16bdc5 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/Drawing.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/Drawing.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Drawing { diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/Escher.php b/htdocs/includes/phpexcel/PHPExcel/Shared/Escher.php index ecd8216aa4c..983cbdaa029 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/Escher.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/Escher.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher { diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DgContainer.php b/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DgContainer.php index adbe429dbbc..3ec564c5663 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DgContainer.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DgContainer.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher_DgContainer { diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php b/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php index ea0235e8bfa..651eaf0eef5 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher_DgContainer_SpgrContainer { diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php b/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php index cb4988c8494..dde115401ca 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer { diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DggContainer.php b/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DggContainer.php index 4fddbdf3fd6..bf5f61f266c 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DggContainer.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DggContainer.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher_DggContainer { diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php b/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php index 428c76e6a41..d16bfc76e8c 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher_DggContainer_BstoreContainer { diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php b/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php index 1f10ae1767d..ea3c52a3772 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE { diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php b/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php index 0d28a6bf561..802ce6d943e 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Escher - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip { diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/Excel5.php b/htdocs/includes/phpexcel/PHPExcel/Shared/Excel5.php index 629f621c8e3..927dace9aca 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/Excel5.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/Excel5.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ /** @@ -30,7 +30,7 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Excel5 { @@ -40,7 +40,7 @@ class PHPExcel_Shared_Excel5 * This holds for Arial 10 * * @param PHPExcel_Worksheet $sheet The sheet - * @param integer $col The column + * @param string $col The column * @return integer The width in pixels */ public static function sizeCol($sheet, $col = 'A') @@ -136,9 +136,9 @@ class PHPExcel_Shared_Excel5 * * @param PHPExcel_Worksheet $sheet * @param string $startColumn - * @param integer $startOffset Offset within start cell measured in 1/1024 of the cell width + * @param integer $startOffsetX Offset within start cell measured in 1/1024 of the cell width * @param string $endColumn - * @param integer $endOffset Offset within end cell measured in 1/1024 of the cell width + * @param integer $endOffsetX Offset within end cell measured in 1/1024 of the cell width * @return integer Horizontal measured in pixels */ public static function getDistanceX(PHPExcel_Worksheet $sheet, $startColumn = 'A', $startOffsetX = 0, $endColumn = 'A', $endOffsetX = 0) @@ -166,10 +166,10 @@ class PHPExcel_Shared_Excel5 * The distanceY is found as sum of all the spanning rows minus two offsets * * @param PHPExcel_Worksheet $sheet - * @param string $startRow (1-based) - * @param integer $startOffset Offset within start cell measured in 1/256 of the cell height - * @param string $endRow (1-based) - * @param integer $endOffset Offset within end cell measured in 1/256 of the cell height + * @param integer $startRow (1-based) + * @param integer $startOffsetY Offset within start cell measured in 1/256 of the cell height + * @param integer $endRow (1-based) + * @param integer $endOffsetY Offset within end cell measured in 1/256 of the cell height * @return integer Vertical distance measured in pixels */ public static function getDistanceY(PHPExcel_Worksheet $sheet, $startRow = 1, $startOffsetY = 0, $endRow = 1, $endOffsetY = 0) diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/File.php b/htdocs/includes/phpexcel/PHPExcel/Shared/File.php index 575ac3cd22c..70756a0446a 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/File.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/File.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,10 +31,39 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_File { + /* + * Use Temp or File Upload Temp for temporary files + * + * @protected + * @var boolean + */ + protected static $_useUploadTempDirectory = FALSE; + + + /** + * Set the flag indicating whether the File Upload Temp directory should be used for temporary files + * + * @param boolean $useUploadTempDir Use File Upload Temporary directory (true or false) + */ + public static function setUseUploadTempDirectory($useUploadTempDir = FALSE) { + self::$_useUploadTempDirectory = (boolean) $useUploadTempDir; + } // function setUseUploadTempDirectory() + + + /** + * Get the flag indicating whether the File Upload Temp directory should be used for temporary files + * + * @return boolean Use File Upload Temporary directory (true or false) + */ + public static function getUseUploadTempDirectory() { + return self::$_useUploadTempDirectory; + } // function getUseUploadTempDirectory() + + /** * Verify if a file exists * @@ -105,9 +134,19 @@ class PHPExcel_Shared_File */ public static function sys_get_temp_dir() { + if (self::$_useUploadTempDirectory) { + // use upload-directory when defined to allow running on environments having very restricted + // open_basedir configs + if (ini_get('upload_tmp_dir') !== FALSE) { + if ($temp = ini_get('upload_tmp_dir')) { + if (file_exists($temp)) + return realpath($temp); + } + } + } + // sys_get_temp_dir is only available since PHP 5.2.1 // http://php.net/manual/en/function.sys-get-temp-dir.php#94119 - if ( !function_exists('sys_get_temp_dir')) { if ($temp = getenv('TMP') ) { if ((!empty($temp)) && (file_exists($temp))) { return realpath($temp); } diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/Font.php b/htdocs/includes/phpexcel/PHPExcel/Shared/Font.php index 3d0662e8830..203d4ecb4e3 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/Font.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/Font.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_Font { @@ -244,11 +244,11 @@ class PHPExcel_Shared_Font /** * Calculate an (approximate) OpenXML column width, based on font size and text contained * - * @param int $fontSize Font size (in pixels or points) - * @param bool $fontSizeInPixels Is the font size specified in pixels (true) or in points (false) ? - * @param string $cellText Text to calculate width - * @param int $rotation Rotation angle - * @return int Column width + * @param PHPExcel_Style_Font $font Font object + * @param PHPExcel_RichText|string $cellText Text to calculate width + * @param integer $rotation Rotation angle + * @param PHPExcel_Style_Font|NULL $defaultFont Font object + * @return integer Column width */ public static function calculateColumnWidth(PHPExcel_Style_Font $font, $cellText = '', $rotation = 0, PHPExcel_Style_Font $defaultFont = null) { @@ -271,7 +271,7 @@ class PHPExcel_Shared_Font try { // If autosize method is set to 'approx', use approximation if (self::$autoSizeMethod == self::AUTOSIZE_METHOD_APPROX) { - throw new Exception('AutoSize method is set to approx'); + throw new PHPExcel_Exception('AutoSize method is set to approx'); } // Width of text in pixels excl. padding @@ -280,7 +280,7 @@ class PHPExcel_Shared_Font // Excel adds some padding, use 1.07 of the width of an 'n' glyph $columnWidth += ceil(self::getTextWidthPixelsExact('0', $font, 0) * 1.07); // pixels incl. padding - } catch (Exception $e) { + } catch (PHPExcel_Exception $e) { // Width of text in pixels excl. padding, approximation $columnWidth = self::getTextWidthPixelsApprox($cellText, $font, $rotation); @@ -302,11 +302,11 @@ class PHPExcel_Shared_Font * @param PHPExcel_Style_Font * @param int $rotation * @return int - * @throws Exception + * @throws PHPExcel_Exception */ public static function getTextWidthPixelsExact($text, PHPExcel_Style_Font $font, $rotation = 0) { if (!function_exists('imagettfbbox')) { - throw new Exception('GD library needs to be enabled'); + throw new PHPExcel_Exception('GD library needs to be enabled'); } // font size should really be supplied in pixels in GD2, @@ -425,7 +425,7 @@ class PHPExcel_Shared_Font */ public static function getTrueTypeFontFileFromFont($font) { if (!file_exists(self::$trueTypeFontPath) || !is_dir(self::$trueTypeFontPath)) { - throw new Exception('Valid directory to TrueType Font files not specified'); + throw new PHPExcel_Exception('Valid directory to TrueType Font files not specified'); } $name = $font->getName(); @@ -530,7 +530,7 @@ class PHPExcel_Shared_Font break; default: - throw new Exception('Unknown font name "'. $name .'". Cannot map to TrueType font file'); + throw new PHPExcel_Exception('Unknown font name "'. $name .'". Cannot map to TrueType font file'); break; } @@ -538,7 +538,7 @@ class PHPExcel_Shared_Font // Check if file actually exists if (!file_exists($fontFile)) { - throw New Exception('TrueType Font file not found'); + throw New PHPExcel_Exception('TrueType Font file not found'); } return $fontFile; diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/CholeskyDecomposition.php b/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/CholeskyDecomposition.php index 9d064f9e63a..cfbaa53bc8d 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/CholeskyDecomposition.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/CholeskyDecomposition.php @@ -73,7 +73,7 @@ class CholeskyDecomposition { } } } else { - throw new Exception(JAMAError(ArgumentTypeException)); + throw new PHPExcel_Calculation_Exception(JAMAError(ArgumentTypeException)); } } // function __construct() @@ -136,13 +136,13 @@ class CholeskyDecomposition { return new Matrix($X, $this->m, $nx); } else { - throw new Exception(JAMAError(MatrixSPDException)); + throw new PHPExcel_Calculation_Exception(JAMAError(MatrixSPDException)); } } else { - throw new Exception(JAMAError(MatrixDimensionException)); + throw new PHPExcel_Calculation_Exception(JAMAError(MatrixDimensionException)); } } else { - throw new Exception(JAMAError(ArgumentTypeException)); + throw new PHPExcel_Calculation_Exception(JAMAError(ArgumentTypeException)); } } // function solve() diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/LUDecomposition.php b/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/LUDecomposition.php index 6c797a6ce00..08e500cf75a 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/LUDecomposition.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/LUDecomposition.php @@ -115,7 +115,7 @@ class PHPExcel_Shared_JAMA_LUDecomposition { } } } else { - throw new Exception(PHPExcel_Shared_JAMA_Matrix::ArgumentTypeException); + throw new PHPExcel_Calculation_Exception(PHPExcel_Shared_JAMA_Matrix::ArgumentTypeException); } } // function __construct() @@ -208,7 +208,7 @@ class PHPExcel_Shared_JAMA_LUDecomposition { } return $d; } else { - throw new Exception(PHPExcel_Shared_JAMA_Matrix::MatrixDimensionException); + throw new PHPExcel_Calculation_Exception(PHPExcel_Shared_JAMA_Matrix::MatrixDimensionException); } } // function det() @@ -218,8 +218,8 @@ class PHPExcel_Shared_JAMA_LUDecomposition { * * @param $B A Matrix with as many rows as A and any number of columns. * @return X so that L*U*X = B(piv,:) - * @exception IllegalArgumentException Matrix row dimensions must agree. - * @exception RuntimeException Matrix is singular. + * @PHPExcel_Calculation_Exception IllegalArgumentException Matrix row dimensions must agree. + * @PHPExcel_Calculation_Exception RuntimeException Matrix is singular. */ public function solve($B) { if ($B->getRowDimension() == $this->m) { @@ -248,10 +248,10 @@ class PHPExcel_Shared_JAMA_LUDecomposition { } return $X; } else { - throw new Exception(self::MatrixSingularException); + throw new PHPExcel_Calculation_Exception(self::MatrixSingularException); } } else { - throw new Exception(self::MatrixSquareException); + throw new PHPExcel_Calculation_Exception(self::MatrixSquareException); } } // function solve() diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/Matrix.php b/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/Matrix.php index aae40e4c57a..b893a447a8e 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/Matrix.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/Matrix.php @@ -102,15 +102,15 @@ class PHPExcel_Shared_JAMA_Matrix { } } } else { - throw new Exception(self::ArrayLengthException); + throw new PHPExcel_Calculation_Exception(self::ArrayLengthException); } break; default: - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); break; } } else { - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); } } // function __construct() @@ -177,8 +177,8 @@ class PHPExcel_Shared_JAMA_Matrix { //A($i0...; $j0...) case 'integer,integer': list($i0, $j0) = $args; - if ($i0 >= 0) { $m = $this->m - $i0; } else { throw new Exception(self::ArgumentBoundsException); } - if ($j0 >= 0) { $n = $this->n - $j0; } else { throw new Exception(self::ArgumentBoundsException); } + if ($i0 >= 0) { $m = $this->m - $i0; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } + if ($j0 >= 0) { $n = $this->n - $j0; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } $R = new PHPExcel_Shared_JAMA_Matrix($m, $n); for($i = $i0; $i < $this->m; ++$i) { for($j = $j0; $j < $this->n; ++$j) { @@ -190,8 +190,8 @@ class PHPExcel_Shared_JAMA_Matrix { //A($i0...$iF; $j0...$jF) case 'integer,integer,integer,integer': list($i0, $iF, $j0, $jF) = $args; - if (($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0)) { $m = $iF - $i0; } else { throw new Exception(self::ArgumentBoundsException); } - if (($jF > $j0) && ($this->n >= $jF) && ($j0 >= 0)) { $n = $jF - $j0; } else { throw new Exception(self::ArgumentBoundsException); } + if (($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0)) { $m = $iF - $i0; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } + if (($jF > $j0) && ($this->n >= $jF) && ($j0 >= 0)) { $n = $jF - $j0; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } $R = new PHPExcel_Shared_JAMA_Matrix($m+1, $n+1); for($i = $i0; $i <= $iF; ++$i) { for($j = $j0; $j <= $jF; ++$j) { @@ -203,8 +203,8 @@ class PHPExcel_Shared_JAMA_Matrix { //$R = array of row indices; $C = array of column indices case 'array,array': list($RL, $CL) = $args; - if (count($RL) > 0) { $m = count($RL); } else { throw new Exception(self::ArgumentBoundsException); } - if (count($CL) > 0) { $n = count($CL); } else { throw new Exception(self::ArgumentBoundsException); } + if (count($RL) > 0) { $m = count($RL); } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } + if (count($CL) > 0) { $n = count($CL); } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } $R = new PHPExcel_Shared_JAMA_Matrix($m, $n); for($i = 0; $i < $m; ++$i) { for($j = 0; $j < $n; ++$j) { @@ -216,8 +216,8 @@ class PHPExcel_Shared_JAMA_Matrix { //$RL = array of row indices; $CL = array of column indices case 'array,array': list($RL, $CL) = $args; - if (count($RL) > 0) { $m = count($RL); } else { throw new Exception(self::ArgumentBoundsException); } - if (count($CL) > 0) { $n = count($CL); } else { throw new Exception(self::ArgumentBoundsException); } + if (count($RL) > 0) { $m = count($RL); } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } + if (count($CL) > 0) { $n = count($CL); } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } $R = new PHPExcel_Shared_JAMA_Matrix($m, $n); for($i = 0; $i < $m; ++$i) { for($j = 0; $j < $n; ++$j) { @@ -229,8 +229,8 @@ class PHPExcel_Shared_JAMA_Matrix { //A($i0...$iF); $CL = array of column indices case 'integer,integer,array': list($i0, $iF, $CL) = $args; - if (($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0)) { $m = $iF - $i0; } else { throw new Exception(self::ArgumentBoundsException); } - if (count($CL) > 0) { $n = count($CL); } else { throw new Exception(self::ArgumentBoundsException); } + if (($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0)) { $m = $iF - $i0; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } + if (count($CL) > 0) { $n = count($CL); } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } $R = new PHPExcel_Shared_JAMA_Matrix($m, $n); for($i = $i0; $i < $iF; ++$i) { for($j = 0; $j < $n; ++$j) { @@ -242,8 +242,8 @@ class PHPExcel_Shared_JAMA_Matrix { //$RL = array of row indices case 'array,integer,integer': list($RL, $j0, $jF) = $args; - if (count($RL) > 0) { $m = count($RL); } else { throw new Exception(self::ArgumentBoundsException); } - if (($jF >= $j0) && ($this->n >= $jF) && ($j0 >= 0)) { $n = $jF - $j0; } else { throw new Exception(self::ArgumentBoundsException); } + if (count($RL) > 0) { $m = count($RL); } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } + if (($jF >= $j0) && ($this->n >= $jF) && ($j0 >= 0)) { $n = $jF - $j0; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } $R = new PHPExcel_Shared_JAMA_Matrix($m, $n+1); for($i = 0; $i < $m; ++$i) { for($j = $j0; $j <= $jF; ++$j) { @@ -253,11 +253,11 @@ class PHPExcel_Shared_JAMA_Matrix { return $R; break; default: - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); break; } } else { - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); } } // function getMatrix() @@ -274,10 +274,10 @@ class PHPExcel_Shared_JAMA_Matrix { if (($this->m == $B->getRowDimension()) && ($this->n == $B->getColumnDimension())) { return true; } else { - throw new Exception(self::MatrixDimensionException); + throw new PHPExcel_Calculation_Exception(self::MatrixDimensionException); } } else { - throw new Exception(self::ArgumentTypeException); + throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } } // function checkMatrixDimensions() @@ -345,7 +345,7 @@ class PHPExcel_Shared_JAMA_Matrix { return $this->getMatrix($i0, 0, $i0 + 1, $this->n); } } else { - throw new Exception(self::ArgumentTypeException); + throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } } // function getMatrixByRow() @@ -366,7 +366,7 @@ class PHPExcel_Shared_JAMA_Matrix { return $this->getMatrix(0, $j0, $this->m, $j0 + 1); } } else { - throw new Exception(self::ArgumentTypeException); + throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } } // function getMatrixByCol() @@ -428,13 +428,13 @@ class PHPExcel_Shared_JAMA_Matrix { switch($match) { case 'object': - if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); } + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } break; case 'array': $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); break; default: - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); break; } $this->checkMatrixDimensions($M); @@ -445,7 +445,7 @@ class PHPExcel_Shared_JAMA_Matrix { } return $M; } else { - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); } } // function plus() @@ -464,13 +464,13 @@ class PHPExcel_Shared_JAMA_Matrix { switch($match) { case 'object': - if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); } + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } break; case 'array': $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); break; default: - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); break; } $this->checkMatrixDimensions($M); @@ -495,7 +495,7 @@ class PHPExcel_Shared_JAMA_Matrix { } return $this; } else { - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); } } // function plusEquals() @@ -514,13 +514,13 @@ class PHPExcel_Shared_JAMA_Matrix { switch($match) { case 'object': - if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); } + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } break; case 'array': $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); break; default: - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); break; } $this->checkMatrixDimensions($M); @@ -531,7 +531,7 @@ class PHPExcel_Shared_JAMA_Matrix { } return $M; } else { - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); } } // function minus() @@ -550,13 +550,13 @@ class PHPExcel_Shared_JAMA_Matrix { switch($match) { case 'object': - if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); } + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } break; case 'array': $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); break; default: - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); break; } $this->checkMatrixDimensions($M); @@ -581,7 +581,7 @@ class PHPExcel_Shared_JAMA_Matrix { } return $this; } else { - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); } } // function minusEquals() @@ -601,13 +601,13 @@ class PHPExcel_Shared_JAMA_Matrix { switch($match) { case 'object': - if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); } + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } break; case 'array': $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); break; default: - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); break; } $this->checkMatrixDimensions($M); @@ -618,7 +618,7 @@ class PHPExcel_Shared_JAMA_Matrix { } return $M; } else { - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); } } // function arrayTimes() @@ -638,13 +638,13 @@ class PHPExcel_Shared_JAMA_Matrix { switch($match) { case 'object': - if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); } + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } break; case 'array': $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); break; default: - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); break; } $this->checkMatrixDimensions($M); @@ -669,7 +669,7 @@ class PHPExcel_Shared_JAMA_Matrix { } return $this; } else { - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); } } // function arrayTimesEquals() @@ -689,13 +689,13 @@ class PHPExcel_Shared_JAMA_Matrix { switch($match) { case 'object': - if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); } + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } break; case 'array': $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); break; default: - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); break; } $this->checkMatrixDimensions($M); @@ -725,7 +725,7 @@ class PHPExcel_Shared_JAMA_Matrix { } return $M; } else { - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); } } // function arrayRightDivide() @@ -745,13 +745,13 @@ class PHPExcel_Shared_JAMA_Matrix { switch($match) { case 'object': - if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); } + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } break; case 'array': $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); break; default: - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); break; } $this->checkMatrixDimensions($M); @@ -762,7 +762,7 @@ class PHPExcel_Shared_JAMA_Matrix { } return $M; } else { - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); } } // function arrayRightDivideEquals() @@ -782,13 +782,13 @@ class PHPExcel_Shared_JAMA_Matrix { switch($match) { case 'object': - if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); } + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } break; case 'array': $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); break; default: - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); break; } $this->checkMatrixDimensions($M); @@ -799,7 +799,7 @@ class PHPExcel_Shared_JAMA_Matrix { } return $M; } else { - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); } } // function arrayLeftDivide() @@ -819,13 +819,13 @@ class PHPExcel_Shared_JAMA_Matrix { switch($match) { case 'object': - if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); } + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } break; case 'array': $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); break; default: - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); break; } $this->checkMatrixDimensions($M); @@ -836,7 +836,7 @@ class PHPExcel_Shared_JAMA_Matrix { } return $M; } else { - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); } } // function arrayLeftDivideEquals() @@ -855,7 +855,7 @@ class PHPExcel_Shared_JAMA_Matrix { switch($match) { case 'object': - if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $B = $args[0]; } else { throw new Exception(self::ArgumentTypeException); } + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $B = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } if ($this->n == $B->m) { $C = new PHPExcel_Shared_JAMA_Matrix($this->m, $B->n); for($j = 0; $j < $B->n; ++$j) { @@ -873,7 +873,7 @@ class PHPExcel_Shared_JAMA_Matrix { } return $C; } else { - throw new Exception(JAMAError(MatrixDimensionMismatch)); + throw new PHPExcel_Calculation_Exception(JAMAError(MatrixDimensionMismatch)); } break; case 'array': @@ -891,7 +891,7 @@ class PHPExcel_Shared_JAMA_Matrix { } return $C; } else { - throw new Exception(JAMAError(MatrixDimensionMismatch)); + throw new PHPExcel_Calculation_Exception(JAMAError(MatrixDimensionMismatch)); } return $M; break; @@ -923,11 +923,11 @@ class PHPExcel_Shared_JAMA_Matrix { return $C; break; default: - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); break; } } else { - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); } } // function times() @@ -946,13 +946,13 @@ class PHPExcel_Shared_JAMA_Matrix { switch($match) { case 'object': - if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); } + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } break; case 'array': $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); break; default: - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); break; } $this->checkMatrixDimensions($M); @@ -977,7 +977,7 @@ class PHPExcel_Shared_JAMA_Matrix { } return $this; } else { - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); } } // function power() @@ -996,12 +996,12 @@ class PHPExcel_Shared_JAMA_Matrix { switch($match) { case 'object': - if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new Exception(self::ArgumentTypeException); } + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } case 'array': $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); break; default: - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); break; } $this->checkMatrixDimensions($M); @@ -1012,7 +1012,7 @@ class PHPExcel_Shared_JAMA_Matrix { } return $this; } else { - throw new Exception(self::PolymorphicArgumentException); + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); } } // function concat() diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/QRDecomposition.php b/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/QRDecomposition.php index 49293d7eca7..7538462987d 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/QRDecomposition.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/QRDecomposition.php @@ -88,7 +88,7 @@ class PHPExcel_Shared_JAMA_QRDecomposition { $this->Rdiag[$k] = -$nrm; } } else { - throw new Exception(PHPExcel_Shared_JAMA_Matrix::ArgumentTypeException); + throw new PHPExcel_Calculation_Exception(PHPExcel_Shared_JAMA_Matrix::ArgumentTypeException); } } // function __construct() @@ -224,10 +224,10 @@ class PHPExcel_Shared_JAMA_QRDecomposition { $X = new PHPExcel_Shared_JAMA_Matrix($X); return ($X->getMatrix(0, $this->n-1, 0, $nx)); } else { - throw new Exception(self::MatrixRankException); + throw new PHPExcel_Calculation_Exception(self::MatrixRankException); } } else { - throw new Exception(PHPExcel_Shared_JAMA_Matrix::MatrixDimensionException); + throw new PHPExcel_Calculation_Exception(PHPExcel_Shared_JAMA_Matrix::MatrixDimensionException); } } // function solve() diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/LMQuadTest.php b/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/LMQuadTest.php deleted file mode 100644 index 2f316de9730..00000000000 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/LMQuadTest.php +++ /dev/null @@ -1,116 +0,0 @@ -val($x[$i], $a); - print("Quad ".$c.",".$r." -> ".$y[$i]."
"); - $s[$i] = 1.; - ++$i; - } - } - print("quad x= "); - - $qx = new Matrix($x); - $qx->print(10, 2); - - print("quad y= "); - $qy = new Matrix($y, $npts); - $qy->print(10, 2); - - $o[0] = $x; - $o[1] = $a; - $o[2] = $y; - $o[3] = $s; - - return $o; - } // function testdata() - -} // class LMQuadTest diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/LagrangeInterpolation.php b/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/LagrangeInterpolation.php deleted file mode 100644 index 5b742861350..00000000000 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/LagrangeInterpolation.php +++ /dev/null @@ -1,59 +0,0 @@ -solve($b); - - return $s->getRowPackedCopy(); - } // function findPolynomialFactors() - -} // class LagrangeInterpolation - - -$x = array(2.0, 1.0, 3.0); -$y = array(3.0, 4.0, 7.0); - -$li = new LagrangeInterpolation; -$f = $li->findPolynomialFactors($x, $y); - - -for ($i = 0; $i < 3; ++$i) { - echo $f[$i]."
"; -} diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/LagrangeInterpolation2.php b/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/LagrangeInterpolation2.php deleted file mode 100644 index e7529c5f162..00000000000 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/LagrangeInterpolation2.php +++ /dev/null @@ -1,59 +0,0 @@ -solve($b); - - return $s->getRowPackedCopy(); - } // function findPolynomialFactors() - -} // class LagrangeInterpolation - - -$x = array(2.0, 1.0, 3.0); -$y = array(3.0, 4.0, 7.0); - -$li = new LagrangeInterpolation; -$f = $li->findPolynomialFactors($x, $y); - -for ($i = 0; $i < 3; ++$i) { - echo $f[$i]."
"; -} diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/LevenbergMarquardt.php b/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/LevenbergMarquardt.php deleted file mode 100644 index 7cfd5f89976..00000000000 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/LevenbergMarquardt.php +++ /dev/null @@ -1,185 +0,0 @@ -val($x[$i], $a); - $d = $d / $s[$i]; - $sum = $sum + ($d*$d); - } - - return $sum; - } // function chiSquared() - - - /** - * Minimize E = sum {(y[k] - f(x[k],a)) / s[k]}^2 - * The individual errors are optionally scaled by s[k]. - * Note that LMfunc implements the value and gradient of f(x,a), - * NOT the value and gradient of E with respect to a! - * - * @param x array of domain points, each may be multidimensional - * @param y corresponding array of values - * @param a the parameters/state of the model - * @param vary false to indicate the corresponding a[k] is to be held fixed - * @param s2 sigma^2 for point i - * @param lambda blend between steepest descent (lambda high) and - * jump to bottom of quadratic (lambda zero). - * Start with 0.001. - * @param termepsilon termination accuracy (0.01) - * @param maxiter stop and return after this many iterations if not done - * @param verbose set to zero (no prints), 1, 2 - * - * @return the new lambda for future iterations. - * Can use this and maxiter to interleave the LM descent with some other - * task, setting maxiter to something small. - */ - function solve($x, $a, $y, $s, $vary, $f, $lambda, $termepsilon, $maxiter, $verbose) { - $npts = count($y); - $nparm = count($a); - - if ($verbose > 0) { - print("solve x[".count($x)."][".count($x[0])."]"); - print(" a[".count($a)."]"); - println(" y[".count(length)."]"); - } - - $e0 = $this->chiSquared($x, $a, $y, $s, $f); - - //double lambda = 0.001; - $done = false; - - // g = gradient, H = hessian, d = step to minimum - // H d = -g, solve for d - $H = array(); - $g = array(); - - //double[] d = new double[nparm]; - - $oos2 = array(); - - for($i = 0; $i < $npts; ++$i) { - $oos2[$i] = 1./($s[$i]*$s[$i]); - } - $iter = 0; - $term = 0; // termination count test - - do { - ++$iter; - - // hessian approximation - for( $r = 0; $r < $nparm; ++$r) { - for( $c = 0; $c < $nparm; ++$c) { - for( $i = 0; $i < $npts; ++$i) { - if ($i == 0) $H[$r][$c] = 0.; - $xi = $x[$i]; - $H[$r][$c] += ($oos2[$i] * $f->grad($xi, $a, $r) * $f->grad($xi, $a, $c)); - } //npts - } //c - } //r - - // boost diagonal towards gradient descent - for( $r = 0; $r < $nparm; ++$r) - $H[$r][$r] *= (1. + $lambda); - - // gradient - for( $r = 0; $r < $nparm; ++$r) { - for( $i = 0; $i < $npts; ++$i) { - if ($i == 0) $g[$r] = 0.; - $xi = $x[$i]; - $g[$r] += ($oos2[$i] * ($y[$i]-$f->val($xi,$a)) * $f->grad($xi, $a, $r)); - } - } //npts - - // scale (for consistency with NR, not necessary) - if ($false) { - for( $r = 0; $r < $nparm; ++$r) { - $g[$r] = -0.5 * $g[$r]; - for( $c = 0; $c < $nparm; ++$c) { - $H[$r][$c] *= 0.5; - } - } - } - - // solve H d = -g, evaluate error at new location - //double[] d = DoubleMatrix.solve(H, g); -// double[] d = (new Matrix(H)).lu().solve(new Matrix(g, nparm)).getRowPackedCopy(); - //double[] na = DoubleVector.add(a, d); -// double[] na = (new Matrix(a, nparm)).plus(new Matrix(d, nparm)).getRowPackedCopy(); -// double e1 = chiSquared(x, na, y, s, f); - -// if (verbose > 0) { -// System.out.println("\n\niteration "+iter+" lambda = "+lambda); -// System.out.print("a = "); -// (new Matrix(a, nparm)).print(10, 2); -// if (verbose > 1) { -// System.out.print("H = "); -// (new Matrix(H)).print(10, 2); -// System.out.print("g = "); -// (new Matrix(g, nparm)).print(10, 2); -// System.out.print("d = "); -// (new Matrix(d, nparm)).print(10, 2); -// } -// System.out.print("e0 = " + e0 + ": "); -// System.out.print("moved from "); -// (new Matrix(a, nparm)).print(10, 2); -// System.out.print("e1 = " + e1 + ": "); -// if (e1 < e0) { -// System.out.print("to "); -// (new Matrix(na, nparm)).print(10, 2); -// } else { -// System.out.println("move rejected"); -// } -// } - - // termination test (slightly different than NR) -// if (Math.abs(e1-e0) > termepsilon) { -// term = 0; -// } else { -// term++; -// if (term == 4) { -// System.out.println("terminating after " + iter + " iterations"); -// done = true; -// } -// } -// if (iter >= maxiter) done = true; - - // in the C++ version, found that changing this to e1 >= e0 - // was not a good idea. See comment there. - // -// if (e1 > e0 || Double.isNaN(e1)) { // new location worse than before -// lambda *= 10.; -// } else { // new location better, accept new parameters -// lambda *= 0.1; -// e0 = e1; -// // simply assigning a = na will not get results copied back to caller -// for( int i = 0; i < nparm; i++ ) { -// if (vary[i]) a[i] = na[i]; -// } -// } - } while(!$done); - - return $lambda; - } // function solve() - -} // class LevenbergMarquardt diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/MagicSquareExample.php b/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/MagicSquareExample.php deleted file mode 100644 index e6c93d05b20..00000000000 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/MagicSquareExample.php +++ /dev/null @@ -1,182 +0,0 @@ -magic($p); - $M = array(); - for ($j = 0; $j < $p; ++$j) { - for ($i = 0; $i < $p; ++$i) { - $aij = $A->get($i,$j); - $M[$i][$j] = $aij; - $M[$i][$j+$p] = $aij + 2*$p*$p; - $M[$i+$p][$j] = $aij + 3*$p*$p; - $M[$i+$p][$j+$p] = $aij + $p*$p; - } - } - - for ($i = 0; $i < $p; ++$i) { - for ($j = 0; $j < $k; ++$j) { - $t = $M[$i][$j]; - $M[$i][$j] = $M[$i+$p][$j]; - $M[$i+$p][$j] = $t; - } - for ($j = $n-$k+1; $j < $n; ++$j) { - $t = $M[$i][$j]; - $M[$i][$j] = $M[$i+$p][$j]; - $M[$i+$p][$j] = $t; - } - } - - $t = $M[$k][0]; $M[$k][0] = $M[$k+$p][0]; $M[$k+$p][0] = $t; - $t = $M[$k][$k]; $M[$k][$k] = $M[$k+$p][$k]; $M[$k+$p][$k] = $t; - - } - - return new Matrix($M); - - } - - /** - * Simple function to replicate PHP 5 behaviour - */ - function microtime_float() { - list($usec, $sec) = explode(" ", microtime()); - return ((float)$usec + (float)$sec); - } - - /** - * Tests LU, QR, SVD and symmetric Eig decompositions. - * - * n = order of magic square. - * trace = diagonal sum, should be the magic sum, (n^3 + n)/2. - * max_eig = maximum eigenvalue of (A + A')/2, should equal trace. - * rank = linear algebraic rank, should equal n if n is odd, - * be less than n if n is even. - * cond = L_2 condition number, ratio of singular values. - * lu_res = test of LU factorization, norm1(L*U-A(p,:))/(n*eps). - * qr_res = test of QR factorization, norm1(Q*R-A)/(n*eps). - */ - function main() { - ?> -

Test of Matrix Class, using magic squares.

-

See MagicSquareExample.main() for an explanation.

- - - - - - - - - - - microtime_float(); - $eps = pow(2.0,-52.0); - for ($n = 3; $n <= 6; ++$n) { - echo ""; - - echo ""; - - $M = $this->magic($n); - $t = (int) $M->trace(); - - echo ""; - - $O = $M->plus($M->transpose()); - $E = new EigenvalueDecomposition($O->times(0.5)); - $d = $E->getRealEigenvalues(); - - echo ""; - - $r = $M->rank(); - - echo ""; - - $c = $M->cond(); - - if ($c < 1/$eps) - echo ""; - else - echo ""; - - $LU = new LUDecomposition($M); - $L = $LU->getL(); - $U = $LU->getU(); - $p = $LU->getPivot(); - // Java version: R = L.times(U).minus(M.getMatrix(p,0,n-1)); - $S = $L->times($U); - $R = $S->minus($M->getMatrix($p,0,$n-1)); - $res = $R->norm1()/($n*$eps); - - echo ""; - - $QR = new QRDecomposition($M); - $Q = $QR->getQ(); - $R = $QR->getR(); - $S = $Q->times($R); - $R = $S->minus($M); - $res = $R->norm1()/($n*$eps); - - echo ""; - - echo ""; - - } - echo "
ntracemax_eigrankcondlu_resqr_res
$n$t".$d[$n-1]."".$r."".sprintf("%.3f",$c)."Inf".sprintf("%.3f",$res)."".sprintf("%.3f",$res)."
"; - echo "
"; - - $stop_time = $this->microtime_float(); - $etime = $stop_time - $start_time; - - echo "

Elapsed time is ". sprintf("%.4f",$etime) ." seconds.

"; - - } - -} - -$magic = new MagicSquareExample(); -$magic->main(); - -?> diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/Stats.php b/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/Stats.php deleted file mode 100644 index 38bc4b7d86c..00000000000 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/Stats.php +++ /dev/null @@ -1,1605 +0,0 @@ - | -// +----------------------------------------------------------------------+ -// -// $Id: Stats.php,v 1.15 2003/06/01 11:40:30 jmcastagnetto Exp $ -// - -include_once 'PEAR.php'; - -/** -* @package Math_Stats -*/ - -// Constants for defining the statistics to calculate /*{{{*/ -/** -* STATS_BASIC to generate the basic descriptive statistics -*/ -define('STATS_BASIC', 1); -/** -* STATS_FULL to generate also higher moments, mode, median, etc. -*/ -define('STATS_FULL', 2); -/*}}}*/ - -// Constants describing the data set format /*{{{*/ -/** -* STATS_DATA_SIMPLE for an array of numeric values. This is the default. -* e.g. $data = array(2,3,4,5,1,1,6); -*/ -define('STATS_DATA_SIMPLE', 0); -/** -* STATS_DATA_CUMMULATIVE for an associative array of frequency values, -* where in each array entry, the index is the data point and the -* value the count (frequency): -* e.g. $data = array(3=>4, 2.3=>5, 1.25=>6, 0.5=>3) -*/ -define('STATS_DATA_CUMMULATIVE', 1); -/*}}}*/ - -// Constants defining how to handle nulls /*{{{*/ -/** -* STATS_REJECT_NULL, reject data sets with null values. This is the default. -* Any non-numeric value is considered a null in this context. -*/ -define('STATS_REJECT_NULL', -1); -/** -* STATS_IGNORE_NULL, ignore null values and prune them from the data. -* Any non-numeric value is considered a null in this context. -*/ -define('STATS_IGNORE_NULL', -2); -/** -* STATS_USE_NULL_AS_ZERO, assign the value of 0 (zero) to null values. -* Any non-numeric value is considered a null in this context. -*/ -define('STATS_USE_NULL_AS_ZERO', -3); -/*}}}*/ - -/** -* A class to calculate descriptive statistics from a data set. -* Data sets can be simple arrays of data, or a cummulative hash. -* The second form is useful when passing large data set, -* for example the data set: -* -*
-* $data1 = array (1,2,1,1,1,1,3,3,4.1,3,2,2,4.1,1,1,2,3,3,2,2,1,1,2,2);
-* 
-* -* can be epxressed more compactly as: -* -*
-* $data2 = array('1'=>9, '2'=>8, '3'=>5, '4.1'=>2);
-* 
-* -* Example of use: -* -*
-* include_once 'Math/Stats.php';
-* $s = new Math_Stats();
-* $s->setData($data1);
-* // or
-* // $s->setData($data2, STATS_DATA_CUMMULATIVE);
-* $stats = $s->calcBasic();
-* echo 'Mean: '.$stats['mean'].' StDev: '.$stats['stdev'].' 
\n'; -* -* // using data with nulls -* // first ignoring them: -* $data3 = array(1.2, 'foo', 2.4, 3.1, 4.2, 3.2, null, 5.1, 6.2); -* $s->setNullOption(STATS_IGNORE_NULL); -* $s->setData($data3); -* $stats3 = $s->calcFull(); -* -* // and then assuming nulls == 0 -* $s->setNullOption(STATS_USE_NULL_AS_ZERO); -* $s->setData($data3); -* $stats3 = $s->calcFull(); -*
-* -* Originally this class was part of NumPHP (Numeric PHP package) -* -* @author Jesus M. Castagnetto -* @version 0.8 -* @access public -* @package Math_Stats -*/ -class Base {/*{{{*/ - // properties /*{{{*/ - - /** - * The simple or cummulative data set. - * Null by default. - * - * @access private - * @var array - */ - public $_data = null; - - /** - * Expanded data set. Only set when cummulative data - * is being used. Null by default. - * - * @access private - * @var array - */ - public $_dataExpanded = null; - - /** - * Flag for data type, one of STATS_DATA_SIMPLE or - * STATS_DATA_CUMMULATIVE. Null by default. - * - * @access private - * @var int - */ - public $_dataOption = null; - - /** - * Flag for null handling options. One of STATS_REJECT_NULL, - * STATS_IGNORE_NULL or STATS_USE_NULL_AS_ZERO - * - * @access private - * @var int - */ - public $_nullOption; - - /** - * Array for caching result values, should be reset - * when using setData() - * - * @access private - * @var array - */ - public $_calculatedValues = array(); - - /*}}}*/ - - /** - * Constructor for the class - * - * @access public - * @param optional int $nullOption how to handle null values - * @return object Math_Stats - */ - function Math_Stats($nullOption=STATS_REJECT_NULL) {/*{{{*/ - $this->_nullOption = $nullOption; - }/*}}}*/ - - /** - * Sets and verifies the data, checking for nulls and using - * the current null handling option - * - * @access public - * @param array $arr the data set - * @param optional int $opt data format: STATS_DATA_CUMMULATIVE or STATS_DATA_SIMPLE (default) - * @return mixed true on success, a PEAR_Error object otherwise - */ - function setData($arr, $opt=STATS_DATA_SIMPLE) {/*{{{*/ - if (!is_array($arr)) { - return PEAR::raiseError('invalid data, an array of numeric data was expected'); - } - $this->_data = null; - $this->_dataExpanded = null; - $this->_dataOption = null; - $this->_calculatedValues = array(); - if ($opt == STATS_DATA_SIMPLE) { - $this->_dataOption = $opt; - $this->_data = array_values($arr); - } else if ($opt == STATS_DATA_CUMMULATIVE) { - $this->_dataOption = $opt; - $this->_data = $arr; - $this->_dataExpanded = array(); - } - return $this->_validate(); - }/*}}}*/ - - /** - * Returns the data which might have been modified - * according to the current null handling options. - * - * @access public - * @param boolean $expanded whether to return a expanded list, default is false - * @return mixed array of data on success, a PEAR_Error object otherwise - * @see _validate() - */ - function getData($expanded=false) {/*{{{*/ - if ($this->_data == null) { - return PEAR::raiseError('data has not been set'); - } - if ($this->_dataOption == STATS_DATA_CUMMULATIVE && $expanded) { - return $this->_dataExpanded; - } else { - return $this->_data; - } - }/*}}}*/ - - /** - * Sets the null handling option. - * Must be called before assigning a new data set containing null values - * - * @access public - * @return mixed true on success, a PEAR_Error object otherwise - * @see _validate() - */ - function setNullOption($nullOption) {/*{{{*/ - if ($nullOption == STATS_REJECT_NULL - || $nullOption == STATS_IGNORE_NULL - || $nullOption == STATS_USE_NULL_AS_ZERO) { - $this->_nullOption = $nullOption; - return true; - } else { - return PEAR::raiseError('invalid null handling option expecting: '. - 'STATS_REJECT_NULL, STATS_IGNORE_NULL or STATS_USE_NULL_AS_ZERO'); - } - }/*}}}*/ - - /** - * Transforms the data by substracting each entry from the mean and - * dividing by its standard deviation. This will reset all pre-calculated - * values to their original (unset) defaults. - * - * @access public - * @return mixed true on success, a PEAR_Error object otherwise - * @see mean() - * @see stDev() - * @see setData() - */ - function studentize() {/*{{{*/ - $mean = $this->mean(); - if (PEAR::isError($mean)) { - return $mean; - } - $std = $this->stDev(); - if (PEAR::isError($std)) { - return $std; - } - if ($std == 0) { - return PEAR::raiseError('cannot studentize data, standard deviation is zero.'); - } - $arr = array(); - if ($this->_dataOption == STATS_DATA_CUMMULATIVE) { - foreach ($this->_data as $val=>$freq) { - $newval = ($val - $mean) / $std; - $arr["$newval"] = $freq; - } - } else { - foreach ($this->_data as $val) { - $newval = ($val - $mean) / $std; - $arr[] = $newval; - } - } - return $this->setData($arr, $this->_dataOption); - }/*}}}*/ - - /** - * Transforms the data by substracting each entry from the mean. - * This will reset all pre-calculated values to their original (unset) defaults. - * - * @access public - * @return mixed true on success, a PEAR_Error object otherwise - * @see mean() - * @see setData() - */ - function center() {/*{{{*/ - $mean = $this->mean(); - if (PEAR::isError($mean)) { - return $mean; - } - $arr = array(); - if ($this->_dataOption == STATS_DATA_CUMMULATIVE) { - foreach ($this->_data as $val=>$freq) { - $newval = $val - $mean; - $arr["$newval"] = $freq; - } - } else { - foreach ($this->_data as $val) { - $newval = $val - $mean; - $arr[] = $newval; - } - } - return $this->setData($arr, $this->_dataOption); - }/*}}}*/ - - /** - * Calculates the basic or full statistics for the data set - * - * @access public - * @param int $mode one of STATS_BASIC or STATS_FULL - * @param boolean $returnErrorObject whether the raw PEAR_Error (when true, default), - * or only the error message will be returned (when false), if an error happens. - * @return mixed an associative array of statistics on success, a PEAR_Error object otherwise - * @see calcBasic() - * @see calcFull() - */ - function calc($mode, $returnErrorObject=true) {/*{{{*/ - if ($this->_data == null) { - return PEAR::raiseError('data has not been set'); - } - if ($mode == STATS_BASIC) { - return $this->calcBasic($returnErrorObject); - } elseif ($mode == STATS_FULL) { - return $this->calcFull($returnErrorObject); - } else { - return PEAR::raiseError('incorrect mode, expected STATS_BASIC or STATS_FULL'); - } - }/*}}}*/ - - /** - * Calculates a basic set of statistics - * - * @access public - * @param boolean $returnErrorObject whether the raw PEAR_Error (when true, default), - * or only the error message will be returned (when false), if an error happens. - * @return mixed an associative array of statistics on success, a PEAR_Error object otherwise - * @see calc() - * @see calcFull() - */ - function calcBasic($returnErrorObject=true) {/*{{{*/ - return array ( - 'min' => $this->__format($this->min(), $returnErrorObject), - 'max' => $this->__format($this->max(), $returnErrorObject), - 'sum' => $this->__format($this->sum(), $returnErrorObject), - 'sum2' => $this->__format($this->sum2(), $returnErrorObject), - 'count' => $this->__format($this->count(), $returnErrorObject), - 'mean' => $this->__format($this->mean(), $returnErrorObject), - 'stdev' => $this->__format($this->stDev(), $returnErrorObject), - 'variance' => $this->__format($this->variance(), $returnErrorObject), - 'range' => $this->__format($this->range(), $returnErrorObject) - ); - }/*}}}*/ - - /** - * Calculates a full set of statistics - * - * @access public - * @param boolean $returnErrorObject whether the raw PEAR_Error (when true, default), - * or only the error message will be returned (when false), if an error happens. - * @return mixed an associative array of statistics on success, a PEAR_Error object otherwise - * @see calc() - * @see calcBasic() - */ - function calcFull($returnErrorObject=true) {/*{{{*/ - return array ( - 'min' => $this->__format($this->min(), $returnErrorObject), - 'max' => $this->__format($this->max(), $returnErrorObject), - 'sum' => $this->__format($this->sum(), $returnErrorObject), - 'sum2' => $this->__format($this->sum2(), $returnErrorObject), - 'count' => $this->__format($this->count(), $returnErrorObject), - 'mean' => $this->__format($this->mean(), $returnErrorObject), - 'median' => $this->__format($this->median(), $returnErrorObject), - 'mode' => $this->__format($this->mode(), $returnErrorObject), - 'midrange' => $this->__format($this->midrange(), $returnErrorObject), - 'geometric_mean' => $this->__format($this->geometricMean(), $returnErrorObject), - 'harmonic_mean' => $this->__format($this->harmonicMean(), $returnErrorObject), - 'stdev' => $this->__format($this->stDev(), $returnErrorObject), - 'absdev' => $this->__format($this->absDev(), $returnErrorObject), - 'variance' => $this->__format($this->variance(), $returnErrorObject), - 'range' => $this->__format($this->range(), $returnErrorObject), - 'std_error_of_mean' => $this->__format($this->stdErrorOfMean(), $returnErrorObject), - 'skewness' => $this->__format($this->skewness(), $returnErrorObject), - 'kurtosis' => $this->__format($this->kurtosis(), $returnErrorObject), - 'coeff_of_variation' => $this->__format($this->coeffOfVariation(), $returnErrorObject), - 'sample_central_moments' => array ( - 1 => $this->__format($this->sampleCentralMoment(1), $returnErrorObject), - 2 => $this->__format($this->sampleCentralMoment(2), $returnErrorObject), - 3 => $this->__format($this->sampleCentralMoment(3), $returnErrorObject), - 4 => $this->__format($this->sampleCentralMoment(4), $returnErrorObject), - 5 => $this->__format($this->sampleCentralMoment(5), $returnErrorObject) - ), - 'sample_raw_moments' => array ( - 1 => $this->__format($this->sampleRawMoment(1), $returnErrorObject), - 2 => $this->__format($this->sampleRawMoment(2), $returnErrorObject), - 3 => $this->__format($this->sampleRawMoment(3), $returnErrorObject), - 4 => $this->__format($this->sampleRawMoment(4), $returnErrorObject), - 5 => $this->__format($this->sampleRawMoment(5), $returnErrorObject) - ), - 'frequency' => $this->__format($this->frequency(), $returnErrorObject), - 'quartiles' => $this->__format($this->quartiles(), $returnErrorObject), - 'interquartile_range' => $this->__format($this->interquartileRange(), $returnErrorObject), - 'interquartile_mean' => $this->__format($this->interquartileMean(), $returnErrorObject), - 'quartile_deviation' => $this->__format($this->quartileDeviation(), $returnErrorObject), - 'quartile_variation_coefficient' => $this->__format($this->quartileVariationCoefficient(), $returnErrorObject), - 'quartile_skewness_coefficient' => $this->__format($this->quartileSkewnessCoefficient(), $returnErrorObject) - ); - }/*}}}*/ - - /** - * Calculates the minimum of a data set. - * Handles cummulative data sets correctly - * - * @access public - * @return mixed the minimum value on success, a PEAR_Error object otherwise - * @see calc() - * @see max() - */ - function min() {/*{{{*/ - if ($this->_data == null) { - return PEAR::raiseError('data has not been set'); - } - if (!array_key_exists('min', $this->_calculatedValues)) { - if ($this->_dataOption == STATS_DATA_CUMMULATIVE) { - $min = min(array_keys($this->_data)); - } else { - $min = min($this->_data); - } - $this->_calculatedValues['min'] = $min; - } - return $this->_calculatedValues['min']; - }/*}}}*/ - - /** - * Calculates the maximum of a data set. - * Handles cummulative data sets correctly - * - * @access public - * @return mixed the maximum value on success, a PEAR_Error object otherwise - * @see calc() - * @see min() - */ - function max() {/*{{{*/ - if ($this->_data == null) { - return PEAR::raiseError('data has not been set'); - } - if (!array_key_exists('max', $this->_calculatedValues)) { - if ($this->_dataOption == STATS_DATA_CUMMULATIVE) { - $max = max(array_keys($this->_data)); - } else { - $max = max($this->_data); - } - $this->_calculatedValues['max'] = $max; - } - return $this->_calculatedValues['max']; - }/*}}}*/ - - /** - * Calculates SUM { xi } - * Handles cummulative data sets correctly - * - * @access public - * @return mixed the sum on success, a PEAR_Error object otherwise - * @see calc() - * @see sum2() - * @see sumN() - */ - function sum() {/*{{{*/ - if (!array_key_exists('sum', $this->_calculatedValues)) { - $sum = $this->sumN(1); - if (PEAR::isError($sum)) { - return $sum; - } else { - $this->_calculatedValues['sum'] = $sum; - } - } - return $this->_calculatedValues['sum']; - }/*}}}*/ - - /** - * Calculates SUM { (xi)^2 } - * Handles cummulative data sets correctly - * - * @access public - * @return mixed the sum on success, a PEAR_Error object otherwise - * @see calc() - * @see sum() - * @see sumN() - */ - function sum2() {/*{{{*/ - if (!array_key_exists('sum2', $this->_calculatedValues)) { - $sum2 = $this->sumN(2); - if (PEAR::isError($sum2)) { - return $sum2; - } else { - $this->_calculatedValues['sum2'] = $sum2; - } - } - return $this->_calculatedValues['sum2']; - }/*}}}*/ - - /** - * Calculates SUM { (xi)^n } - * Handles cummulative data sets correctly - * - * @access public - * @param numeric $n the exponent - * @return mixed the sum on success, a PEAR_Error object otherwise - * @see calc() - * @see sum() - * @see sum2() - */ - function sumN($n) {/*{{{*/ - if ($this->_data == null) { - return PEAR::raiseError('data has not been set'); - } - $sumN = 0; - if ($this->_dataOption == STATS_DATA_CUMMULATIVE) { - foreach($this->_data as $val=>$freq) { - $sumN += $freq * pow((double)$val, (double)$n); - } - } else { - foreach($this->_data as $val) { - $sumN += pow((double)$val, (double)$n); - } - } - return $sumN; - }/*}}}*/ - - /** - * Calculates PROD { (xi) }, (the product of all observations) - * Handles cummulative data sets correctly - * - * @access public - * @return mixed the product on success, a PEAR_Error object otherwise - * @see productN() - */ - function product() {/*{{{*/ - if (!array_key_exists('product', $this->_calculatedValues)) { - $product = $this->productN(1); - if (PEAR::isError($product)) { - return $product; - } else { - $this->_calculatedValues['product'] = $product; - } - } - return $this->_calculatedValues['product']; - }/*}}}*/ - - /** - * Calculates PROD { (xi)^n }, which is the product of all observations - * Handles cummulative data sets correctly - * - * @access public - * @param numeric $n the exponent - * @return mixed the product on success, a PEAR_Error object otherwise - * @see product() - */ - function productN($n) {/*{{{*/ - if ($this->_data == null) { - return PEAR::raiseError('data has not been set'); - } - $prodN = 1.0; - if ($this->_dataOption == STATS_DATA_CUMMULATIVE) { - foreach($this->_data as $val=>$freq) { - if ($val == 0) { - return 0.0; - } - $prodN *= $freq * pow((double)$val, (double)$n); - } - } else { - foreach($this->_data as $val) { - if ($val == 0) { - return 0.0; - } - $prodN *= pow((double)$val, (double)$n); - } - } - return $prodN; - - }/*}}}*/ - - /** - * Calculates the number of data points in the set - * Handles cummulative data sets correctly - * - * @access public - * @return mixed the count on success, a PEAR_Error object otherwise - * @see calc() - */ - function count() {/*{{{*/ - if ($this->_data == null) { - return PEAR::raiseError('data has not been set'); - } - if (!array_key_exists('count', $this->_calculatedValues)) { - if ($this->_dataOption == STATS_DATA_CUMMULATIVE) { - $count = count($this->_dataExpanded); - } else { - $count = count($this->_data); - } - $this->_calculatedValues['count'] = $count; - } - return $this->_calculatedValues['count']; - }/*}}}*/ - - /** - * Calculates the mean (average) of the data points in the set - * Handles cummulative data sets correctly - * - * @access public - * @return mixed the mean value on success, a PEAR_Error object otherwise - * @see calc() - * @see sum() - * @see count() - */ - function mean() {/*{{{*/ - if (!array_key_exists('mean', $this->_calculatedValues)) { - $sum = $this->sum(); - if (PEAR::isError($sum)) { - return $sum; - } - $count = $this->count(); - if (PEAR::isError($count)) { - return $count; - } - $this->_calculatedValues['mean'] = $sum / $count; - } - return $this->_calculatedValues['mean']; - }/*}}}*/ - - /** - * Calculates the range of the data set = max - min - * - * @access public - * @return mixed the value of the range on success, a PEAR_Error object otherwise. - */ - function range() {/*{{{*/ - if (!array_key_exists('range', $this->_calculatedValues)) { - $min = $this->min(); - if (PEAR::isError($min)) { - return $min; - } - $max = $this->max(); - if (PEAR::isError($max)) { - return $max; - } - $this->_calculatedValues['range'] = $max - $min; - } - return $this->_calculatedValues['range']; - - }/*}}}*/ - - /** - * Calculates the variance (unbiased) of the data points in the set - * Handles cummulative data sets correctly - * - * @access public - * @return mixed the variance value on success, a PEAR_Error object otherwise - * @see calc() - * @see __sumdiff() - * @see count() - */ - function variance() {/*{{{*/ - if (!array_key_exists('variance', $this->_calculatedValues)) { - $variance = $this->__calcVariance(); - if (PEAR::isError($variance)) { - return $variance; - } - $this->_calculatedValues['variance'] = $variance; - } - return $this->_calculatedValues['variance']; - }/*}}}*/ - - /** - * Calculates the standard deviation (unbiased) of the data points in the set - * Handles cummulative data sets correctly - * - * @access public - * @return mixed the standard deviation on success, a PEAR_Error object otherwise - * @see calc() - * @see variance() - */ - function stDev() {/*{{{*/ - if (!array_key_exists('stDev', $this->_calculatedValues)) { - $variance = $this->variance(); - if (PEAR::isError($variance)) { - return $variance; - } - $this->_calculatedValues['stDev'] = sqrt($variance); - } - return $this->_calculatedValues['stDev']; - }/*}}}*/ - - /** - * Calculates the variance (unbiased) of the data points in the set - * given a fixed mean (average) value. Not used in calcBasic(), calcFull() - * or calc(). - * Handles cummulative data sets correctly - * - * @access public - * @param numeric $mean the fixed mean value - * @return mixed the variance on success, a PEAR_Error object otherwise - * @see __sumdiff() - * @see count() - * @see variance() - */ - function varianceWithMean($mean) {/*{{{*/ - return $this->__calcVariance($mean); - }/*}}}*/ - - /** - * Calculates the standard deviation (unbiased) of the data points in the set - * given a fixed mean (average) value. Not used in calcBasic(), calcFull() - * or calc(). - * Handles cummulative data sets correctly - * - * @access public - * @param numeric $mean the fixed mean value - * @return mixed the standard deviation on success, a PEAR_Error object otherwise - * @see varianceWithMean() - * @see stDev() - */ - function stDevWithMean($mean) {/*{{{*/ - $varianceWM = $this->varianceWithMean($mean); - if (PEAR::isError($varianceWM)) { - return $varianceWM; - } - return sqrt($varianceWM); - }/*}}}*/ - - /** - * Calculates the absolute deviation of the data points in the set - * Handles cummulative data sets correctly - * - * @access public - * @return mixed the absolute deviation on success, a PEAR_Error object otherwise - * @see calc() - * @see __sumabsdev() - * @see count() - * @see absDevWithMean() - */ - function absDev() {/*{{{*/ - if (!array_key_exists('absDev', $this->_calculatedValues)) { - $absDev = $this->__calcAbsoluteDeviation(); - if (PEAR::isError($absdev)) { - return $absdev; - } - $this->_calculatedValues['absDev'] = $absDev; - } - return $this->_calculatedValues['absDev']; - }/*}}}*/ - - /** - * Calculates the absolute deviation of the data points in the set - * given a fixed mean (average) value. Not used in calcBasic(), calcFull() - * or calc(). - * Handles cummulative data sets correctly - * - * @access public - * @param numeric $mean the fixed mean value - * @return mixed the absolute deviation on success, a PEAR_Error object otherwise - * @see __sumabsdev() - * @see absDev() - */ - function absDevWithMean($mean) {/*{{{*/ - return $this->__calcAbsoluteDeviation($mean); - }/*}}}*/ - - /** - * Calculates the skewness of the data distribution in the set - * The skewness measures the degree of asymmetry of a distribution, - * and is related to the third central moment of a distribution. - * A normal distribution has a skewness = 0 - * A distribution with a tail off towards the high end of the scale - * (positive skew) has a skewness > 0 - * A distribution with a tail off towards the low end of the scale - * (negative skew) has a skewness < 0 - * Handles cummulative data sets correctly - * - * @access public - * @return mixed the skewness value on success, a PEAR_Error object otherwise - * @see __sumdiff() - * @see count() - * @see stDev() - * @see calc() - */ - function skewness() {/*{{{*/ - if (!array_key_exists('skewness', $this->_calculatedValues)) { - $count = $this->count(); - if (PEAR::isError($count)) { - return $count; - } - $stDev = $this->stDev(); - if (PEAR::isError($stDev)) { - return $stDev; - } - $sumdiff3 = $this->__sumdiff(3); - if (PEAR::isError($sumdiff3)) { - return $sumdiff3; - } - $this->_calculatedValues['skewness'] = ($sumdiff3 / ($count * pow($stDev, 3))); - } - return $this->_calculatedValues['skewness']; - }/*}}}*/ - - /** - * Calculates the kurtosis of the data distribution in the set - * The kurtosis measures the degrees of peakedness of a distribution. - * It is also called the "excess" or "excess coefficient", and is - * a normalized form of the fourth central moment of a distribution. - * A normal distributions has kurtosis = 0 - * A narrow and peaked (leptokurtic) distribution has a - * kurtosis > 0 - * A flat and wide (platykurtic) distribution has a kurtosis < 0 - * Handles cummulative data sets correctly - * - * @access public - * @return mixed the kurtosis value on success, a PEAR_Error object otherwise - * @see __sumdiff() - * @see count() - * @see stDev() - * @see calc() - */ - function kurtosis() {/*{{{*/ - if (!array_key_exists('kurtosis', $this->_calculatedValues)) { - $count = $this->count(); - if (PEAR::isError($count)) { - return $count; - } - $stDev = $this->stDev(); - if (PEAR::isError($stDev)) { - return $stDev; - } - $sumdiff4 = $this->__sumdiff(4); - if (PEAR::isError($sumdiff4)) { - return $sumdiff4; - } - $this->_calculatedValues['kurtosis'] = ($sumdiff4 / ($count * pow($stDev, 4))) - 3; - } - return $this->_calculatedValues['kurtosis']; - }/*}}}*/ - - /** - * Calculates the median of a data set. - * The median is the value such that half of the points are below it - * in a sorted data set. - * If the number of values is odd, it is the middle item. - * If the number of values is even, is the average of the two middle items. - * Handles cummulative data sets correctly - * - * @access public - * @return mixed the median value on success, a PEAR_Error object otherwise - * @see count() - * @see calc() - */ - function median() {/*{{{*/ - if ($this->_data == null) { - return PEAR::raiseError('data has not been set'); - } - if (!array_key_exists('median', $this->_calculatedValues)) { - if ($this->_dataOption == STATS_DATA_CUMMULATIVE) { - $arr =& $this->_dataExpanded; - } else { - $arr =& $this->_data; - } - $n = $this->count(); - if (PEAR::isError($n)) { - return $n; - } - $h = intval($n / 2); - if ($n % 2 == 0) { - $median = ($arr[$h] + $arr[$h - 1]) / 2; - } else { - $median = $arr[$h + 1]; - } - $this->_calculatedValues['median'] = $median; - } - return $this->_calculatedValues['median']; - }/*}}}*/ - - /** - * Calculates the mode of a data set. - * The mode is the value with the highest frequency in the data set. - * There can be more than one mode. - * Handles cummulative data sets correctly - * - * @access public - * @return mixed an array of mode value on success, a PEAR_Error object otherwise - * @see frequency() - * @see calc() - */ - function mode() {/*{{{*/ - if ($this->_data == null) { - return PEAR::raiseError('data has not been set'); - } - if (!array_key_exists('mode', $this->_calculatedValues)) { - if ($this->_dataOption == STATS_DATA_CUMMULATIVE) { - $arr = $this->_data; - } else { - $arr = $this->frequency(); - } - arsort($arr); - $mcount = 1; - foreach ($arr as $val=>$freq) { - if ($mcount == 1) { - $mode = array($val); - $mfreq = $freq; - ++$mcount; - continue; - } - if ($mfreq == $freq) - $mode[] = $val; - if ($mfreq > $freq) - break; - } - $this->_calculatedValues['mode'] = $mode; - } - return $this->_calculatedValues['mode']; - }/*}}}*/ - - /** - * Calculates the midrange of a data set. - * The midrange is the average of the minimum and maximum of the data set. - * Handles cummulative data sets correctly - * - * @access public - * @return mixed the midrange value on success, a PEAR_Error object otherwise - * @see min() - * @see max() - * @see calc() - */ - function midrange() {/*{{{*/ - if (!array_key_exists('midrange', $this->_calculatedValues)) { - $min = $this->min(); - if (PEAR::isError($min)) { - return $min; - } - $max = $this->max(); - if (PEAR::isError($max)) { - return $max; - } - $this->_calculatedValues['midrange'] = (($max + $min) / 2); - } - return $this->_calculatedValues['midrange']; - }/*}}}*/ - - /** - * Calculates the geometrical mean of the data points in the set - * Handles cummulative data sets correctly - * - * @access public - * @return mixed the geometrical mean value on success, a PEAR_Error object otherwise - * @see calc() - * @see product() - * @see count() - */ - function geometricMean() {/*{{{*/ - if (!array_key_exists('geometricMean', $this->_calculatedValues)) { - $count = $this->count(); - if (PEAR::isError($count)) { - return $count; - } - $prod = $this->product(); - if (PEAR::isError($prod)) { - return $prod; - } - if ($prod == 0.0) { - return 0.0; - } - if ($prod < 0) { - return PEAR::raiseError('The product of the data set is negative, geometric mean undefined.'); - } - $this->_calculatedValues['geometricMean'] = pow($prod , 1 / $count); - } - return $this->_calculatedValues['geometricMean']; - }/*}}}*/ - - /** - * Calculates the harmonic mean of the data points in the set - * Handles cummulative data sets correctly - * - * @access public - * @return mixed the harmonic mean value on success, a PEAR_Error object otherwise - * @see calc() - * @see count() - */ - function harmonicMean() {/*{{{*/ - if ($this->_data == null) { - return PEAR::raiseError('data has not been set'); - } - if (!array_key_exists('harmonicMean', $this->_calculatedValues)) { - $count = $this->count(); - if (PEAR::isError($count)) { - return $count; - } - $invsum = 0.0; - if ($this->_dataOption == STATS_DATA_CUMMULATIVE) { - foreach($this->_data as $val=>$freq) { - if ($val == 0) { - return PEAR::raiseError('cannot calculate a '. - 'harmonic mean with data values of zero.'); - } - $invsum += $freq / $val; - } - } else { - foreach($this->_data as $val) { - if ($val == 0) { - return PEAR::raiseError('cannot calculate a '. - 'harmonic mean with data values of zero.'); - } - $invsum += 1 / $val; - } - } - $this->_calculatedValues['harmonicMean'] = $count / $invsum; - } - return $this->_calculatedValues['harmonicMean']; - }/*}}}*/ - - /** - * Calculates the nth central moment (m{n}) of a data set. - * - * The definition of a sample central moment is: - * - * m{n} = 1/N * SUM { (xi - avg)^n } - * - * where: N = sample size, avg = sample mean. - * - * @access public - * @param integer $n moment to calculate - * @return mixed the numeric value of the moment on success, PEAR_Error otherwise - */ - function sampleCentralMoment($n) {/*{{{*/ - if (!is_int($n) || $n < 1) { - return PEAR::isError('moment must be a positive integer >= 1.'); - } - - if ($n == 1) { - return 0; - } - $count = $this->count(); - if (PEAR::isError($count)) { - return $count; - } - if ($count == 0) { - return PEAR::raiseError("Cannot calculate {$n}th sample moment, ". - 'there are zero data entries'); - } - $sum = $this->__sumdiff($n); - if (PEAR::isError($sum)) { - return $sum; - } - return ($sum / $count); - }/*}}}*/ - - /** - * Calculates the nth raw moment (m{n}) of a data set. - * - * The definition of a sample central moment is: - * - * m{n} = 1/N * SUM { xi^n } - * - * where: N = sample size, avg = sample mean. - * - * @access public - * @param integer $n moment to calculate - * @return mixed the numeric value of the moment on success, PEAR_Error otherwise - */ - function sampleRawMoment($n) {/*{{{*/ - if (!is_int($n) || $n < 1) { - return PEAR::isError('moment must be a positive integer >= 1.'); - } - - $count = $this->count(); - if (PEAR::isError($count)) { - return $count; - } - if ($count == 0) { - return PEAR::raiseError("Cannot calculate {$n}th raw moment, ". - 'there are zero data entries.'); - } - $sum = $this->sumN($n); - if (PEAR::isError($sum)) { - return $sum; - } - return ($sum / $count); - }/*}}}*/ - - - /** - * Calculates the coefficient of variation of a data set. - * The coefficient of variation measures the spread of a set of data - * as a proportion of its mean. It is often expressed as a percentage. - * Handles cummulative data sets correctly - * - * @access public - * @return mixed the coefficient of variation on success, a PEAR_Error object otherwise - * @see stDev() - * @see mean() - * @see calc() - */ - function coeffOfVariation() {/*{{{*/ - if (!array_key_exists('coeffOfVariation', $this->_calculatedValues)) { - $mean = $this->mean(); - if (PEAR::isError($mean)) { - return $mean; - } - if ($mean == 0.0) { - return PEAR::raiseError('cannot calculate the coefficient '. - 'of variation, mean of sample is zero'); - } - $stDev = $this->stDev(); - if (PEAR::isError($stDev)) { - return $stDev; - } - - $this->_calculatedValues['coeffOfVariation'] = $stDev / $mean; - } - return $this->_calculatedValues['coeffOfVariation']; - }/*}}}*/ - - /** - * Calculates the standard error of the mean. - * It is the standard deviation of the sampling distribution of - * the mean. The formula is: - * - * S.E. Mean = SD / (N)^(1/2) - * - * This formula does not assume a normal distribution, and shows - * that the size of the standard error of the mean is inversely - * proportional to the square root of the sample size. - * - * @access public - * @return mixed the standard error of the mean on success, a PEAR_Error object otherwise - * @see stDev() - * @see count() - * @see calc() - */ - function stdErrorOfMean() {/*{{{*/ - if (!array_key_exists('stdErrorOfMean', $this->_calculatedValues)) { - $count = $this->count(); - if (PEAR::isError($count)) { - return $count; - } - $stDev = $this->stDev(); - if (PEAR::isError($stDev)) { - return $stDev; - } - $this->_calculatedValues['stdErrorOfMean'] = $stDev / sqrt($count); - } - return $this->_calculatedValues['stdErrorOfMean']; - }/*}}}*/ - - /** - * Calculates the value frequency table of a data set. - * Handles cummulative data sets correctly - * - * @access public - * @return mixed an associative array of value=>frequency items on success, a PEAR_Error object otherwise - * @see min() - * @see max() - * @see calc() - */ - function frequency() {/*{{{*/ - if ($this->_data == null) { - return PEAR::raiseError('data has not been set'); - } - if (!array_key_exists('frequency', $this->_calculatedValues)) { - if ($this->_dataOption == STATS_DATA_CUMMULATIVE) { - $freq = $this->_data; - } else { - $freq = array(); - foreach ($this->_data as $val) { - $freq["$val"]++; - } - ksort($freq); - } - $this->_calculatedValues['frequency'] = $freq; - } - return $this->_calculatedValues['frequency']; - }/*}}}*/ - - /** - * The quartiles are defined as the values that divide a sorted - * data set into four equal-sized subsets, and correspond to the - * 25th, 50th, and 75th percentiles. - * - * @access public - * @return mixed an associative array of quartiles on success, a PEAR_Error otherwise - * @see percentile() - */ - function quartiles() {/*{{{*/ - if (!array_key_exists('quartiles', $this->_calculatedValues)) { - $q1 = $this->percentile(25); - if (PEAR::isError($q1)) { - return $q1; - } - $q2 = $this->percentile(50); - if (PEAR::isError($q2)) { - return $q2; - } - $q3 = $this->percentile(75); - if (PEAR::isError($q3)) { - return $q3; - } - $this->_calculatedValues['quartiles'] = array ( - '25' => $q1, - '50' => $q2, - '75' => $q3 - ); - } - return $this->_calculatedValues['quartiles']; - }/*}}}*/ - - /** - * The interquartile mean is defined as the mean of the values left - * after discarding the lower 25% and top 25% ranked values, i.e.: - * - * interquart mean = mean() - * - * where: P = percentile - * - * @todo need to double check the equation - * @access public - * @return mixed a numeric value on success, a PEAR_Error otherwise - * @see quartiles() - */ - function interquartileMean() {/*{{{*/ - if (!array_key_exists('interquartileMean', $this->_calculatedValues)) { - $quart = $this->quartiles(); - if (PEAR::isError($quart)) { - return $quart; - } - $q3 = $quart['75']; - $q1 = $quart['25']; - $sum = 0; - $n = 0; - foreach ($this->getData(true) as $val) { - if ($val >= $q1 && $val <= $q3) { - $sum += $val; - ++$n; - } - } - if ($n == 0) { - return PEAR::raiseError('error calculating interquartile mean, '. - 'empty interquartile range of values.'); - } - $this->_calculatedValues['interquartileMean'] = $sum / $n; - } - return $this->_calculatedValues['interquartileMean']; - }/*}}}*/ - - /** - * The interquartile range is the distance between the 75th and 25th - * percentiles. Basically the range of the middle 50% of the data set, - * and thus is not affected by outliers or extreme values. - * - * interquart range = P(75) - P(25) - * - * where: P = percentile - * - * @access public - * @return mixed a numeric value on success, a PEAR_Error otherwise - * @see quartiles() - */ - function interquartileRange() {/*{{{*/ - if (!array_key_exists('interquartileRange', $this->_calculatedValues)) { - $quart = $this->quartiles(); - if (PEAR::isError($quart)) { - return $quart; - } - $q3 = $quart['75']; - $q1 = $quart['25']; - $this->_calculatedValues['interquartileRange'] = $q3 - $q1; - } - return $this->_calculatedValues['interquartileRange']; - }/*}}}*/ - - /** - * The quartile deviation is half of the interquartile range value - * - * quart dev = (P(75) - P(25)) / 2 - * - * where: P = percentile - * - * @access public - * @return mixed a numeric value on success, a PEAR_Error otherwise - * @see quartiles() - * @see interquartileRange() - */ - function quartileDeviation() {/*{{{*/ - if (!array_key_exists('quartileDeviation', $this->_calculatedValues)) { - $iqr = $this->interquartileRange(); - if (PEAR::isError($iqr)) { - return $iqr; - } - $this->_calculatedValues['quartileDeviation'] = $iqr / 2; - } - return $this->_calculatedValues['quartileDeviation']; - }/*}}}*/ - - /** - * The quartile variation coefficient is defines as follows: - * - * quart var coeff = 100 * (P(75) - P(25)) / (P(75) + P(25)) - * - * where: P = percentile - * - * @todo need to double check the equation - * @access public - * @return mixed a numeric value on success, a PEAR_Error otherwise - * @see quartiles() - */ - function quartileVariationCoefficient() {/*{{{*/ - if (!array_key_exists('quartileVariationCoefficient', $this->_calculatedValues)) { - $quart = $this->quartiles(); - if (PEAR::isError($quart)) { - return $quart; - } - $q3 = $quart['75']; - $q1 = $quart['25']; - $d = $q3 - $q1; - $s = $q3 + $q1; - $this->_calculatedValues['quartileVariationCoefficient'] = 100 * $d / $s; - } - return $this->_calculatedValues['quartileVariationCoefficient']; - }/*}}}*/ - - /** - * The quartile skewness coefficient (also known as Bowley Skewness), - * is defined as follows: - * - * quart skewness coeff = (P(25) - 2*P(50) + P(75)) / (P(75) - P(25)) - * - * where: P = percentile - * - * @todo need to double check the equation - * @access public - * @return mixed a numeric value on success, a PEAR_Error otherwise - * @see quartiles() - */ - function quartileSkewnessCoefficient() {/*{{{*/ - if (!array_key_exists('quartileSkewnessCoefficient', $this->_calculatedValues)) { - $quart = $this->quartiles(); - if (PEAR::isError($quart)) { - return $quart; - } - $q3 = $quart['75']; - $q2 = $quart['50']; - $q1 = $quart['25']; - $d = $q3 - 2*$q2 + $q1; - $s = $q3 - $q1; - $this->_calculatedValues['quartileSkewnessCoefficient'] = $d / $s; - } - return $this->_calculatedValues['quartileSkewnessCoefficient']; - }/*}}}*/ - - /** - * The pth percentile is the value such that p% of the a sorted data set - * is smaller than it, and (100 - p)% of the data is larger. - * - * A quick algorithm to pick the appropriate value from a sorted data - * set is as follows: - * - * - Count the number of values: n - * - Calculate the position of the value in the data list: i = p * (n + 1) - * - if i is an integer, return the data at that position - * - if i < 1, return the minimum of the data set - * - if i > n, return the maximum of the data set - * - otherwise, average the entries at adjacent positions to i - * - * The median is the 50th percentile value. - * - * @todo need to double check generality of the algorithm - * - * @access public - * @param numeric $p the percentile to estimate, e.g. 25 for 25th percentile - * @return mixed a numeric value on success, a PEAR_Error otherwise - * @see quartiles() - * @see median() - */ - function percentile($p) {/*{{{*/ - $count = $this->count(); - if (PEAR::isError($count)) { - return $count; - } - if ($this->_dataOption == STATS_DATA_CUMMULATIVE) { - $data =& $this->_dataExpanded; - } else { - $data =& $this->_data; - } - $obsidx = $p * ($count + 1) / 100; - if (intval($obsidx) == $obsidx) { - return $data[($obsidx - 1)]; - } elseif ($obsidx < 1) { - return $data[0]; - } elseif ($obsidx > $count) { - return $data[($count - 1)]; - } else { - $left = floor($obsidx - 1); - $right = ceil($obsidx - 1); - return ($data[$left] + $data[$right]) / 2; - } - }/*}}}*/ - - // private methods - - /** - * Utility function to calculate: SUM { (xi - mean)^n } - * - * @access private - * @param numeric $power the exponent - * @param optional double $mean the data set mean value - * @return mixed the sum on success, a PEAR_Error object otherwise - * - * @see stDev() - * @see variaceWithMean(); - * @see skewness(); - * @see kurtosis(); - */ - function __sumdiff($power, $mean=null) {/*{{{*/ - if ($this->_data == null) { - return PEAR::raiseError('data has not been set'); - } - if (is_null($mean)) { - $mean = $this->mean(); - if (PEAR::isError($mean)) { - return $mean; - } - } - $sdiff = 0; - if ($this->_dataOption == STATS_DATA_CUMMULATIVE) { - foreach ($this->_data as $val=>$freq) { - $sdiff += $freq * pow((double)($val - $mean), (double)$power); - } - } else { - foreach ($this->_data as $val) - $sdiff += pow((double)($val - $mean), (double)$power); - } - return $sdiff; - }/*}}}*/ - - /** - * Utility function to calculate the variance with or without - * a fixed mean - * - * @access private - * @param $mean the fixed mean to use, null as default - * @return mixed a numeric value on success, a PEAR_Error otherwise - * @see variance() - * @see varianceWithMean() - */ - function __calcVariance($mean = null) {/*{{{*/ - if ($this->_data == null) { - return PEAR::raiseError('data has not been set'); - } - $sumdiff2 = $this->__sumdiff(2, $mean); - if (PEAR::isError($sumdiff2)) { - return $sumdiff2; - } - $count = $this->count(); - if (PEAR::isError($count)) { - return $count; - } - if ($count == 1) { - return PEAR::raiseError('cannot calculate variance of a singe data point'); - } - return ($sumdiff2 / ($count - 1)); - }/*}}}*/ - - /** - * Utility function to calculate the absolute deviation with or without - * a fixed mean - * - * @access private - * @param $mean the fixed mean to use, null as default - * @return mixed a numeric value on success, a PEAR_Error otherwise - * @see absDev() - * @see absDevWithMean() - */ - function __calcAbsoluteDeviation($mean = null) {/*{{{*/ - if ($this->_data == null) { - return PEAR::raiseError('data has not been set'); - } - $count = $this->count(); - if (PEAR::isError($count)) { - return $count; - } - $sumabsdev = $this->__sumabsdev($mean); - if (PEAR::isError($sumabsdev)) { - return $sumabsdev; - } - return $sumabsdev / $count; - }/*}}}*/ - - /** - * Utility function to calculate: SUM { | xi - mean | } - * - * @access private - * @param optional double $mean the mean value for the set or population - * @return mixed the sum on success, a PEAR_Error object otherwise - * - * @see absDev() - * @see absDevWithMean() - */ - function __sumabsdev($mean=null) {/*{{{*/ - if ($this->_data == null) { - return PEAR::raiseError('data has not been set'); - } - if (is_null($mean)) { - $mean = $this->mean(); - } - $sdev = 0; - if ($this->_dataOption == STATS_DATA_CUMMULATIVE) { - foreach ($this->_data as $val=>$freq) { - $sdev += $freq * abs($val - $mean); - } - } else { - foreach ($this->_data as $val) { - $sdev += abs($val - $mean); - } - } - return $sdev; - }/*}}}*/ - - /** - * Utility function to format a PEAR_Error to be used by calc(), - * calcBasic() and calcFull() - * - * @access private - * @param mixed $v value to be formatted - * @param boolean $returnErrorObject whether the raw PEAR_Error (when true, default), - * or only the error message will be returned (when false) - * @return mixed if the value is a PEAR_Error object, and $useErrorObject - * is false, then a string with the error message will be returned, - * otherwise the value will not be modified and returned as passed. - */ - function __format($v, $useErrorObject=true) {/*{{{*/ - if (PEAR::isError($v) && $useErrorObject == false) { - return $v->getMessage(); - } else { - return $v; - } - }/*}}}*/ - - /** - * Utility function to validate the data and modify it - * according to the current null handling option - * - * @access private - * @return mixed true on success, a PEAR_Error object otherwise - * - * @see setData() - */ - function _validate() {/*{{{*/ - $flag = ($this->_dataOption == STATS_DATA_CUMMULATIVE); - foreach ($this->_data as $key=>$value) { - $d = ($flag) ? $key : $value; - $v = ($flag) ? $value : $key; - if (!is_numeric($d)) { - switch ($this->_nullOption) { - case STATS_IGNORE_NULL : - unset($this->_data["$key"]); - break; - case STATS_USE_NULL_AS_ZERO: - if ($flag) { - unset($this->_data["$key"]); - $this->_data[0] += $v; - } else { - $this->_data[$key] = 0; - } - break; - case STATS_REJECT_NULL : - default: - return PEAR::raiseError('data rejected, contains NULL values'); - break; - } - } - } - if ($flag) { - ksort($this->_data); - $this->_dataExpanded = array(); - foreach ($this->_data as $val=>$freq) { - $this->_dataExpanded = array_pad($this->_dataExpanded, count($this->_dataExpanded) + $freq, $val); - } - sort($this->_dataExpanded); - } else { - sort($this->_data); - } - return true; - }/*}}}*/ - -}/*}}}*/ - -// vim: ts=4:sw=4:et: -// vim6: fdl=1: fdm=marker: - -?> diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/benchmark.php b/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/benchmark.php deleted file mode 100644 index 1b963b46be2..00000000000 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/benchmark.php +++ /dev/null @@ -1,263 +0,0 @@ -stat->setData($times); - $stats = $this->stat->calcFull(); - - echo '
'; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo '
n:' . $stats['count'] . '
Mean:' . $stats['mean'] . '
Min.:' . $stats['min'] . '
Max.:' . $stats['max'] . '
σ:' . $stats['stdev'] . '
Variance:' . $stats['variance'] . '
Range:' . $stats['range'] . '
'; - - return $stats; - } // function displayStats() - - - function runEig($n = 4, $t = 100) { - $times = array(); - - for ($i = 0; $i < $t; ++$i) { - $M = Matrix::random($n, $n); - $start_time = $this->microtime_float(); - $E = new EigenvalueDecomposition($M); - $stop_time = $this->microtime_float(); - $times[] = $stop_time - $start_time; - } - - return $times; - } // function runEig() - - - function runLU($n = 4, $t = 100) { - $times = array(); - - for ($i = 0; $i < $t; ++$i) { - $M = Matrix::random($n, $n); - $start_time = $this->microtime_float(); - $E = new LUDecomposition($M); - $stop_time = $this->microtime_float(); - $times[] = $stop_time - $start_time; - } - - return $times; - } // function runLU() - - - function runQR($n = 4, $t = 100) { - $times = array(); - - for ($i = 0; $i < $t; ++$i) { - $M = Matrix::random($n, $n); - $start_time = $this->microtime_float(); - $E = new QRDecomposition($M); - $stop_time = $this->microtime_float(); - $times[] = $stop_time - $start_time; - } - - return $times; - } // function runQR() - - - function runCholesky($n = 4, $t = 100) { - $times = array(); - - for ($i = 0; $i < $t; ++$i) { - $M = Matrix::random($n, $n); - $start_time = $this->microtime_float(); - $E = new CholeskyDecomposition($M); - $stop_time = $this->microtime_float(); - $times[] = $stop_time - $start_time; - } - - return $times; - } // function runCholesky() - - - function runSVD($n = 4, $t = 100) { - $times = array(); - - for ($i = 0; $i < $t; ++$i) { - $M = Matrix::random($n, $n); - $start_time = $this->microtime_float(); - $E = new SingularValueDecomposition($M); - $stop_time = $this->microtime_float(); - $times[] = $stop_time - $start_time; - } - - return $times; - } // function runSVD() - - - function run() { - $n = 8; - $t = 16; - $sum = 0; - echo "Cholesky decomposition: $t random {$n}x{$n} matrices
"; - $r = $this->displayStats($this->runCholesky($n, $t)); - $sum += $r['mean'] * $n; - - echo '
'; - - echo "Eigenvalue decomposition: $t random {$n}x{$n} matrices
"; - $r = $this->displayStats($this->runEig($n, $t)); - $sum += $r['mean'] * $n; - - echo '
'; - - echo "LU decomposition: $t random {$n}x{$n} matrices
"; - $r = $this->displayStats($this->runLU($n, $t)); - $sum += $r['mean'] * $n; - - echo '
'; - - echo "QR decomposition: $t random {$n}x{$n} matrices
"; - $r = $this->displayStats($this->runQR($n, $t)); - $sum += $r['mean'] * $n; - - echo '
'; - - echo "Singular Value decomposition: $t random {$n}x{$n} matrices
"; - $r = $this->displayStats($this->runSVD($n, $t)); - $sum += $r['mean'] * $n; - - return $sum; - } // function run() - - - public function __construct() { - $this->stat = new Base(); - } // function Benchmark() - -} // class Benchmark (end MagicSquareExample) - - -$benchmark = new Benchmark(); - -switch($_REQUEST['decomposition']) { - case 'cholesky': - $m = array(); - for ($i = 2; $i <= 8; $i *= 2) { - $t = 32 / $i; - echo "Cholesky decomposition: $t random {$i}x{$i} matrices
"; - $s = $benchmark->displayStats($benchmark->runCholesky($i, $t)); - $m[$i] = $s['mean']; - echo "
"; - } - echo '
';
-		foreach($m as $x => $y) {
-			echo "$x\t" . 1000*$y . "\n";
-		}
-		echo '
'; - break; - case 'eigenvalue': - $m = array(); - for ($i = 2; $i <= 8; $i *= 2) { - $t = 32 / $i; - echo "Eigenvalue decomposition: $t random {$i}x{$i} matrices
"; - $s = $benchmark->displayStats($benchmark->runEig($i, $t)); - $m[$i] = $s['mean']; - echo "
"; - } - echo '
';
-		foreach($m as $x => $y) {
-			echo "$x\t" . 1000*$y . "\n";
-		}
-		echo '
'; - break; - case 'lu': - $m = array(); - for ($i = 2; $i <= 8; $i *= 2) { - $t = 32 / $i; - echo "LU decomposition: $t random {$i}x{$i} matrices
"; - $s = $benchmark->displayStats($benchmark->runLU($i, $t)); - $m[$i] = $s['mean']; - echo "
"; - } - echo '
';
-		foreach($m as $x => $y) {
-			echo "$x\t" . 1000*$y . "\n";
-		}
-		echo '
'; - break; - case 'qr': - $m = array(); - for ($i = 2; $i <= 8; $i *= 2) { - $t = 32 / $i; - echo "QR decomposition: $t random {$i}x{$i} matrices
"; - $s = $benchmark->displayStats($benchmark->runQR($i, $t)); - $m[$i] = $s['mean']; - echo "
"; - } - echo '
';
-		foreach($m as $x => $y) {
-			echo "$x\t" . 1000*$y . "\n";
-		}
-		echo '
'; - break; - case 'svd': - $m = array(); - for($i = 2; $i <= 8; $i *= 2) { - $t = 32 / $i; - echo "Singular value decomposition: $t random {$i}x{$i} matrices
"; - $s = $benchmark->displayStats($benchmark->runSVD($i, $t)); - $m[$i] = $s['mean']; - echo "
"; - } - echo '
';
-		foreach($m as $x => $y) {
-			echo "$x\t" . 1000*$y . "\n";
-		}
-		echo '
'; - break; - case 'all': - $s = $benchmark->run(); - print("
Total: {$s}s
"); - break; - default: - ?> - - $n+1 -*/ -function polyfit($X, $Y, $n) { - for ($i = 0; $i < sizeof($X); ++$i) - for ($j = 0; $j <= $n; ++$j) - $A[$i][$j] = pow($X[$i], $j); - for ($i=0; $i < sizeof($Y); ++$i) - $B[$i] = array($Y[$i]); - $matrixA = new Matrix($A); - $matrixB = new Matrix($B); - $C = $matrixA->solve($matrixB); - return $C->getMatrix(0, $n, 0, 1); -} - -function printpoly( $C = null ) { - for($i = $C->m - 1; $i >= 0; --$i) { - $r = $C->get($i, 0); - if ( abs($r) <= pow(10, -9) ) - $r = 0; - if ($i == $C->m - 1) - echo $r . "x$i"; - else if ($i < $C->m - 1) - echo " + " . $r . "x$i"; - else if ($i == 0) - echo " + " . $r; - } -} - -$X = array(0,1,2,3,4,5); -$Y = array(4,3,12,67,228, 579); -$points = new Matrix(array($X, $Y)); -$points->toHTML(); -printpoly(polyfit($X, $Y, 4)); - -echo '
'; - -$X = array(0,1,2,3,4,5); -$Y = array(1,2,5,10,17, 26); -$points = new Matrix(array($X, $Y)); -$points->toHTML(); -printpoly(polyfit($X, $Y, 2)); - -echo '
'; - -$X = array(0,1,2,3,4,5,6); -$Y = array(-90,-104,-178,-252,-26, 1160, 4446); -$points = new Matrix(array($X, $Y)); -$points->toHTML(); -printpoly(polyfit($X, $Y, 5)); - -echo '
'; - -$X = array(0,1,2,3,4); -$Y = array(mt_rand(0, 10), mt_rand(40, 80), mt_rand(240, 400), mt_rand(1800, 2215), mt_rand(8000, 9000)); -$points = new Matrix(array($X, $Y)); -$points->toHTML(); -printpoly(polyfit($X, $Y, 3)); -?> diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/tile.php b/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/tile.php deleted file mode 100644 index 7a47ea57b2a..00000000000 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/examples/tile.php +++ /dev/null @@ -1,78 +0,0 @@ -getArray(); - print_r($xArray); - - $countRow = 0; - $countColumn = 0; - - $m = $X->getRowDimension(); - $n = $X->getColumnDimension(); - - if( $rowWise<1 || $colWise<1 ){ - die("tile : Array index is out-of-bound."); - } - - $newRowDim = $m*$rowWise; - $newColDim = $n*$colWise; - - $result = array(); - - for($i=0 ; $i<$newRowDim; ++$i) { - - $holder = array(); - - for($j=0 ; $j<$newColDim ; ++$j) { - - $holder[$j] = $xArray[$countRow][$countColumn++]; - - // reset the column-index to zero to avoid reference to out-of-bound index in xArray[][] - - if($countColumn == $n) { $countColumn = 0; } - - } // end for - - ++$countRow; - - // reset the row-index to zero to avoid reference to out-of-bound index in xArray[][] - - if($countRow == $m) { $countRow = 0; } - - $result[$i] = $holder; - - } // end for - - return new Matrix($result); - -} - - -$X =array(1,2,3,4,5,6,7,8,9); -$nRow = 3; -$nCol = 3; -$tiled_matrix = tile(new Matrix($X), $nRow, $nCol); -echo "
";
-print_r($tiled_matrix);
-echo "
"; -?> diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/tests/TestMatrix.php b/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/tests/TestMatrix.php deleted file mode 100644 index 5290ceb5af2..00000000000 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/tests/TestMatrix.php +++ /dev/null @@ -1,415 +0,0 @@ -Testing constructors and constructor-like methods...

"; - - $A = new Matrix($columnwise, 3); - if($A instanceof Matrix) { - $this->try_success("Column-packed constructor..."); - } else - $errorCount = $this->try_failure($errorCount, "Column-packed constructor...", "Unable to construct Matrix"); - - $T = new Matrix($tvals); - if($T instanceof Matrix) - $this->try_success("2D array constructor..."); - else - $errorCount = $this->try_failure($errorCount, "2D array constructor...", "Unable to construct Matrix"); - - $A = new Matrix($columnwise, $validID); - $B = new Matrix($avals); - $tmp = $B->get(0,0); - $avals[0][0] = 0.0; - $C = $B->minus($A); - $avals[0][0] = $tmp; - $B = Matrix::constructWithCopy($avals); - $tmp = $B->get(0,0); - $avals[0][0] = 0.0; - /** check that constructWithCopy behaves properly **/ - if ( ( $tmp - $B->get(0,0) ) != 0.0 ) - $errorCount = $this->try_failure($errorCount,"constructWithCopy... ","copy not effected... data visible outside"); - else - $this->try_success("constructWithCopy... ",""); - - $I = new Matrix($ivals); - if ( $this->checkMatrices($I,Matrix::identity(3,4)) ) - $this->try_success("identity... ",""); - else - $errorCount = $this->try_failure($errorCount,"identity... ","identity Matrix not successfully created"); - - /** - * Access Methods: - * - * getColumnDimension() - * getRowDimension() - * getArray() - * getArrayCopy() - * getColumnPackedCopy() - * getRowPackedCopy() - * get(int,int) - * getMatrix(int,int,int,int) - * getMatrix(int,int,int[]) - * getMatrix(int[],int,int) - * getMatrix(int[],int[]) - * set(int,int,double) - * setMatrix(int,int,int,int,Matrix) - * setMatrix(int,int,int[],Matrix) - * setMatrix(int[],int,int,Matrix) - * setMatrix(int[],int[],Matrix) - */ - print "

Testing access methods...

"; - - $B = new Matrix($avals); - if($B->getRowDimension() == $rows) - $this->try_success("getRowDimension..."); - else - $errorCount = $this->try_failure($errorCount, "getRowDimension..."); - - if($B->getColumnDimension() == $cols) - $this->try_success("getColumnDimension..."); - else - $errorCount = $this->try_failure($errorCount, "getColumnDimension..."); - - $barray = $B->getArray(); - if($this->checkArrays($barray, $avals)) - $this->try_success("getArray..."); - else - $errorCount = $this->try_failure($errorCount, "getArray..."); - - $bpacked = $B->getColumnPackedCopy(); - if($this->checkArrays($bpacked, $columnwise)) - $this->try_success("getColumnPackedCopy..."); - else - $errorCount = $this->try_failure($errorCount, "getColumnPackedCopy..."); - - $bpacked = $B->getRowPackedCopy(); - if($this->checkArrays($bpacked, $rowwise)) - $this->try_success("getRowPackedCopy..."); - else - $errorCount = $this->try_failure($errorCount, "getRowPackedCopy..."); - - /** - * Array-like methods: - * minus - * minusEquals - * plus - * plusEquals - * arrayLeftDivide - * arrayLeftDivideEquals - * arrayRightDivide - * arrayRightDivideEquals - * arrayTimes - * arrayTimesEquals - * uminus - */ - print "

Testing array-like methods...

"; - - /** - * I/O methods: - * read - * print - * serializable: - * writeObject - * readObject - */ - print "

Testing I/O methods...

"; - - /** - * Test linear algebra methods - */ - echo "

Testing linear algebra methods...

"; - - $A = new Matrix($columnwise, 3); - if( $this->checkMatrices($A->transpose(), $T) ) - $this->try_success("Transpose check..."); - else - $errorCount = $this->try_failure($errorCount, "Transpose check...", "Matrices are not equal"); - - if($this->checkScalars($A->norm1(), $columnsummax)) - $this->try_success("Maximum column sum..."); - else - $errorCount = $this->try_failure($errorCount, "Maximum column sum...", "Incorrect: " . $A->norm1() . " != " . $columnsummax); - - if($this->checkScalars($A->normInf(), $rowsummax)) - $this->try_success("Maximum row sum..."); - else - $errorCount = $this->try_failure($errorCount, "Maximum row sum...", "Incorrect: " . $A->normInf() . " != " . $rowsummax ); - - if($this->checkScalars($A->normF(), sqrt($sumofsquares))) - $this->try_success("Frobenius norm..."); - else - $errorCount = $this->try_failure($errorCount, "Frobenius norm...", "Incorrect:" . $A->normF() . " != " . sqrt($sumofsquares)); - - if($this->checkScalars($A->trace(), $sumofdiagonals)) - $this->try_success("Matrix trace..."); - else - $errorCount = $this->try_failure($errorCount, "Matrix trace...", "Incorrect: " . $A->trace() . " != " . $sumofdiagonals); - - $B = $A->getMatrix(0, $A->getRowDimension(), 0, $A->getRowDimension()); - if( $B->det() == 0 ) - $this->try_success("Matrix determinant..."); - else - $errorCount = $this->try_failure($errorCount, "Matrix determinant...", "Incorrect: " . $B->det() . " != " . 0); - - $A = new Matrix($columnwise,3); - $SQ = new Matrix($square); - if ($this->checkMatrices($SQ, $A->times($A->transpose()))) - $this->try_success("times(Matrix)..."); - else { - $errorCount = $this->try_failure($errorCount, "times(Matrix)...", "Unable to multiply matrices"); - $SQ->toHTML(); - $AT->toHTML(); - } - - $A = new Matrix($columnwise, 4); - - $QR = $A->qr(); - $R = $QR->getR(); - $Q = $QR->getQ(); - if($this->checkMatrices($A, $Q->times($R))) - $this->try_success("QRDecomposition...",""); - else - $errorCount = $this->try_failure($errorCount,"QRDecomposition...","incorrect qr decomposition calculation"); - - $A = new Matrix($columnwise, 4); - $SVD = $A->svd(); - $U = $SVD->getU(); - $S = $SVD->getS(); - $V = $SVD->getV(); - if ($this->checkMatrices($A, $U->times($S->times($V->transpose())))) - $this->try_success("SingularValueDecomposition...",""); - else - $errorCount = $this->try_failure($errorCount,"SingularValueDecomposition...","incorrect singular value decomposition calculation"); - - $n = $A->getColumnDimension(); - $A = $A->getMatrix(0,$n-1,0,$n-1); - $A->set(0,0,0.); - - $LU = $A->lu(); - $L = $LU->getL(); - if ( $this->checkMatrices($A->getMatrix($LU->getPivot(),0,$n-1), $L->times($LU->getU())) ) - $this->try_success("LUDecomposition...",""); - else - $errorCount = $this->try_failure($errorCount,"LUDecomposition...","incorrect LU decomposition calculation"); - - $X = $A->inverse(); - if ( $this->checkMatrices($A->times($X),Matrix::identity(3,3)) ) - $this->try_success("inverse()...",""); - else - $errorCount = $this->try_failure($errorCount, "inverse()...","incorrect inverse calculation"); - - $DEF = new Matrix($rankdef); - if($this->checkScalars($DEF->rank(), min($DEF->getRowDimension(), $DEF->getColumnDimension())-1)) - $this->try_success("Rank..."); - else - $this->try_failure("Rank...", "incorrect rank calculation"); - - $B = new Matrix($condmat); - $SVD = $B->svd(); - $singularvalues = $SVD->getSingularValues(); - if($this->checkScalars($B->cond(), $singularvalues[0]/$singularvalues[min($B->getRowDimension(), $B->getColumnDimension())-1])) - $this->try_success("Condition number..."); - else - $this->try_failure("Condition number...", "incorrect condition number calculation"); - - $SUB = new Matrix($subavals); - $O = new Matrix($SUB->getRowDimension(),1,1.0); - $SOL = new Matrix($sqSolution); - $SQ = $SUB->getMatrix(0,$SUB->getRowDimension()-1,0,$SUB->getRowDimension()-1); - if ( $this->checkMatrices($SQ->solve($SOL),$O) ) - $this->try_success("solve()...",""); - else - $errorCount = $this->try_failure($errorCount,"solve()...","incorrect lu solve calculation"); - - $A = new Matrix($pvals); - $Chol = $A->chol(); - $L = $Chol->getL(); - if ( $this->checkMatrices($A, $L->times($L->transpose())) ) - $this->try_success("CholeskyDecomposition...",""); - else - $errorCount = $this->try_failure($errorCount,"CholeskyDecomposition...","incorrect Cholesky decomposition calculation"); - - $X = $Chol->solve(Matrix::identity(3,3)); - if ( $this->checkMatrices($A->times($X), Matrix::identity(3,3)) ) - $this->try_success("CholeskyDecomposition solve()...",""); - else - $errorCount = $this->try_failure($errorCount,"CholeskyDecomposition solve()...","incorrect Choleskydecomposition solve calculation"); - - $Eig = $A->eig(); - $D = $Eig->getD(); - $V = $Eig->getV(); - if( $this->checkMatrices($A->times($V),$V->times($D)) ) - $this->try_success("EigenvalueDecomposition (symmetric)...",""); - else - $errorCount = $this->try_failure($errorCount,"EigenvalueDecomposition (symmetric)...","incorrect symmetric Eigenvalue decomposition calculation"); - - $A = new Matrix($evals); - $Eig = $A->eig(); - $D = $Eig->getD(); - $V = $Eig->getV(); - if ( $this->checkMatrices($A->times($V),$V->times($D)) ) - $this->try_success("EigenvalueDecomposition (nonsymmetric)...",""); - else - $errorCount = $this->try_failure($errorCount,"EigenvalueDecomposition (nonsymmetric)...","incorrect nonsymmetric Eigenvalue decomposition calculation"); - - print("{$errorCount} total errors."); - } - - /** - * Print appropriate messages for successful outcome try - * @param string $s - * @param string $e - */ - function try_success($s, $e = "") { - print "> ". $s ."success
"; - if ($e != "") - print "> Message: ". $e ."
"; - } - - /** - * Print appropriate messages for unsuccessful outcome try - * @param int $count - * @param string $s - * @param string $e - * @return int incremented counter - */ - function try_failure($count, $s, $e="") { - print "> ". $s ."*** failure ***
> Message: ". $e ."
"; - return ++$count; - } - - /** - * Print appropriate messages for unsuccessful outcome try - * @param int $count - * @param string $s - * @param string $e - * @return int incremented counter - */ - function try_warning($count, $s, $e="") { - print "> ". $s ."*** warning ***
> Message: ". $e ."
"; - return ++$count; - } - - /** - * Check magnitude of difference of "scalars". - * @param float $x - * @param float $y - */ - function checkScalars($x, $y) { - $eps = pow(2.0,-52.0); - if ($x == 0 & abs($y) < 10*$eps) return; - if ($y == 0 & abs($x) < 10*$eps) return; - if (abs($x-$y) > 10 * $eps * max(abs($x),abs($y))) - return false; - else - return true; - } - - /** - * Check norm of difference of "vectors". - * @param float $x[] - * @param float $y[] - */ - function checkVectors($x, $y) { - $nx = count($x); - $ny = count($y); - if ($nx == $ny) - for($i=0; $i < $nx; ++$i) - $this->checkScalars($x[$i],$y[$i]); - else - die("Attempt to compare vectors of different lengths"); - } - - /** - * Check norm of difference of "arrays". - * @param float $x[][] - * @param float $y[][] - */ - function checkArrays($x, $y) { - $A = new Matrix($x); - $B = new Matrix($y); - return $this->checkMatrices($A,$B); - } - - /** - * Check norm of difference of "matrices". - * @param matrix $X - * @param matrix $Y - */ - function checkMatrices($X = null, $Y = null) { - if( $X == null || $Y == null ) - return false; - - $eps = pow(2.0,-52.0); - if ($X->norm1() == 0. & $Y->norm1() < 10*$eps) return true; - if ($Y->norm1() == 0. & $X->norm1() < 10*$eps) return true; - - $A = $X->minus($Y); - - if ($A->norm1() > 1000 * $eps * max($X->norm1(),$Y->norm1())) - die("The norm of (X-Y) is too large: ".$A->norm1()); - else - return true; - } - -} - -$test = new TestMatrix; -?> diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/utils/Maths.php b/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/utils/Maths.php index f5e2a372165..aa09a8bbbfa 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/utils/Maths.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/JAMA/utils/Maths.php @@ -35,7 +35,7 @@ function hypot() { if (is_numeric($d)) { $s += pow($d, 2); } else { - throw new Exception(JAMAError(ArgumentTypeException)); + throw new PHPExcel_Calculation_Exception(JAMAError(ArgumentTypeException)); } } return sqrt($s); diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/OLE.php b/htdocs/includes/phpexcel/PHPExcel/Shared/OLE.php index a5c8dd1d000..9796282a806 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/OLE.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/OLE.php @@ -97,18 +97,18 @@ class PHPExcel_Shared_OLE { $fh = fopen($file, "r"); if (!$fh) { - throw new Exception("Can't open file $file"); + throw new PHPExcel_Reader_Exception("Can't open file $file"); } $this->_file_handle = $fh; $signature = fread($fh, 8); if ("\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1" != $signature) { - throw new Exception("File doesn't seem to be an OLE container."); + throw new PHPExcel_Reader_Exception("File doesn't seem to be an OLE container."); } fseek($fh, 28); if (fread($fh, 2) != "\xFE\xFF") { // This shouldn't be a problem in practice - throw new Exception("Only Little-Endian encoding is supported."); + throw new PHPExcel_Reader_Exception("Only Little-Endian encoding is supported."); } // Size of blocks and short blocks in bytes $this->bigBlockSize = pow(2, self::_readInt2($fh)); diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/OLE/ChainedBlockStream.php b/htdocs/includes/phpexcel/PHPExcel/Shared/OLE/ChainedBlockStream.php index 4e233ad0436..3dcd7e1dad0 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/OLE/ChainedBlockStream.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/OLE/ChainedBlockStream.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (C) 2006 - 2012 PHPExcel + * Copyright (C) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,7 +22,7 @@ * @package PHPExcel_Shared_OLE * @copyright Copyright (c) 2006 - 2007 Christian Schmidt * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ /** @@ -161,14 +161,15 @@ class PHPExcel_Shared_OLE_ChainedBlockStream */ public function stream_eof() { - $eof = $this->pos >= strlen($this->data); - // Workaround for bug in PHP 5.0.x: http://bugs.php.net/27508 - if (version_compare(PHP_VERSION, '5.0', '>=') && - version_compare(PHP_VERSION, '5.1', '<')) { - - $eof = !$eof; - } - return $eof; +// As we don't support below 5.2 anymore, this is simply redundancy and overhead +// $eof = $this->pos >= strlen($this->data); +// // Workaround for bug in PHP 5.0.x: http://bugs.php.net/27508 +// if (version_compare(PHP_VERSION, '5.0', '>=') && +// version_compare(PHP_VERSION, '5.1', '<')) { +// $eof = !$eof; +// } +// return $eof; + return $this->pos >= strlen($this->data); } /** diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/OLE/PPS/Root.php b/htdocs/includes/phpexcel/PHPExcel/Shared/OLE/PPS/Root.php index 7046a0a3aeb..8c6dcda078a 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/OLE/PPS/Root.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/OLE/PPS/Root.php @@ -84,13 +84,13 @@ class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS $this->_tmp_filename = tempnam($this->_tmp_dir, "OLE_PPS_Root"); $this->_FILEH_ = fopen($this->_tmp_filename,"w+b"); if ($this->_FILEH_ == false) { - throw new Exception("Can't create temporary file."); + throw new PHPExcel_Writer_Exception("Can't create temporary file."); } } else { $this->_FILEH_ = fopen($filename, "wb"); } if ($this->_FILEH_ == false) { - throw new Exception("Can't open $filename. It may be in use or protected."); + throw new PHPExcel_Writer_Exception("Can't open $filename. It may be in use or protected."); } // Make an array of PPS's (for Save) $aList = array(); diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/OLERead.php b/htdocs/includes/phpexcel/PHPExcel/Shared/OLERead.php index 2a5eb7d7a12..c4cb7da3064 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/OLERead.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/OLERead.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,12 +20,13 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ -define('IDENTIFIER_OLE', pack('CCCCCCCC', 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1)); +defined('IDENTIFIER_OLE') || + define('IDENTIFIER_OLE', pack('CCCCCCCC', 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1)); class PHPExcel_Shared_OLERead { private $data = ''; @@ -70,23 +71,27 @@ class PHPExcel_Shared_OLERead { * Read the file * * @param $sFileName string Filename - * @throws Exception + * @throws PHPExcel_Reader_Exception */ public function read($sFileName) { // Check if file exists and is readable if(!is_readable($sFileName)) { - throw new Exception("Could not open " . $sFileName . " for reading! File does not exist, or it is not readable."); + throw new PHPExcel_Reader_Exception("Could not open " . $sFileName . " for reading! File does not exist, or it is not readable."); + } + + // Get the file identifier + // Don't bother reading the whole file until we know it's a valid OLE file + $this->data = file_get_contents($sFileName, FALSE, NULL, 0, 8); + + // Check OLE identifier + if ($this->data != self::IDENTIFIER_OLE) { + throw new PHPExcel_Reader_Exception('The filename ' . $sFileName . ' is not recognised as an OLE file'); } // Get the file data $this->data = file_get_contents($sFileName); - // Check OLE identifier - if (substr($this->data, 0, 8) != self::IDENTIFIER_OLE) { - throw new Exception('The filename ' . $sFileName . ' is not recognised as an OLE file'); - } - // Total number of sectors used for the SAT $this->numBigBlockDepotBlocks = self::_GetInt4d($this->data, self::NUM_BIG_BLOCK_DEPOT_BLOCKS_POS); @@ -131,34 +136,26 @@ class PHPExcel_Shared_OLERead { } } - $pos = $index = 0; - $this->bigBlockChain = array(); - + $pos = 0; + $this->bigBlockChain = ''; $bbs = self::BIG_BLOCK_SIZE / 4; for ($i = 0; $i < $this->numBigBlockDepotBlocks; ++$i) { $pos = ($bigBlockDepotBlocks[$i] + 1) * self::BIG_BLOCK_SIZE; - for ($j = 0 ; $j < $bbs; ++$j) { - $this->bigBlockChain[$index] = self::_GetInt4d($this->data, $pos); - $pos += 4 ; - ++$index; - } + $this->bigBlockChain .= substr($this->data, $pos, 4*$bbs); + $pos += 4*$bbs; } - $pos = $index = 0; + $pos = 0; $sbdBlock = $this->sbdStartBlock; - $this->smallBlockChain = array(); - + $this->smallBlockChain = ''; while ($sbdBlock != -2) { $pos = ($sbdBlock + 1) * self::BIG_BLOCK_SIZE; - for ($j = 0; $j < $bbs; ++$j) { - $this->smallBlockChain[$index] = self::_GetInt4d($this->data, $pos); - $pos += 4; - ++$index; - } + $this->smallBlockChain .= substr($this->data, $pos, 4*$bbs); + $pos += 4*$bbs; - $sbdBlock = $this->bigBlockChain[$sbdBlock]; + $sbdBlock = self::_GetInt4d($this->bigBlockChain, $sbdBlock*4); } // read the directory stream @@ -190,7 +187,7 @@ class PHPExcel_Shared_OLERead { $pos = $block * self::SMALL_BLOCK_SIZE; $streamData .= substr($rootdata, $pos, self::SMALL_BLOCK_SIZE); - $block = $this->smallBlockChain[$block]; + $block = self::_GetInt4d($this->smallBlockChain, $block*4); } return $streamData; @@ -207,7 +204,7 @@ class PHPExcel_Shared_OLERead { while ($block != -2) { $pos = ($block + 1) * self::BIG_BLOCK_SIZE; $streamData .= substr($this->data, $pos, self::BIG_BLOCK_SIZE); - $block = $this->bigBlockChain[$block]; + $block = self::_GetInt4d($this->bigBlockChain, $block*4); } return $streamData; @@ -228,7 +225,7 @@ class PHPExcel_Shared_OLERead { while ($block != -2) { $pos = ($block + 1) * self::BIG_BLOCK_SIZE; $data .= substr($this->data, $pos, self::BIG_BLOCK_SIZE); - $block = $this->bigBlockChain[$block]; + $block = self::_GetInt4d($this->bigBlockChain, $block*4); } return $data; } @@ -259,19 +256,22 @@ class PHPExcel_Shared_OLERead { $name = str_replace("\x00", "", substr($d,0,$nameSize)); + $this->props[] = array ( 'name' => $name, 'type' => $type, 'startBlock' => $startBlock, 'size' => $size); + // tmp helper to simplify checks + $upName = strtoupper($name); + // Workbook directory entry (BIFF5 uses Book, BIFF8 uses Workbook) - if (($name == 'Workbook') || ($name == 'Book') || ($name == 'WORKBOOK') || ($name == 'BOOK')) { + if (($upName === 'WORKBOOK') || ($upName === 'BOOK')) { $this->wrkbook = count($this->props) - 1; } - - // Root entry - if ($name == 'Root Entry' || $name == 'ROOT ENTRY' || $name == 'R') { + else if ( $upName === 'ROOT ENTRY' || $upName === 'R') { + // Root entry $this->rootentry = count($this->props) - 1; } diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/PasswordHasher.php b/htdocs/includes/phpexcel/PHPExcel/Shared/PasswordHasher.php index 65317d55b43..4f505a2aca6 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/PasswordHasher.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/PasswordHasher.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_PasswordHasher { @@ -46,17 +46,16 @@ class PHPExcel_Shared_PasswordHasher * @return string Hashed password */ public static function hashPassword($pPassword = '') { - $password = 0x0000; - $i = 1; // char position + $password = 0x0000; + $charPos = 1; // char position // split the plain text password in its component characters $chars = preg_split('//', $pPassword, -1, PREG_SPLIT_NO_EMPTY); foreach ($chars as $char) { - $value = ord($char) << $i; // shifted ASCII value - $rotated_bits = $value >> 15; // rotated bits beyond bit 15 - $value &= 0x7fff; // first 15 bits - $password ^= ($value | $rotated_bits); - ++$i; + $value = ord($char) << $charPos++; // shifted ASCII value + $rotated_bits = $value >> 15; // rotated bits beyond bit 15 + $value &= 0x7fff; // first 15 bits + $password ^= ($value | $rotated_bits); } $password ^= strlen($pPassword); diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/String.php b/htdocs/includes/phpexcel/PHPExcel/Shared/String.php index a62a681662a..49d217a5cbd 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/String.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/String.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_String { @@ -403,7 +403,7 @@ class PHPExcel_Shared_String * @return boolean */ public static function IsUTF8($value = '') { - return utf8_encode(utf8_decode($value)) === $value; + return $string === '' || preg_match('/^./su', $string) === 1; } /** @@ -427,14 +427,14 @@ class PHPExcel_Shared_String * although this will give wrong results for non-ASCII strings * see OpenOffice.org's Documentation of the Microsoft Excel File Format, sect. 2.5.3 * - * @param string $value UTF-8 encoded string + * @param string $value UTF-8 encoded string + * @param mixed[] $arrcRuns Details of rich text runs in $value * @return string */ public static function UTF8toBIFF8UnicodeShort($value, $arrcRuns = array()) { // character count $ln = self::CountCharacters($value, 'UTF-8'); - // option flags if(empty($arrcRuns)){ $opt = (self::getIsIconvEnabled() || self::getIsMbstringEnabled()) ? @@ -444,10 +444,10 @@ class PHPExcel_Shared_String $data .= self::ConvertEncoding($value, 'UTF-16LE', 'UTF-8'); } else { - $data = pack('vC', $ln, 0x08); + $data = pack('vC', $ln, 0x09); $data .= pack('v', count($arrcRuns)); // characters - $data .= $value; + $data .= self::ConvertEncoding($value, 'UTF-16LE', 'UTF-8'); foreach ($arrcRuns as $cRun){ $data .= pack('v', $cRun['strlen']); $data .= pack('v', $cRun['fontidx']); @@ -483,7 +483,7 @@ class PHPExcel_Shared_String } /** - * Convert string from one encoding to another. First try iconv, then mbstring, or no convertion + * Convert string from one encoding to another. First try mbstring, then iconv, finally strlen * * @param string $value * @param string $to Encoding to convert to, e.g. 'UTF-8' @@ -493,14 +493,13 @@ class PHPExcel_Shared_String public static function ConvertEncoding($value, $to, $from) { if (self::getIsIconvEnabled()) { - $value = iconv($from, $to, $value); - return $value; + return iconv($from, $to, $value); } if (self::getIsMbstringEnabled()) { - $value = mb_convert_encoding($value, $to, $from); - return $value; + return mb_convert_encoding($value, $to, $from); } + if($from == 'UTF-16LE'){ return self::utf16_decode($value, false); }else if($from == 'UTF-16BE'){ @@ -525,7 +524,7 @@ class PHPExcel_Shared_String * @author Rasmus Andersson {@link http://rasmusandersson.se/} * @author vadik56 */ - public static function utf16_decode( $str, $bom_be=true ) { + public static function utf16_decode($str, $bom_be = TRUE) { if( strlen($str) < 2 ) return $str; $c0 = ord($str{0}); $c1 = ord($str{1}); @@ -550,40 +549,82 @@ class PHPExcel_Shared_String */ public static function CountCharacters($value, $enc = 'UTF-8') { - if (self::getIsIconvEnabled()) { - return iconv_strlen($value, $enc); - } - if (self::getIsMbstringEnabled()) { return mb_strlen($value, $enc); } + if (self::getIsIconvEnabled()) { + return iconv_strlen($value, $enc); + } + // else strlen return strlen($value); } /** - * Get a substring of a UTF-8 encoded string + * Get a substring of a UTF-8 encoded string. First try mbstring, then iconv, finally strlen * * @param string $pValue UTF-8 encoded string - * @param int $start Start offset - * @param int $length Maximum number of characters in substring + * @param int $pStart Start offset + * @param int $pLength Maximum number of characters in substring * @return string */ public static function Substring($pValue = '', $pStart = 0, $pLength = 0) { - if (self::getIsIconvEnabled()) { - return iconv_substr($pValue, $pStart, $pLength, 'UTF-8'); - } - if (self::getIsMbstringEnabled()) { return mb_substr($pValue, $pStart, $pLength, 'UTF-8'); } + if (self::getIsIconvEnabled()) { + return iconv_substr($pValue, $pStart, $pLength, 'UTF-8'); + } + // else substr return substr($pValue, $pStart, $pLength); } + /** + * Convert a UTF-8 encoded string to upper case + * + * @param string $pValue UTF-8 encoded string + * @return string + */ + public static function StrToUpper($pValue = '') + { + if (function_exists('mb_convert_case')) { + return mb_convert_case($pValue, MB_CASE_UPPER, "UTF-8"); + } + return strtoupper($pValue); + } + + /** + * Convert a UTF-8 encoded string to lower case + * + * @param string $pValue UTF-8 encoded string + * @return string + */ + public static function StrToLower($pValue = '') + { + if (function_exists('mb_convert_case')) { + return mb_convert_case($pValue, MB_CASE_LOWER, "UTF-8"); + } + return strtolower($pValue); + } + + /** + * Convert a UTF-8 encoded string to title/proper case + * (uppercase every first character in each word, lower case all other characters) + * + * @param string $pValue UTF-8 encoded string + * @return string + */ + public static function StrToTitle($pValue = '') + { + if (function_exists('mb_convert_case')) { + return mb_convert_case($pValue, MB_CASE_TITLE, "UTF-8"); + } + return ucwords($pValue); + } /** * Identify whether a string contains a fractional numeric value, @@ -646,6 +687,11 @@ class PHPExcel_Shared_String $localeconv = localeconv(); self::$_thousandsSeparator = ($localeconv['thousands_sep'] != '') ? $localeconv['thousands_sep'] : $localeconv['mon_thousands_sep']; + + if (self::$_thousandsSeparator == '') { + // Default to . + self::$_thousandsSeparator = ','; + } } return self::$_thousandsSeparator; } diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/TimeZone.php b/htdocs/includes/phpexcel/PHPExcel/Shared/TimeZone.php new file mode 100644 index 00000000000..d5fa2ade694 --- /dev/null +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/TimeZone.php @@ -0,0 +1,140 @@ +getTransitions(); + $transitions = array(); + foreach($allTransitions as $key => $transition) { + if ($transition['ts'] > $timestamp) { + $transitions[] = ($key > 0) ? $allTransitions[$key - 1] : $transition; + break; + } + if (empty($transitions)) { + $transitions[] = end($allTransitions); + } + } + + return $transitions; + } + + /** + * Return the Timezone offset used for date/time conversions to/from UST + * This requires both the timezone and the calculated date/time to allow for local DST + * + * @param string $timezone The timezone for finding the adjustment to UST + * @param integer $timestamp PHP date/time value + * @return integer Number of seconds for timezone adjustment + * @throws PHPExcel_Exception + */ + public static function getTimeZoneAdjustment($timezone, $timestamp) { + if ($timezone !== NULL) { + if (!self::_validateTimezone($timezone)) { + throw new PHPExcel_Exception("Invalid timezone " . $timezone); + } + } else { + $timezone = self::$_timezone; + } + + if ($timezone == 'UST') { + return 0; + } + + $objTimezone = new DateTimeZone($timezone); + if (version_compare(PHP_VERSION, '5.3.0') >= 0) { + $transitions = $objTimezone->getTransitions($timestamp,$timestamp); + } else { + $transitions = self::_getTimezoneTransitions($objTimezone, $timestamp); + } + + return (count($transitions) > 0) ? $transitions[0]['offset'] : 0; + } + +} diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/XMLWriter.php b/htdocs/includes/phpexcel/PHPExcel/Shared/XMLWriter.php index 403c0996adb..0b0b5539d47 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/XMLWriter.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/XMLWriter.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ if (!defined('DATE_W3C')) { @@ -39,7 +39,7 @@ if (!defined('DEBUGMODE_ENABLED')) { * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_XMLWriter extends XMLWriter { /** Temporary storage method */ diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/ZipArchive.php b/htdocs/includes/phpexcel/PHPExcel/Shared/ZipArchive.php index 56d7c391854..ab551afe946 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/ZipArchive.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/ZipArchive.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_ZipArchive - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ if (!defined('PCLZIP_TEMPORARY_DIR')) { @@ -36,7 +36,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/PCLZip/pclzip.lib.php'; * * @category PHPExcel * @package PHPExcel_Shared_ZipArchive - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_ZipArchive { @@ -105,10 +105,71 @@ class PHPExcel_Shared_ZipArchive PCLZIP_OPT_ADD_PATH, $filenameParts["dirname"] ); if ($res == 0) { - throw new Exception("Error zipping files : " . $this->_zip->errorInfo(true)); + throw new PHPExcel_Writer_Exception("Error zipping files : " . $this->_zip->errorInfo(true)); } unlink($this->_tempDir.'/'.$filenameParts["basename"]); } + /** + * Find if given fileName exist in archive (Emulate ZipArchive locateName()) + * + * @param string $fileName Filename for the file in zip archive + * @return boolean + */ + public function locateName($fileName) + { + $list = $this->_zip->listContent(); + $listCount = count($list); + $list_index = -1; + for ($i = 0; $i < $listCount; ++$i) { + if (strtolower($list[$i]["filename"]) == strtolower($fileName) || + strtolower($list[$i]["stored_filename"]) == strtolower($fileName)) { + $list_index = $i; + break; + } + } + return ($list_index > -1); + } + + /** + * Extract file from archive by given fileName (Emulate ZipArchive getFromName()) + * + * @param string $fileName Filename for the file in zip archive + * @return string $contents File string contents + */ + public function getFromName($fileName) + { + $list = $this->_zip->listContent(); + $listCount = count($list); + $list_index = -1; + for ($i = 0; $i < $listCount; ++$i) { + if (strtolower($list[$i]["filename"]) == strtolower($fileName) || + strtolower($list[$i]["stored_filename"]) == strtolower($fileName)) { + $list_index = $i; + break; + } + } + + $extracted = ""; + if ($list_index != -1) { + $extracted = $this->_zip->extractByIndex($list_index, PCLZIP_OPT_EXTRACT_AS_STRING); + } else { + $filename = substr($fileName, 1); + $list_index = -1; + for ($i = 0; $i < $listCount; ++$i) { + if (strtolower($list[$i]["filename"]) == strtolower($fileName) || + strtolower($list[$i]["stored_filename"]) == strtolower($fileName)) { + $list_index = $i; + break; + } + } + $extracted = $this->_zip->extractByIndex($list_index, PCLZIP_OPT_EXTRACT_AS_STRING); + } + if ((is_array($extracted)) && ($extracted != 0)) { + $contents = $extracted[0]["content"]; + } + + return $contents; + } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/ZipStreamWrapper.php b/htdocs/includes/phpexcel/PHPExcel/Shared/ZipStreamWrapper.php index 58d7e020a1c..696072bb0bd 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/ZipStreamWrapper.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/ZipStreamWrapper.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Shared - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Shared_ZipStreamWrapper { /** @@ -82,7 +82,7 @@ class PHPExcel_Shared_ZipStreamWrapper { public function stream_open($path, $mode, $options, &$opened_path) { // Check for mode if ($mode{0} != 'r') { - throw new Exception('Mode ' . $mode . ' is not supported. Only read mode is supported.'); + throw new PHPExcel_Reader_Exception('Mode ' . $mode . ' is not supported. Only read mode is supported.'); } $pos = strrpos($path, '#'); @@ -100,6 +100,24 @@ class PHPExcel_Shared_ZipStreamWrapper { return true; } + /** + * Implements support for fstat(). + * + * @return boolean + */ + public function statName() { + return $this->_fileNameInArchive; + } + + /** + * Implements support for fstat(). + * + * @return boolean + */ + public function url_stat() { + return $this->statName( $this->_fileNameInArchive ); + } + /** * Implements support for fstat(). * diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/trend/bestFitClass.php b/htdocs/includes/phpexcel/PHPExcel/Shared/trend/bestFitClass.php index d86424f1a0d..088ce067cb1 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/trend/bestFitClass.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/trend/bestFitClass.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Trend - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Shared_Trend - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Best_Fit { diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/trend/exponentialBestFitClass.php b/htdocs/includes/phpexcel/PHPExcel/Shared/trend/exponentialBestFitClass.php index cc44678bea8..44c7aee8519 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/trend/exponentialBestFitClass.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/trend/exponentialBestFitClass.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Trend - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -34,7 +34,7 @@ require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'); * * @category PHPExcel * @package PHPExcel_Shared_Trend - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Exponential_Best_Fit extends PHPExcel_Best_Fit { diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/trend/linearBestFitClass.php b/htdocs/includes/phpexcel/PHPExcel/Shared/trend/linearBestFitClass.php index 9aa44fec24e..00da841168f 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/trend/linearBestFitClass.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/trend/linearBestFitClass.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Trend - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -34,7 +34,7 @@ require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'); * * @category PHPExcel * @package PHPExcel_Shared_Trend - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Linear_Best_Fit extends PHPExcel_Best_Fit { diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/trend/logarithmicBestFitClass.php b/htdocs/includes/phpexcel/PHPExcel/Shared/trend/logarithmicBestFitClass.php index 38aaa880381..ac9c1e200bf 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/trend/logarithmicBestFitClass.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/trend/logarithmicBestFitClass.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Trend - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -34,7 +34,7 @@ require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'); * * @category PHPExcel * @package PHPExcel_Shared_Trend - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Logarithmic_Best_Fit extends PHPExcel_Best_Fit { diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/trend/polynomialBestFitClass.php b/htdocs/includes/phpexcel/PHPExcel/Shared/trend/polynomialBestFitClass.php index 7c05faf61be..a5079752927 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/trend/polynomialBestFitClass.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/trend/polynomialBestFitClass.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Trend - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -35,7 +35,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/Matrix.php'; * * @category PHPExcel * @package PHPExcel_Shared_Trend - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Polynomial_Best_Fit extends PHPExcel_Best_Fit { diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/trend/powerBestFitClass.php b/htdocs/includes/phpexcel/PHPExcel/Shared/trend/powerBestFitClass.php index 20b36741e3f..158e0c4592e 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/trend/powerBestFitClass.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/trend/powerBestFitClass.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Trend - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -34,7 +34,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'; * * @category PHPExcel * @package PHPExcel_Shared_Trend - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Power_Best_Fit extends PHPExcel_Best_Fit { diff --git a/htdocs/includes/phpexcel/PHPExcel/Shared/trend/trendClass.php b/htdocs/includes/phpexcel/PHPExcel/Shared/trend/trendClass.php index 63ccc04c311..d891a7dc6ca 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Shared/trend/trendClass.php +++ b/htdocs/includes/phpexcel/PHPExcel/Shared/trend/trendClass.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Shared_Trend - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -38,7 +38,7 @@ require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/polynomialBestFitClass.php'; * * @category PHPExcel * @package PHPExcel_Shared_Trend - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class trendClass { diff --git a/htdocs/includes/phpexcel/PHPExcel/Style.php b/htdocs/includes/phpexcel/PHPExcel/Style.php index 2fdef0e4cc9..715ae11319c 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Style.php +++ b/htdocs/includes/phpexcel/PHPExcel/Style.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.8.0, 2014-03-02 */ @@ -31,197 +31,147 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Style implements PHPExcel_IComparable +class PHPExcel_Style extends PHPExcel_Style_Supervisor implements PHPExcel_IComparable { - /** - * Font - * - * @var PHPExcel_Style_Font - */ - private $_font; + /** + * Font + * + * @var PHPExcel_Style_Font + */ + protected $_font; - /** - * Fill - * - * @var PHPExcel_Style_Fill - */ - private $_fill; + /** + * Fill + * + * @var PHPExcel_Style_Fill + */ + protected $_fill; - /** - * Borders - * - * @var PHPExcel_Style_Borders - */ - private $_borders; + /** + * Borders + * + * @var PHPExcel_Style_Borders + */ + protected $_borders; - /** - * Alignment - * - * @var PHPExcel_Style_Alignment - */ - private $_alignment; + /** + * Alignment + * + * @var PHPExcel_Style_Alignment + */ + protected $_alignment; - /** - * Number Format - * - * @var PHPExcel_Style_NumberFormat - */ - private $_numberFormat; + /** + * Number Format + * + * @var PHPExcel_Style_NumberFormat + */ + protected $_numberFormat; - /** - * Conditional styles - * - * @var PHPExcel_Style_Conditional[] - */ - private $_conditionalStyles; + /** + * Conditional styles + * + * @var PHPExcel_Style_Conditional[] + */ + protected $_conditionalStyles; - /** - * Protection - * - * @var PHPExcel_Style_Protection - */ - private $_protection; + /** + * Protection + * + * @var PHPExcel_Style_Protection + */ + protected $_protection; - /** - * Style supervisor? - * - * @var boolean - */ - private $_isSupervisor; + /** + * Index of style in collection. Only used for real style. + * + * @var int + */ + protected $_index; - /** - * Parent. Only used for style supervisor - * - * @var PHPExcel - */ - private $_parent; - - /** - * Index of style in collection. Only used for real style. - * - * @var int - */ - private $_index; + /** + * Use Quote Prefix when displaying in cell editor. Only used for real style. + * + * @var boolean + */ + protected $_quotePrefix = false; /** * Create a new PHPExcel_Style - * - * @param boolean $isSupervisor Flag indicating if this is a supervisor or not - * Leave this value at default unless you understand exactly what - * its ramifications are - * @param boolean $isConditional Flag indicating if this is a conditional style or not - * Leave this value at default unless you understand exactly what - * its ramifications are + * + * @param boolean $isSupervisor Flag indicating if this is a supervisor or not + * Leave this value at default unless you understand exactly what + * its ramifications are + * @param boolean $isConditional Flag indicating if this is a conditional style or not + * Leave this value at default unless you understand exactly what + * its ramifications are */ public function __construct($isSupervisor = false, $isConditional = false) { - // Supervisor? - $this->_isSupervisor = $isSupervisor; + // Supervisor? + $this->_isSupervisor = $isSupervisor; - // Initialise values - $this->_conditionalStyles = array(); - $this->_font = new PHPExcel_Style_Font($isSupervisor, $isConditional); - $this->_fill = new PHPExcel_Style_Fill($isSupervisor, $isConditional); - $this->_borders = new PHPExcel_Style_Borders($isSupervisor, $isConditional); - $this->_alignment = new PHPExcel_Style_Alignment($isSupervisor, $isConditional); - $this->_numberFormat = new PHPExcel_Style_NumberFormat($isSupervisor, $isConditional); - $this->_protection = new PHPExcel_Style_Protection($isSupervisor, $isConditional); + // Initialise values + $this->_conditionalStyles = array(); + $this->_font = new PHPExcel_Style_Font($isSupervisor, $isConditional); + $this->_fill = new PHPExcel_Style_Fill($isSupervisor, $isConditional); + $this->_borders = new PHPExcel_Style_Borders($isSupervisor, $isConditional); + $this->_alignment = new PHPExcel_Style_Alignment($isSupervisor, $isConditional); + $this->_numberFormat = new PHPExcel_Style_NumberFormat($isSupervisor, $isConditional); + $this->_protection = new PHPExcel_Style_Protection($isSupervisor, $isConditional); - // bind parent if we are a supervisor - if ($isSupervisor) { - $this->_font->bindParent($this); - $this->_fill->bindParent($this); - $this->_borders->bindParent($this); - $this->_alignment->bindParent($this); - $this->_numberFormat->bindParent($this); - $this->_protection->bindParent($this); - } + // bind parent if we are a supervisor + if ($isSupervisor) { + $this->_font->bindParent($this); + $this->_fill->bindParent($this); + $this->_borders->bindParent($this); + $this->_alignment->bindParent($this); + $this->_numberFormat->bindParent($this); + $this->_protection->bindParent($this); + } + } + + /** + * Get the shared style component for the currently active cell in currently active sheet. + * Only used for style supervisor + * + * @return PHPExcel_Style + */ + public function getSharedComponent() + { + $activeSheet = $this->getActiveSheet(); + $selectedCell = $this->getActiveCell(); // e.g. 'A1' + + if ($activeSheet->cellExists($selectedCell)) { + $xfIndex = $activeSheet->getCell($selectedCell)->getXfIndex(); + } else { + $xfIndex = 0; + } + + return $this->_parent->getCellXfByIndex($xfIndex); + } + + /** + * Get parent. Only used for style supervisor + * + * @return PHPExcel + */ + public function getParent() + { + return $this->_parent; } /** - * Bind parent. Only used for supervisor + * Build style array from subcomponents * - * @param PHPExcel $parent - * @return PHPExcel_Style + * @param array $array + * @return array */ - public function bindParent($parent) + public function getStyleArray($array) { - $this->_parent = $parent; - return $this; - } - - /** - * Is this a supervisor or a real style component? - * - * @return boolean - */ - public function getIsSupervisor() - { - return $this->_isSupervisor; - } - - /** - * Get the shared style component for the currently active cell in currently active sheet. - * Only used for style supervisor - * - * @return PHPExcel_Style - */ - public function getSharedComponent() - { - $activeSheet = $this->getActiveSheet(); - $selectedCell = $this->getActiveCell(); // e.g. 'A1' - - if ($activeSheet->cellExists($selectedCell)) { - $xfIndex = $activeSheet->getCell($selectedCell)->getXfIndex(); - } else { - $xfIndex = 0; - } - - return $this->_parent->getCellXfByIndex($xfIndex); - } - - /** - * Get the currently active sheet. Only used for supervisor - * - * @return PHPExcel_Worksheet - */ - public function getActiveSheet() - { - return $this->_parent->getActiveSheet(); - } - - /** - * Get the currently active cell coordinate in currently active sheet. - * Only used for supervisor - * - * @return string E.g. 'A1' - */ - public function getSelectedCells() - { - return $this->_parent->getActiveSheet()->getSelectedCells(); - } - - /** - * Get the currently active cell coordinate in currently active sheet. - * Only used for supervisor - * - * @return string E.g. 'A1' - */ - public function getActiveCell() - { - return $this->_parent->getActiveSheet()->getActiveCell(); - } - - /** - * Get parent. Only used for style supervisor - * - * @return PHPExcel - */ - public function getParent() - { - return $this->_parent; + return array('quotePrefix' => $array); } /** @@ -229,321 +179,327 @@ class PHPExcel_Style implements PHPExcel_IComparable * * * $objPHPExcel->getActiveSheet()->getStyle('B2')->applyFromArray( - * array( - * 'font' => array( - * 'name' => 'Arial', - * 'bold' => true, - * 'italic' => false, - * 'underline' => PHPExcel_Style_Font::UNDERLINE_DOUBLE, - * 'strike' => false, - * 'color' => array( - * 'rgb' => '808080' - * ) - * ), - * 'borders' => array( - * 'bottom' => array( - * 'style' => PHPExcel_Style_Border::BORDER_DASHDOT, - * 'color' => array( - * 'rgb' => '808080' - * ) - * ), - * 'top' => array( - * 'style' => PHPExcel_Style_Border::BORDER_DASHDOT, - * 'color' => array( - * 'rgb' => '808080' - * ) - * ) - * ) - * ) + * array( + * 'font' => array( + * 'name' => 'Arial', + * 'bold' => true, + * 'italic' => false, + * 'underline' => PHPExcel_Style_Font::UNDERLINE_DOUBLE, + * 'strike' => false, + * 'color' => array( + * 'rgb' => '808080' + * ) + * ), + * 'borders' => array( + * 'bottom' => array( + * 'style' => PHPExcel_Style_Border::BORDER_DASHDOT, + * 'color' => array( + * 'rgb' => '808080' + * ) + * ), + * 'top' => array( + * 'style' => PHPExcel_Style_Border::BORDER_DASHDOT, + * 'color' => array( + * 'rgb' => '808080' + * ) + * ) + * ), + * 'quotePrefix' => true + * ) * ); * * - * @param array $pStyles Array containing style information - * @param boolean $pAdvanced Advanced mode for setting borders. - * @throws Exception + * @param array $pStyles Array containing style information + * @param boolean $pAdvanced Advanced mode for setting borders. + * @throws PHPExcel_Exception * @return PHPExcel_Style */ - public function applyFromArray($pStyles = null, $pAdvanced = true) { - if (is_array($pStyles)) { - if ($this->_isSupervisor) { + public function applyFromArray($pStyles = null, $pAdvanced = true) + { + if (is_array($pStyles)) { + if ($this->_isSupervisor) { - $pRange = $this->getSelectedCells(); + $pRange = $this->getSelectedCells(); - // Uppercase coordinate - $pRange = strtoupper($pRange); + // Uppercase coordinate + $pRange = strtoupper($pRange); - // Is it a cell range or a single cell? - if (strpos($pRange, ':') === false) { - $rangeA = $pRange; - $rangeB = $pRange; - } else { - list($rangeA, $rangeB) = explode(':', $pRange); - } + // Is it a cell range or a single cell? + if (strpos($pRange, ':') === false) { + $rangeA = $pRange; + $rangeB = $pRange; + } else { + list($rangeA, $rangeB) = explode(':', $pRange); + } - // Calculate range outer borders - $rangeStart = PHPExcel_Cell::coordinateFromString($rangeA); - $rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB); + // Calculate range outer borders + $rangeStart = PHPExcel_Cell::coordinateFromString($rangeA); + $rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB); - // Translate column into index - $rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]) - 1; - $rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]) - 1; + // Translate column into index + $rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]) - 1; + $rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]) - 1; - // Make sure we can loop upwards on rows and columns - if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) { - $tmp = $rangeStart; - $rangeStart = $rangeEnd; - $rangeEnd = $tmp; - } + // Make sure we can loop upwards on rows and columns + if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) { + $tmp = $rangeStart; + $rangeStart = $rangeEnd; + $rangeEnd = $tmp; + } - // ADVANCED MODE: + // ADVANCED MODE: - if ($pAdvanced && isset($pStyles['borders'])) { + if ($pAdvanced && isset($pStyles['borders'])) { - // 'allborders' is a shorthand property for 'outline' and 'inside' and - // it applies to components that have not been set explicitly - if (isset($pStyles['borders']['allborders'])) { - foreach (array('outline', 'inside') as $component) { - if (!isset($pStyles['borders'][$component])) { - $pStyles['borders'][$component] = $pStyles['borders']['allborders']; - } - } - unset($pStyles['borders']['allborders']); // not needed any more - } + // 'allborders' is a shorthand property for 'outline' and 'inside' and + // it applies to components that have not been set explicitly + if (isset($pStyles['borders']['allborders'])) { + foreach (array('outline', 'inside') as $component) { + if (!isset($pStyles['borders'][$component])) { + $pStyles['borders'][$component] = $pStyles['borders']['allborders']; + } + } + unset($pStyles['borders']['allborders']); // not needed any more + } - // 'outline' is a shorthand property for 'top', 'right', 'bottom', 'left' - // it applies to components that have not been set explicitly - if (isset($pStyles['borders']['outline'])) { - foreach (array('top', 'right', 'bottom', 'left') as $component) { - if (!isset($pStyles['borders'][$component])) { - $pStyles['borders'][$component] = $pStyles['borders']['outline']; - } - } - unset($pStyles['borders']['outline']); // not needed any more - } + // 'outline' is a shorthand property for 'top', 'right', 'bottom', 'left' + // it applies to components that have not been set explicitly + if (isset($pStyles['borders']['outline'])) { + foreach (array('top', 'right', 'bottom', 'left') as $component) { + if (!isset($pStyles['borders'][$component])) { + $pStyles['borders'][$component] = $pStyles['borders']['outline']; + } + } + unset($pStyles['borders']['outline']); // not needed any more + } - // 'inside' is a shorthand property for 'vertical' and 'horizontal' - // it applies to components that have not been set explicitly - if (isset($pStyles['borders']['inside'])) { - foreach (array('vertical', 'horizontal') as $component) { - if (!isset($pStyles['borders'][$component])) { - $pStyles['borders'][$component] = $pStyles['borders']['inside']; - } - } - unset($pStyles['borders']['inside']); // not needed any more - } + // 'inside' is a shorthand property for 'vertical' and 'horizontal' + // it applies to components that have not been set explicitly + if (isset($pStyles['borders']['inside'])) { + foreach (array('vertical', 'horizontal') as $component) { + if (!isset($pStyles['borders'][$component])) { + $pStyles['borders'][$component] = $pStyles['borders']['inside']; + } + } + unset($pStyles['borders']['inside']); // not needed any more + } - // width and height characteristics of selection, 1, 2, or 3 (for 3 or more) - $xMax = min($rangeEnd[0] - $rangeStart[0] + 1, 3); - $yMax = min($rangeEnd[1] - $rangeStart[1] + 1, 3); + // width and height characteristics of selection, 1, 2, or 3 (for 3 or more) + $xMax = min($rangeEnd[0] - $rangeStart[0] + 1, 3); + $yMax = min($rangeEnd[1] - $rangeStart[1] + 1, 3); - // loop through up to 3 x 3 = 9 regions - for ($x = 1; $x <= $xMax; ++$x) { - // start column index for region - $colStart = ($x == 3) ? - PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]) - : PHPExcel_Cell::stringFromColumnIndex($rangeStart[0] + $x - 1); + // loop through up to 3 x 3 = 9 regions + for ($x = 1; $x <= $xMax; ++$x) { + // start column index for region + $colStart = ($x == 3) ? + PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]) + : PHPExcel_Cell::stringFromColumnIndex($rangeStart[0] + $x - 1); - // end column index for region - $colEnd = ($x == 1) ? - PHPExcel_Cell::stringFromColumnIndex($rangeStart[0]) - : PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0] - $xMax + $x); + // end column index for region + $colEnd = ($x == 1) ? + PHPExcel_Cell::stringFromColumnIndex($rangeStart[0]) + : PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0] - $xMax + $x); - for ($y = 1; $y <= $yMax; ++$y) { + for ($y = 1; $y <= $yMax; ++$y) { - // which edges are touching the region - $edges = array(); + // which edges are touching the region + $edges = array(); - // are we at left edge - if ($x == 1) { - $edges[] = 'left'; - } + // are we at left edge + if ($x == 1) { + $edges[] = 'left'; + } - // are we at right edge - if ($x == $xMax) { - $edges[] = 'right'; - } + // are we at right edge + if ($x == $xMax) { + $edges[] = 'right'; + } - // are we at top edge? - if ($y == 1) { - $edges[] = 'top'; - } + // are we at top edge? + if ($y == 1) { + $edges[] = 'top'; + } - // are we at bottom edge? - if ($y == $yMax) { - $edges[] = 'bottom'; - } + // are we at bottom edge? + if ($y == $yMax) { + $edges[] = 'bottom'; + } - // start row index for region - $rowStart = ($y == 3) ? - $rangeEnd[1] : $rangeStart[1] + $y - 1; + // start row index for region + $rowStart = ($y == 3) ? + $rangeEnd[1] : $rangeStart[1] + $y - 1; - // end row index for region - $rowEnd = ($y == 1) ? - $rangeStart[1] : $rangeEnd[1] - $yMax + $y; + // end row index for region + $rowEnd = ($y == 1) ? + $rangeStart[1] : $rangeEnd[1] - $yMax + $y; - // build range for region - $range = $colStart . $rowStart . ':' . $colEnd . $rowEnd; + // build range for region + $range = $colStart . $rowStart . ':' . $colEnd . $rowEnd; - // retrieve relevant style array for region - $regionStyles = $pStyles; - unset($regionStyles['borders']['inside']); + // retrieve relevant style array for region + $regionStyles = $pStyles; + unset($regionStyles['borders']['inside']); - // what are the inner edges of the region when looking at the selection - $innerEdges = array_diff( array('top', 'right', 'bottom', 'left'), $edges ); + // what are the inner edges of the region when looking at the selection + $innerEdges = array_diff( array('top', 'right', 'bottom', 'left'), $edges ); - // inner edges that are not touching the region should take the 'inside' border properties if they have been set - foreach ($innerEdges as $innerEdge) { - switch ($innerEdge) { - case 'top': - case 'bottom': - // should pick up 'horizontal' border property if set - if (isset($pStyles['borders']['horizontal'])) { - $regionStyles['borders'][$innerEdge] = $pStyles['borders']['horizontal']; - } else { - unset($regionStyles['borders'][$innerEdge]); - } - break; - case 'left': - case 'right': - // should pick up 'vertical' border property if set - if (isset($pStyles['borders']['vertical'])) { - $regionStyles['borders'][$innerEdge] = $pStyles['borders']['vertical']; - } else { - unset($regionStyles['borders'][$innerEdge]); - } - break; - } - } + // inner edges that are not touching the region should take the 'inside' border properties if they have been set + foreach ($innerEdges as $innerEdge) { + switch ($innerEdge) { + case 'top': + case 'bottom': + // should pick up 'horizontal' border property if set + if (isset($pStyles['borders']['horizontal'])) { + $regionStyles['borders'][$innerEdge] = $pStyles['borders']['horizontal']; + } else { + unset($regionStyles['borders'][$innerEdge]); + } + break; + case 'left': + case 'right': + // should pick up 'vertical' border property if set + if (isset($pStyles['borders']['vertical'])) { + $regionStyles['borders'][$innerEdge] = $pStyles['borders']['vertical']; + } else { + unset($regionStyles['borders'][$innerEdge]); + } + break; + } + } - // apply region style to region by calling applyFromArray() in simple mode - $this->getActiveSheet()->getStyle($range)->applyFromArray($regionStyles, false); - } - } - return $this; - } + // apply region style to region by calling applyFromArray() in simple mode + $this->getActiveSheet()->getStyle($range)->applyFromArray($regionStyles, false); + } + } + return $this; + } - // SIMPLE MODE: + // SIMPLE MODE: - // Selection type, inspect - if (preg_match('/^[A-Z]+1:[A-Z]+1048576$/', $pRange)) { - $selectionType = 'COLUMN'; - } else if (preg_match('/^A[0-9]+:XFD[0-9]+$/', $pRange)) { - $selectionType = 'ROW'; - } else { - $selectionType = 'CELL'; - } + // Selection type, inspect + if (preg_match('/^[A-Z]+1:[A-Z]+1048576$/', $pRange)) { + $selectionType = 'COLUMN'; + } else if (preg_match('/^A[0-9]+:XFD[0-9]+$/', $pRange)) { + $selectionType = 'ROW'; + } else { + $selectionType = 'CELL'; + } - // First loop through columns, rows, or cells to find out which styles are affected by this operation - switch ($selectionType) { - case 'COLUMN': - $oldXfIndexes = array(); - for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { - $oldXfIndexes[$this->getActiveSheet()->getColumnDimensionByColumn($col)->getXfIndex()] = true; - } - break; + // First loop through columns, rows, or cells to find out which styles are affected by this operation + switch ($selectionType) { + case 'COLUMN': + $oldXfIndexes = array(); + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + $oldXfIndexes[$this->getActiveSheet()->getColumnDimensionByColumn($col)->getXfIndex()] = true; + } + break; - case 'ROW': - $oldXfIndexes = array(); - for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { - if ($this->getActiveSheet()->getRowDimension($row)->getXfIndex() == null) { - $oldXfIndexes[0] = true; // row without explicit style should be formatted based on default style - } else { - $oldXfIndexes[$this->getActiveSheet()->getRowDimension($row)->getXfIndex()] = true; - } - } - break; + case 'ROW': + $oldXfIndexes = array(); + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + if ($this->getActiveSheet()->getRowDimension($row)->getXfIndex() == null) { + $oldXfIndexes[0] = true; // row without explicit style should be formatted based on default style + } else { + $oldXfIndexes[$this->getActiveSheet()->getRowDimension($row)->getXfIndex()] = true; + } + } + break; - case 'CELL': - $oldXfIndexes = array(); - for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { - for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { - $oldXfIndexes[$this->getActiveSheet()->getCellByColumnAndRow($col, $row)->getXfIndex()] = true; - } - } - break; - } + case 'CELL': + $oldXfIndexes = array(); + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + $oldXfIndexes[$this->getActiveSheet()->getCellByColumnAndRow($col, $row)->getXfIndex()] = true; + } + } + break; + } - // clone each of the affected styles, apply the style arrray, and add the new styles to the workbook - $workbook = $this->getActiveSheet()->getParent(); - foreach ($oldXfIndexes as $oldXfIndex => $dummy) { - $style = $workbook->getCellXfByIndex($oldXfIndex); - $newStyle = clone $style; - $newStyle->applyFromArray($pStyles); + // clone each of the affected styles, apply the style array, and add the new styles to the workbook + $workbook = $this->getActiveSheet()->getParent(); + foreach ($oldXfIndexes as $oldXfIndex => $dummy) { + $style = $workbook->getCellXfByIndex($oldXfIndex); + $newStyle = clone $style; + $newStyle->applyFromArray($pStyles); - if ($existingStyle = $workbook->getCellXfByHashCode($newStyle->getHashCode())) { - // there is already such cell Xf in our collection - $newXfIndexes[$oldXfIndex] = $existingStyle->getIndex(); - } else { - // we don't have such a cell Xf, need to add - $workbook->addCellXf($newStyle); - $newXfIndexes[$oldXfIndex] = $newStyle->getIndex(); - } - } + if ($existingStyle = $workbook->getCellXfByHashCode($newStyle->getHashCode())) { + // there is already such cell Xf in our collection + $newXfIndexes[$oldXfIndex] = $existingStyle->getIndex(); + } else { + // we don't have such a cell Xf, need to add + $workbook->addCellXf($newStyle); + $newXfIndexes[$oldXfIndex] = $newStyle->getIndex(); + } + } - // Loop through columns, rows, or cells again and update the XF index - switch ($selectionType) { - case 'COLUMN': - for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { - $columnDimension = $this->getActiveSheet()->getColumnDimensionByColumn($col); - $oldXfIndex = $columnDimension->getXfIndex(); - $columnDimension->setXfIndex($newXfIndexes[$oldXfIndex]); - } - break; + // Loop through columns, rows, or cells again and update the XF index + switch ($selectionType) { + case 'COLUMN': + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + $columnDimension = $this->getActiveSheet()->getColumnDimensionByColumn($col); + $oldXfIndex = $columnDimension->getXfIndex(); + $columnDimension->setXfIndex($newXfIndexes[$oldXfIndex]); + } + break; - case 'ROW': - for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { - $rowDimension = $this->getActiveSheet()->getRowDimension($row); - $oldXfIndex = $rowDimension->getXfIndex() === null ? - 0 : $rowDimension->getXfIndex(); // row without explicit style should be formatted based on default style - $rowDimension->setXfIndex($newXfIndexes[$oldXfIndex]); - } - break; + case 'ROW': + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + $rowDimension = $this->getActiveSheet()->getRowDimension($row); + $oldXfIndex = $rowDimension->getXfIndex() === null ? + 0 : $rowDimension->getXfIndex(); // row without explicit style should be formatted based on default style + $rowDimension->setXfIndex($newXfIndexes[$oldXfIndex]); + } + break; - case 'CELL': - for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { - for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { - $cell = $this->getActiveSheet()->getCellByColumnAndRow($col, $row); - $oldXfIndex = $cell->getXfIndex(); - $cell->setXfIndex($newXfIndexes[$oldXfIndex]); - } - } - break; - } + case 'CELL': + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + $cell = $this->getActiveSheet()->getCellByColumnAndRow($col, $row); + $oldXfIndex = $cell->getXfIndex(); + $cell->setXfIndex($newXfIndexes[$oldXfIndex]); + } + } + break; + } - } else { - // not a supervisor, just apply the style array directly on style object - if (array_key_exists('fill', $pStyles)) { - $this->getFill()->applyFromArray($pStyles['fill']); - } - if (array_key_exists('font', $pStyles)) { - $this->getFont()->applyFromArray($pStyles['font']); - } - if (array_key_exists('borders', $pStyles)) { - $this->getBorders()->applyFromArray($pStyles['borders']); - } - if (array_key_exists('alignment', $pStyles)) { - $this->getAlignment()->applyFromArray($pStyles['alignment']); - } - if (array_key_exists('numberformat', $pStyles)) { - $this->getNumberFormat()->applyFromArray($pStyles['numberformat']); - } - if (array_key_exists('protection', $pStyles)) { - $this->getProtection()->applyFromArray($pStyles['protection']); - } - } - } else { - throw new Exception("Invalid style array passed."); - } - return $this; - } + } else { + // not a supervisor, just apply the style array directly on style object + if (array_key_exists('fill', $pStyles)) { + $this->getFill()->applyFromArray($pStyles['fill']); + } + if (array_key_exists('font', $pStyles)) { + $this->getFont()->applyFromArray($pStyles['font']); + } + if (array_key_exists('borders', $pStyles)) { + $this->getBorders()->applyFromArray($pStyles['borders']); + } + if (array_key_exists('alignment', $pStyles)) { + $this->getAlignment()->applyFromArray($pStyles['alignment']); + } + if (array_key_exists('numberformat', $pStyles)) { + $this->getNumberFormat()->applyFromArray($pStyles['numberformat']); + } + if (array_key_exists('protection', $pStyles)) { + $this->getProtection()->applyFromArray($pStyles['protection']); + } + if (array_key_exists('quotePrefix', $pStyles)) { + $this->_quotePrefix = $pStyles['quotePrefix']; + } + } + } else { + throw new PHPExcel_Exception("Invalid style array passed."); + } + return $this; + } /** * Get Fill * * @return PHPExcel_Style_Fill */ - public function getFill() { - return $this->_fill; + public function getFill() + { + return $this->_fill; } /** @@ -551,29 +507,31 @@ class PHPExcel_Style implements PHPExcel_IComparable * * @return PHPExcel_Style_Font */ - public function getFont() { - return $this->_font; + public function getFont() + { + return $this->_font; } - /** - * Set font - * - * @param PHPExcel_Style_Font $font - * @return PHPExcel_Style - */ - public function setFont(PHPExcel_Style_Font $font) - { - $this->_font = $font; - return $this; - } + /** + * Set font + * + * @param PHPExcel_Style_Font $font + * @return PHPExcel_Style + */ + public function setFont(PHPExcel_Style_Font $font) + { + $this->_font = $font; + return $this; + } /** * Get Borders * * @return PHPExcel_Style_Borders */ - public function getBorders() { - return $this->_borders; + public function getBorders() + { + return $this->_borders; } /** @@ -581,8 +539,9 @@ class PHPExcel_Style implements PHPExcel_IComparable * * @return PHPExcel_Style_Alignment */ - public function getAlignment() { - return $this->_alignment; + public function getAlignment() + { + return $this->_alignment; } /** @@ -590,8 +549,9 @@ class PHPExcel_Style implements PHPExcel_IComparable * * @return PHPExcel_Style_NumberFormat */ - public function getNumberFormat() { - return $this->_numberFormat; + public function getNumberFormat() + { + return $this->_numberFormat; } /** @@ -599,21 +559,23 @@ class PHPExcel_Style implements PHPExcel_IComparable * * @return PHPExcel_Style_Conditional[] */ - public function getConditionalStyles() { - return $this->getActiveSheet()->getConditionalStyles($this->getActiveCell()); + public function getConditionalStyles() + { + return $this->getActiveSheet()->getConditionalStyles($this->getActiveCell()); } /** * Set Conditional Styles. Only used on supervisor. * - * @param PHPExcel_Style_Conditional[] $pValue Array of condtional styles + * @param PHPExcel_Style_Conditional[] $pValue Array of condtional styles * @return PHPExcel_Style */ - public function setConditionalStyles($pValue = null) { - if (is_array($pValue)) { - $this->getActiveSheet()->setConditionalStyles($this->getSelectedCells(), $pValue); - } - return $this; + public function setConditionalStyles($pValue = null) + { + if (is_array($pValue)) { + $this->getActiveSheet()->setConditionalStyles($this->getSelectedCells(), $pValue); + } + return $this; } /** @@ -621,64 +583,86 @@ class PHPExcel_Style implements PHPExcel_IComparable * * @return PHPExcel_Style_Protection */ - public function getProtection() { - return $this->_protection; + public function getProtection() + { + return $this->_protection; } - /** - * Get hash code - * - * @return string Hash code - */ - public function getHashCode() { - $hashConditionals = ''; - foreach ($this->_conditionalStyles as $conditional) { - $hashConditionals .= $conditional->getHashCode(); - } - - return md5( - $this->_fill->getHashCode() - . $this->_font->getHashCode() - . $this->_borders->getHashCode() - . $this->_alignment->getHashCode() - . $this->_numberFormat->getHashCode() - . $hashConditionals - . $this->_protection->getHashCode() - . __CLASS__ - ); + /** + * Get quote prefix + * + * @return boolean + */ + public function getQuotePrefix() + { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getQuotePrefix(); + } + return $this->_quotePrefix; } - /** - * Get own index in style collection - * - * @return int - */ - public function getIndex() - { - return $this->_index; - } + /** + * Set quote prefix + * + * @param boolean $pValue + */ + public function setQuotePrefix($pValue) + { + if ($pValue == '') { + $pValue = false; + } + if ($this->_isSupervisor) { + $styleArray = array('quotePrefix' => $pValue); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_quotePrefix = (boolean) $pValue; + } + return $this; + } - /** - * Set own index in style collection - * - * @param int $pValue - */ - public function setIndex($pValue) - { - $this->_index = $pValue; - } + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() + { + $hashConditionals = ''; + foreach ($this->_conditionalStyles as $conditional) { + $hashConditionals .= $conditional->getHashCode(); + } + + return md5( + $this->_fill->getHashCode() + . $this->_font->getHashCode() + . $this->_borders->getHashCode() + . $this->_alignment->getHashCode() + . $this->_numberFormat->getHashCode() + . $hashConditionals + . $this->_protection->getHashCode() + . ($this->_quotePrefix ? 't' : 'f') + . __CLASS__ + ); + } + + /** + * Get own index in style collection + * + * @return int + */ + public function getIndex() + { + return $this->_index; + } + + /** + * Set own index in style collection + * + * @param int $pValue + */ + public function setIndex($pValue) + { + $this->_index = $pValue; + } - /** - * Implement PHP __clone to create a deep clone, not just a shallow copy. - */ - public function __clone() { - $vars = get_object_vars($this); - foreach ($vars as $key => $value) { - if ((is_object($value)) && ($key != '_parent')) { - $this->$key = clone $value; - } else { - $this->$key = $value; - } - } - } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Style/Alignment.php b/htdocs/includes/phpexcel/PHPExcel/Style/Alignment.php index 81ca387c5be..0d9e076799e 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Style/Alignment.php +++ b/htdocs/includes/phpexcel/PHPExcel/Style/Alignment.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,9 +31,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Style_Alignment implements PHPExcel_IComparable +class PHPExcel_Style_Alignment extends PHPExcel_Style_Supervisor implements PHPExcel_IComparable { /* Horizontal alignment styles */ const HORIZONTAL_GENERAL = 'general'; @@ -42,75 +42,57 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable const HORIZONTAL_CENTER = 'center'; const HORIZONTAL_CENTER_CONTINUOUS = 'centerContinuous'; const HORIZONTAL_JUSTIFY = 'justify'; + const HORIZONTAL_FILL = 'fill'; + const HORIZONTAL_DISTRIBUTED = 'distributed'; // Excel2007 only /* Vertical alignment styles */ const VERTICAL_BOTTOM = 'bottom'; const VERTICAL_TOP = 'top'; const VERTICAL_CENTER = 'center'; const VERTICAL_JUSTIFY = 'justify'; + const VERTICAL_DISTRIBUTED = 'distributed'; // Excel2007 only /** * Horizontal * * @var string */ - private $_horizontal = PHPExcel_Style_Alignment::HORIZONTAL_GENERAL; + protected $_horizontal = PHPExcel_Style_Alignment::HORIZONTAL_GENERAL; /** * Vertical * * @var string */ - private $_vertical = PHPExcel_Style_Alignment::VERTICAL_BOTTOM; + protected $_vertical = PHPExcel_Style_Alignment::VERTICAL_BOTTOM; /** * Text rotation * * @var int */ - private $_textRotation = 0; + protected $_textRotation = 0; /** * Wrap text * * @var boolean */ - private $_wrapText = false; + protected $_wrapText = FALSE; /** * Shrink to fit * * @var boolean */ - private $_shrinkToFit = false; + protected $_shrinkToFit = FALSE; /** * Indent - only possible with horizontal alignment left and right * * @var int */ - private $_indent = 0; - - /** - * Parent Borders - * - * @var _parentPropertyName string - */ - private $_parentPropertyName; - - /** - * Supervisor? - * - * @var boolean - */ - private $_isSupervisor; - - /** - * Parent. Only used for supervisor - * - * @var PHPExcel_Style - */ - private $_parent; + protected $_indent = 0; /** * Create a new PHPExcel_Style_Alignment @@ -122,10 +104,10 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable * Leave this value at default unless you understand exactly what * its ramifications are */ - public function __construct($isSupervisor = false, $isConditional = false) + public function __construct($isSupervisor = FALSE, $isConditional = FALSE) { // Supervisor? - $this->_isSupervisor = $isSupervisor; + parent::__construct($isSupervisor); if ($isConditional) { $this->_horizontal = NULL; @@ -134,28 +116,6 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable } } - /** - * Bind parent. Only used for supervisor - * - * @param PHPExcel $parent - * @return PHPExcel_Style_Alignment - */ - public function bindParent($parent) - { - $this->_parent = $parent; - return $this; - } - - /** - * Is this a supervisor or a real style component? - * - * @return boolean - */ - public function getIsSupervisor() - { - return $this->_isSupervisor; - } - /** * Get the shared style component for the currently active cell in currently active sheet. * Only used for style supervisor @@ -167,38 +127,6 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable return $this->_parent->getSharedComponent()->getAlignment(); } - /** - * Get the currently active sheet. Only used for supervisor - * - * @return PHPExcel_Worksheet - */ - public function getActiveSheet() - { - return $this->_parent->getActiveSheet(); - } - - /** - * Get the currently active cell coordinate in currently active sheet. - * Only used for supervisor - * - * @return string E.g. 'A1' - */ - public function getSelectedCells() - { - return $this->getActiveSheet()->getSelectedCells(); - } - - /** - * Get the currently active cell coordinate in currently active sheet. - * Only used for supervisor - * - * @return string E.g. 'A1' - */ - public function getActiveCell() - { - return $this->getActiveSheet()->getActiveCell(); - } - /** * Build style array from subcomponents * @@ -219,41 +147,42 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable * 'horizontal' => PHPExcel_Style_Alignment::HORIZONTAL_CENTER, * 'vertical' => PHPExcel_Style_Alignment::VERTICAL_CENTER, * 'rotation' => 0, - * 'wrap' => true + * 'wrap' => TRUE * ) * ); * * * @param array $pStyles Array containing style information - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Style_Alignment */ - public function applyFromArray($pStyles = null) { + public function applyFromArray($pStyles = NULL) { if (is_array($pStyles)) { if ($this->_isSupervisor) { - $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + $this->getActiveSheet()->getStyle($this->getSelectedCells()) + ->applyFromArray($this->getStyleArray($pStyles)); } else { - if (array_key_exists('horizontal', $pStyles)) { + if (isset($pStyles['horizontal'])) { $this->setHorizontal($pStyles['horizontal']); } - if (array_key_exists('vertical', $pStyles)) { + if (isset($pStyles['vertical'])) { $this->setVertical($pStyles['vertical']); } - if (array_key_exists('rotation', $pStyles)) { + if (isset($pStyles['rotation'])) { $this->setTextRotation($pStyles['rotation']); } - if (array_key_exists('wrap', $pStyles)) { + if (isset($pStyles['wrap'])) { $this->setWrapText($pStyles['wrap']); } - if (array_key_exists('shrinkToFit', $pStyles)) { + if (isset($pStyles['shrinkToFit'])) { $this->setShrinkToFit($pStyles['shrinkToFit']); } - if (array_key_exists('indent', $pStyles)) { + if (isset($pStyles['indent'])) { $this->setIndent($pStyles['indent']); } } } else { - throw new Exception("Invalid style array passed."); + throw new PHPExcel_Exception("Invalid style array passed."); } return $this; } @@ -339,7 +268,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable * Set TextRotation * * @param int $pValue - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Style_Alignment */ public function setTextRotation($pValue = 0) { @@ -357,7 +286,7 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable $this->_textRotation = $pValue; } } else { - throw new Exception("Text rotation should be a value between -90 and 90."); + throw new PHPExcel_Exception("Text rotation should be a value between -90 and 90."); } return $this; @@ -381,9 +310,9 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable * @param boolean $pValue * @return PHPExcel_Style_Alignment */ - public function setWrapText($pValue = false) { + public function setWrapText($pValue = FALSE) { if ($pValue == '') { - $pValue = false; + $pValue = FALSE; } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('wrap' => $pValue)); @@ -412,9 +341,9 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable * @param boolean $pValue * @return PHPExcel_Style_Alignment */ - public function setShrinkToFit($pValue = false) { + public function setShrinkToFit($pValue = FALSE) { if ($pValue == '') { - $pValue = false; + $pValue = FALSE; } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('shrinkToFit' => $pValue)); @@ -445,7 +374,9 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable */ public function setIndent($pValue = 0) { if ($pValue > 0) { - if ($this->getHorizontal() != self::HORIZONTAL_GENERAL && $this->getHorizontal() != self::HORIZONTAL_LEFT && $this->getHorizontal() != self::HORIZONTAL_RIGHT) { + if ($this->getHorizontal() != self::HORIZONTAL_GENERAL && + $this->getHorizontal() != self::HORIZONTAL_LEFT && + $this->getHorizontal() != self::HORIZONTAL_RIGHT) { $pValue = 0; // indent not supported } } @@ -478,17 +409,4 @@ class PHPExcel_Style_Alignment implements PHPExcel_IComparable ); } - /** - * Implement PHP __clone to create a deep clone, not just a shallow copy. - */ - public function __clone() { - $vars = get_object_vars($this); - foreach ($vars as $key => $value) { - if ((is_object($value)) && ($key != '_parent')) { - $this->$key = clone $value; - } else { - $this->$key = $value; - } - } - } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Style/Border.php b/htdocs/includes/phpexcel/PHPExcel/Style/Border.php index 6f8767fb277..3b7eba9af9c 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Style/Border.php +++ b/htdocs/includes/phpexcel/PHPExcel/Style/Border.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,9 +31,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Style_Border implements PHPExcel_IComparable +class PHPExcel_Style_Border extends PHPExcel_Style_Supervisor implements PHPExcel_IComparable { /* Border style */ const BORDER_NONE = 'none'; @@ -56,35 +56,21 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable * * @var string */ - private $_borderStyle = PHPExcel_Style_Border::BORDER_NONE; + protected $_borderStyle = PHPExcel_Style_Border::BORDER_NONE; /** * Border color * * @var PHPExcel_Style_Color */ - private $_color; - - /** - * Supervisor? - * - * @var boolean - */ - private $_isSupervisor; - - /** - * Parent. Only used for supervisor - * - * @var PHPExcel_Style_Borders - */ - private $_parent; + protected $_color; /** * Parent property name * * @var string */ - private $_parentPropertyName; + protected $_parentPropertyName; /** * Create a new PHPExcel_Style_Border @@ -96,10 +82,10 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable * Leave this value at default unless you understand exactly what * its ramifications are */ - public function __construct($isSupervisor = false, $isConditional = false) + public function __construct($isSupervisor = FALSE, $isConditional = FALSE) { // Supervisor? - $this->_isSupervisor = $isSupervisor; + parent::__construct($isSupervisor); // Initialise values $this->_color = new PHPExcel_Style_Color(PHPExcel_Style_Color::COLOR_BLACK, $isSupervisor); @@ -117,29 +103,19 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable * @param string $parentPropertyName * @return PHPExcel_Style_Border */ - public function bindParent($parent, $parentPropertyName) + public function bindParent($parent, $parentPropertyName=NULL) { $this->_parent = $parent; $this->_parentPropertyName = $parentPropertyName; return $this; } - /** - * Is this a supervisor or a real style component? - * - * @return boolean - */ - public function getIsSupervisor() - { - return $this->_isSupervisor; - } - /** * Get the shared style component for the currently active cell in currently active sheet. * Only used for style supervisor * * @return PHPExcel_Style_Border - * @throws Exception + * @throws PHPExcel_Exception */ public function getSharedComponent() { @@ -149,64 +125,22 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable case '_inside': case '_outline': case '_vertical': - throw new Exception('Cannot get shared component for a pseudo-border.'); + throw new PHPExcel_Exception('Cannot get shared component for a pseudo-border.'); break; - case '_bottom': - return $this->_parent->getSharedComponent()->getBottom(); - break; - + return $this->_parent->getSharedComponent()->getBottom(); break; case '_diagonal': - return $this->_parent->getSharedComponent()->getDiagonal(); - break; - + return $this->_parent->getSharedComponent()->getDiagonal(); break; case '_left': - return $this->_parent->getSharedComponent()->getLeft(); - break; - + return $this->_parent->getSharedComponent()->getLeft(); break; case '_right': - return $this->_parent->getSharedComponent()->getRight(); - break; - + return $this->_parent->getSharedComponent()->getRight(); break; case '_top': - return $this->_parent->getSharedComponent()->getTop(); - break; + return $this->_parent->getSharedComponent()->getTop(); break; } } - /** - * Get the currently active sheet. Only used for supervisor - * - * @return PHPExcel_Worksheet - */ - public function getActiveSheet() - { - return $this->_parent->getActiveSheet(); - } - - /** - * Get the currently active cell coordinate in currently active sheet. - * Only used for supervisor - * - * @return string E.g. 'A1' - */ - public function getSelectedCells() - { - return $this->getActiveSheet()->getSelectedCells(); - } - - /** - * Get the currently active cell coordinate in currently active sheet. - * Only used for supervisor - * - * @return string E.g. 'A1' - */ - public function getActiveCell() - { - return $this->getActiveSheet()->getActiveCell(); - } - /** * Build style array from subcomponents * @@ -217,44 +151,25 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable { switch ($this->_parentPropertyName) { case '_allBorders': - $key = 'allborders'; - break; - + $key = 'allborders'; break; case '_bottom': - $key = 'bottom'; - break; - + $key = 'bottom'; break; case '_diagonal': - $key = 'diagonal'; - break; - + $key = 'diagonal'; break; case '_horizontal': - $key = 'horizontal'; - break; - + $key = 'horizontal'; break; case '_inside': - $key = 'inside'; - break; - + $key = 'inside'; break; case '_left': - $key = 'left'; - break; - + $key = 'left'; break; case '_outline': - $key = 'outline'; - break; - + $key = 'outline'; break; case '_right': - $key = 'right'; - break; - + $key = 'right'; break; case '_top': - $key = 'top'; - break; - + $key = 'top'; break; case '_vertical': - $key = 'vertical'; - break; + $key = 'vertical'; break; } return $this->_parent->getStyleArray(array($key => $array)); } @@ -274,7 +189,7 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable * * * @param array $pStyles Array containing style information - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Style_Border */ public function applyFromArray($pStyles = null) { @@ -282,15 +197,15 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable if ($this->_isSupervisor) { $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); } else { - if (array_key_exists('style', $pStyles)) { + if (isset($pStyles['style'])) { $this->setBorderStyle($pStyles['style']); } - if (array_key_exists('color', $pStyles)) { + if (isset($pStyles['color'])) { $this->getColor()->applyFromArray($pStyles['color']); } } } else { - throw new Exception("Invalid style array passed."); + throw new PHPExcel_Exception("Invalid style array passed."); } return $this; } @@ -310,13 +225,17 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable /** * Set Border style * - * @param string $pValue + * @param string|boolean $pValue + * When passing a boolean, FALSE equates PHPExcel_Style_Border::BORDER_NONE + * and TRUE to PHPExcel_Style_Border::BORDER_MEDIUM * @return PHPExcel_Style_Border */ public function setBorderStyle($pValue = PHPExcel_Style_Border::BORDER_NONE) { - if ($pValue == '') { + if (empty($pValue)) { $pValue = PHPExcel_Style_Border::BORDER_NONE; + } elseif(is_bool($pValue) && $pValue) { + $pValue = PHPExcel_Style_Border::BORDER_MEDIUM; } if ($this->_isSupervisor) { $styleArray = $this->getStyleArray(array('style' => $pValue)); @@ -340,7 +259,7 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable * Set Border Color * * @param PHPExcel_Style_Color $pValue - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Style_Border */ public function setColor(PHPExcel_Style_Color $pValue = null) { @@ -372,17 +291,4 @@ class PHPExcel_Style_Border implements PHPExcel_IComparable ); } - /** - * Implement PHP __clone to create a deep clone, not just a shallow copy. - */ - public function __clone() { - $vars = get_object_vars($this); - foreach ($vars as $key => $value) { - if ((is_object($value)) && ($key != '_parent')) { - $this->$key = clone $value; - } else { - $this->$key = $value; - } - } - } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Style/Borders.php b/htdocs/includes/phpexcel/PHPExcel/Style/Borders.php index d8a3196e3af..b90838a60dc 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Style/Borders.php +++ b/htdocs/includes/phpexcel/PHPExcel/Style/Borders.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,9 +31,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Style_Borders implements PHPExcel_IComparable +class PHPExcel_Style_Borders extends PHPExcel_Style_Supervisor implements PHPExcel_IComparable { /* Diagonal directions */ const DIAGONAL_NONE = 0; @@ -46,98 +46,77 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable * * @var PHPExcel_Style_Border */ - private $_left; + protected $_left; /** * Right * * @var PHPExcel_Style_Border */ - private $_right; + protected $_right; /** * Top * * @var PHPExcel_Style_Border */ - private $_top; + protected $_top; /** * Bottom * * @var PHPExcel_Style_Border */ - private $_bottom; + protected $_bottom; /** * Diagonal * * @var PHPExcel_Style_Border */ - private $_diagonal; + protected $_diagonal; /** * DiagonalDirection * * @var int */ - private $_diagonalDirection; + protected $_diagonalDirection; /** * All borders psedo-border. Only applies to supervisor. * * @var PHPExcel_Style_Border */ - private $_allBorders; + protected $_allBorders; /** * Outline psedo-border. Only applies to supervisor. * * @var PHPExcel_Style_Border */ - private $_outline; + protected $_outline; /** * Inside psedo-border. Only applies to supervisor. * * @var PHPExcel_Style_Border */ - private $_inside; + protected $_inside; /** * Vertical pseudo-border. Only applies to supervisor. * * @var PHPExcel_Style_Border */ - private $_vertical; + protected $_vertical; /** * Horizontal pseudo-border. Only applies to supervisor. * * @var PHPExcel_Style_Border */ - private $_horizontal; - - /** - * Parent Borders - * - * @var _parentPropertyName string - */ - private $_parentPropertyName; - - /** - * Supervisor? - * - * @var boolean - */ - private $_isSupervisor; - - /** - * Parent. Only used for supervisor - * - * @var PHPExcel_Style - */ - private $_parent; + protected $_horizontal; /** * Create a new PHPExcel_Style_Borders @@ -149,10 +128,10 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable * Leave this value at default unless you understand exactly what * its ramifications are */ - public function __construct($isSupervisor = false, $isConditional = false) + public function __construct($isSupervisor = FALSE, $isConditional = FALSE) { // Supervisor? - $this->_isSupervisor = $isSupervisor; + parent::__construct($isSupervisor); // Initialise values $this->_left = new PHPExcel_Style_Border($isSupervisor, $isConditional); @@ -165,11 +144,11 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable // Specially for supervisor if ($isSupervisor) { // Initialize pseudo-borders - $this->_allBorders = new PHPExcel_Style_Border(true); - $this->_outline = new PHPExcel_Style_Border(true); - $this->_inside = new PHPExcel_Style_Border(true); - $this->_vertical = new PHPExcel_Style_Border(true); - $this->_horizontal = new PHPExcel_Style_Border(true); + $this->_allBorders = new PHPExcel_Style_Border(TRUE); + $this->_outline = new PHPExcel_Style_Border(TRUE); + $this->_inside = new PHPExcel_Style_Border(TRUE); + $this->_vertical = new PHPExcel_Style_Border(TRUE); + $this->_horizontal = new PHPExcel_Style_Border(TRUE); // bind parent if we are a supervisor $this->_left->bindParent($this, '_left'); @@ -185,28 +164,6 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable } } - /** - * Bind parent. Only used for supervisor - * - * @param PHPExcel_Style $parent - * @return PHPExcel_Style_Borders - */ - public function bindParent($parent) - { - $this->_parent = $parent; - return $this; - } - - /** - * Is this a supervisor or a real style component? - * - * @return boolean - */ - public function getIsSupervisor() - { - return $this->_isSupervisor; - } - /** * Get the shared style component for the currently active cell in currently active sheet. * Only used for style supervisor @@ -218,38 +175,6 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable return $this->_parent->getSharedComponent()->getBorders(); } - /** - * Get the currently active sheet. Only used for supervisor - * - * @return PHPExcel_Worksheet - */ - public function getActiveSheet() - { - return $this->_parent->getActiveSheet(); - } - - /** - * Get the currently active cell coordinate in currently active sheet. - * Only used for supervisor - * - * @return string E.g. 'A1' - */ - public function getSelectedCells() - { - return $this->getActiveSheet()->getSelectedCells(); - } - - /** - * Get the currently active cell coordinate in currently active sheet. - * Only used for supervisor - * - * @return string E.g. 'A1' - */ - public function getActiveCell() - { - return $this->getActiveSheet()->getActiveCell(); - } - /** * Build style array from subcomponents * @@ -296,7 +221,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable * * * @param array $pStyles Array containing style information - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Style_Borders */ public function applyFromArray($pStyles = null) { @@ -330,7 +255,7 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable } } } else { - throw new Exception("Invalid style array passed."); + throw new PHPExcel_Exception("Invalid style array passed."); } return $this; } @@ -384,11 +309,11 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable * Get AllBorders (pseudo-border). Only applies to supervisor. * * @return PHPExcel_Style_Border - * @throws Exception + * @throws PHPExcel_Exception */ public function getAllBorders() { if (!$this->_isSupervisor) { - throw new Exception('Can only get pseudo-border for supervisor.'); + throw new PHPExcel_Exception('Can only get pseudo-border for supervisor.'); } return $this->_allBorders; } @@ -397,11 +322,11 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable * Get Outline (pseudo-border). Only applies to supervisor. * * @return boolean - * @throws Exception + * @throws PHPExcel_Exception */ public function getOutline() { if (!$this->_isSupervisor) { - throw new Exception('Can only get pseudo-border for supervisor.'); + throw new PHPExcel_Exception('Can only get pseudo-border for supervisor.'); } return $this->_outline; } @@ -410,11 +335,11 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable * Get Inside (pseudo-border). Only applies to supervisor. * * @return boolean - * @throws Exception + * @throws PHPExcel_Exception */ public function getInside() { if (!$this->_isSupervisor) { - throw new Exception('Can only get pseudo-border for supervisor.'); + throw new PHPExcel_Exception('Can only get pseudo-border for supervisor.'); } return $this->_inside; } @@ -423,11 +348,11 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable * Get Vertical (pseudo-border). Only applies to supervisor. * * @return PHPExcel_Style_Border - * @throws Exception + * @throws PHPExcel_Exception */ public function getVertical() { if (!$this->_isSupervisor) { - throw new Exception('Can only get pseudo-border for supervisor.'); + throw new PHPExcel_Exception('Can only get pseudo-border for supervisor.'); } return $this->_vertical; } @@ -436,11 +361,11 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable * Get Horizontal (pseudo-border). Only applies to supervisor. * * @return PHPExcel_Style_Border - * @throws Exception + * @throws PHPExcel_Exception */ public function getHorizontal() { if (!$this->_isSupervisor) { - throw new Exception('Can only get pseudo-border for supervisor.'); + throw new PHPExcel_Exception('Can only get pseudo-border for supervisor.'); } return $this->_horizontal; } @@ -496,17 +421,4 @@ class PHPExcel_Style_Borders implements PHPExcel_IComparable ); } - /** - * Implement PHP __clone to create a deep clone, not just a shallow copy. - */ - public function __clone() { - $vars = get_object_vars($this); - foreach ($vars as $key => $value) { - if ((is_object($value)) && ($key != '_parent')) { - $this->$key = clone $value; - } else { - $this->$key = $value; - } - } - } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Style/Color.php b/htdocs/includes/phpexcel/PHPExcel/Style/Color.php index 1c0f3f6808e..4d34504f397 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Style/Color.php +++ b/htdocs/includes/phpexcel/PHPExcel/Style/Color.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,9 +31,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Style_Color implements PHPExcel_IComparable +class PHPExcel_Style_Color extends PHPExcel_Style_Supervisor implements PHPExcel_IComparable { /* Colors */ const COLOR_BLACK = 'FF000000'; @@ -52,35 +52,21 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable * * @var array */ - private static $_indexedColors; + protected static $_indexedColors; /** * ARGB - Alpha RGB * * @var string */ - private $_argb = NULL; - - /** - * Supervisor? - * - * @var boolean - */ - private $_isSupervisor; - - /** - * Parent. Only used for supervisor - * - * @var mixed - */ - private $_parent; + protected $_argb = NULL; /** * Parent property name * * @var string */ - private $_parentPropertyName; + protected $_parentPropertyName; /** @@ -94,10 +80,10 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable * Leave this value at default unless you understand exactly what * its ramifications are */ - public function __construct($pARGB = PHPExcel_Style_Color::COLOR_BLACK, $isSupervisor = false, $isConditional = false) + public function __construct($pARGB = PHPExcel_Style_Color::COLOR_BLACK, $isSupervisor = FALSE, $isConditional = FALSE) { // Supervisor? - $this->_isSupervisor = $isSupervisor; + parent::__construct($isSupervisor); // Initialise values if (!$isConditional) { @@ -112,23 +98,13 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable * @param string $parentPropertyName * @return PHPExcel_Style_Color */ - public function bindParent($parent, $parentPropertyName) + public function bindParent($parent, $parentPropertyName=NULL) { $this->_parent = $parent; $this->_parentPropertyName = $parentPropertyName; return $this; } - /** - * Is this a supervisor or a real style component? - * - * @return boolean - */ - public function getIsSupervisor() - { - return $this->_isSupervisor; - } - /** * Get the shared style component for the currently active cell in currently active sheet. * Only used for style supervisor @@ -147,38 +123,6 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable } } - /** - * Get the currently active sheet. Only used for supervisor - * - * @return PHPExcel_Worksheet - */ - public function getActiveSheet() - { - return $this->_parent->getActiveSheet(); - } - - /** - * Get the currently active cell coordinate in currently active sheet. - * Only used for supervisor - * - * @return string E.g. 'A1' - */ - public function getSelectedCells() - { - return $this->getActiveSheet()->getSelectedCells(); - } - - /** - * Get the currently active cell coordinate in currently active sheet. - * Only used for supervisor - * - * @return string E.g. 'A1' - */ - public function getActiveCell() - { - return $this->getActiveSheet()->getActiveCell(); - } - /** * Build style array from subcomponents * @@ -210,7 +154,7 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable * * * @param array $pStyles Array containing style information - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Style_Color */ public function applyFromArray($pStyles = NULL) { @@ -226,7 +170,7 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable } } } else { - throw new Exception("Invalid style array passed."); + throw new PHPExcel_Exception("Invalid style array passed."); } return $this; } @@ -319,11 +263,7 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable * @return string The red colour component */ public static function getRed($RGB,$hex=TRUE) { - if (strlen($RGB) == 8) { - return self::_getColourComponent($RGB, 2, $hex); - } elseif (strlen($RGB) == 6) { - return self::_getColourComponent($RGB, 0, $hex); - } + return self::_getColourComponent($RGB, strlen($RGB) - 6, $hex); } /** @@ -335,11 +275,7 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable * @return string The green colour component */ public static function getGreen($RGB,$hex=TRUE) { - if (strlen($RGB) == 8) { - return self::_getColourComponent($RGB, 4, $hex); - } elseif (strlen($RGB) == 6) { - return self::_getColourComponent($RGB, 2, $hex); - } + return self::_getColourComponent($RGB, strlen($RGB) - 4, $hex); } /** @@ -351,11 +287,7 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable * @return string The blue colour component */ public static function getBlue($RGB,$hex=TRUE) { - if (strlen($RGB) == 8) { - return self::_getColourComponent($RGB, 6, $hex); - } elseif (strlen($RGB) == 6) { - return self::_getColourComponent($RGB, 4, $hex); - } + return self::_getColourComponent($RGB, strlen($RGB) - 2, $hex); } /** @@ -494,17 +426,4 @@ class PHPExcel_Style_Color implements PHPExcel_IComparable ); } - /** - * Implement PHP __clone to create a deep clone, not just a shallow copy. - */ - public function __clone() { - $vars = get_object_vars($this); - foreach ($vars as $key => $value) { - if ((is_object($value)) && ($key != '_parent')) { - $this->$key = clone $value; - } else { - $this->$key = $value; - } - } - } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Style/Conditional.php b/htdocs/includes/phpexcel/PHPExcel/Style/Conditional.php index d9f7dd4cf5f..ffd7a9f9b57 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Style/Conditional.php +++ b/htdocs/includes/phpexcel/PHPExcel/Style/Conditional.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Style_Conditional implements PHPExcel_IComparable { @@ -238,7 +238,7 @@ class PHPExcel_Style_Conditional implements PHPExcel_IComparable * Set Style * * @param PHPExcel_Style $pValue - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Style_Conditional */ public function setStyle(PHPExcel_Style $pValue = null) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Style/Fill.php b/htdocs/includes/phpexcel/PHPExcel/Style/Fill.php index afede653c74..1b4d0ad34d1 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Style/Fill.php +++ b/htdocs/includes/phpexcel/PHPExcel/Style/Fill.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,9 +31,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Style_Fill implements PHPExcel_IComparable +class PHPExcel_Style_Fill extends PHPExcel_Style_Supervisor implements PHPExcel_IComparable { /* Fill types */ const FILL_NONE = 'none'; @@ -63,49 +63,28 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable * * @var string */ - private $_fillType = PHPExcel_Style_Fill::FILL_NONE; + protected $_fillType = PHPExcel_Style_Fill::FILL_NONE; /** * Rotation * * @var double */ - private $_rotation = 0; + protected $_rotation = 0; /** * Start color * * @var PHPExcel_Style_Color */ - private $_startColor; + protected $_startColor; /** * End color * * @var PHPExcel_Style_Color */ - private $_endColor; - - /** - * Parent Borders - * - * @var _parentPropertyName string - */ - private $_parentPropertyName; - - /** - * Supervisor? - * - * @var boolean - */ - private $_isSupervisor; - - /** - * Parent. Only used for supervisor - * - * @var PHPExcel_Style - */ - private $_parent; + protected $_endColor; /** * Create a new PHPExcel_Style_Fill @@ -117,10 +96,10 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable * Leave this value at default unless you understand exactly what * its ramifications are */ - public function __construct($isSupervisor = false, $isConditional = false) + public function __construct($isSupervisor = FALSE, $isConditional = FALSE) { // Supervisor? - $this->_isSupervisor = $isSupervisor; + parent::__construct($isSupervisor); // Initialise values if ($isConditional) { @@ -136,28 +115,6 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable } } - /** - * Bind parent. Only used for supervisor - * - * @param PHPExcel_Style $parent - * @return PHPExcel_Style_Fill - */ - public function bindParent($parent) - { - $this->_parent = $parent; - return $this; - } - - /** - * Is this a supervisor or a real style component? - * - * @return boolean - */ - public function getIsSupervisor() - { - return $this->_isSupervisor; - } - /** * Get the shared style component for the currently active cell in currently active sheet. * Only used for style supervisor @@ -169,38 +126,6 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable return $this->_parent->getSharedComponent()->getFill(); } - /** - * Get the currently active sheet. Only used for supervisor - * - * @return PHPExcel_Worksheet - */ - public function getActiveSheet() - { - return $this->_parent->getActiveSheet(); - } - - /** - * Get the currently active cell coordinate in currently active sheet. - * Only used for supervisor - * - * @return string E.g. 'A1' - */ - public function getSelectedCells() - { - return $this->getActiveSheet()->getSelectedCells(); - } - - /** - * Get the currently active cell coordinate in currently active sheet. - * Only used for supervisor - * - * @return string E.g. 'A1' - */ - public function getActiveCell() - { - return $this->getActiveSheet()->getActiveCell(); - } - /** * Build style array from subcomponents * @@ -231,7 +156,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable * * * @param array $pStyles Array containing style information - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Style_Fill */ public function applyFromArray($pStyles = null) { @@ -256,7 +181,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable } } } else { - throw new Exception("Invalid style array passed."); + throw new PHPExcel_Exception("Invalid style array passed."); } return $this; } @@ -330,7 +255,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable * Set Start Color * * @param PHPExcel_Style_Color $pValue - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Style_Fill */ public function setStartColor(PHPExcel_Style_Color $pValue = null) { @@ -359,7 +284,7 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable * Set End Color * * @param PHPExcel_Style_Color $pValue - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Style_Fill */ public function setEndColor(PHPExcel_Style_Color $pValue = null) { @@ -393,17 +318,4 @@ class PHPExcel_Style_Fill implements PHPExcel_IComparable ); } - /** - * Implement PHP __clone to create a deep clone, not just a shallow copy. - */ - public function __clone() { - $vars = get_object_vars($this); - foreach ($vars as $key => $value) { - if ((is_object($value)) && ($key != '_parent')) { - $this->$key = clone $value; - } else { - $this->$key = $value; - } - } - } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Style/Font.php b/htdocs/includes/phpexcel/PHPExcel/Style/Font.php index 59ae7730956..e89488c2c1c 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Style/Font.php +++ b/htdocs/includes/phpexcel/PHPExcel/Style/Font.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,9 +31,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Style_Font implements PHPExcel_IComparable +class PHPExcel_Style_Font extends PHPExcel_Style_Supervisor implements PHPExcel_IComparable { /* Underline types */ const UNDERLINE_NONE = 'none'; @@ -47,84 +47,63 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable * * @var string */ - private $_name = 'Calibri'; + protected $_name = 'Calibri'; /** * Font Size * * @var float */ - private $_size = 11; + protected $_size = 11; /** * Bold * * @var boolean */ - private $_bold = false; + protected $_bold = FALSE; /** * Italic * * @var boolean */ - private $_italic = false; + protected $_italic = FALSE; /** * Superscript * * @var boolean */ - private $_superScript = false; + protected $_superScript = FALSE; /** * Subscript * * @var boolean */ - private $_subScript = false; + protected $_subScript = FALSE; /** * Underline * * @var string */ - private $_underline = self::UNDERLINE_NONE; + protected $_underline = self::UNDERLINE_NONE; /** * Strikethrough * * @var boolean */ - private $_strikethrough = false; + protected $_strikethrough = FALSE; /** * Foreground color * * @var PHPExcel_Style_Color */ - private $_color; - - /** - * Parent Borders - * - * @var _parentPropertyName string - */ - private $_parentPropertyName; - - /** - * Supervisor? - * - * @var boolean - */ - private $_isSupervisor; - - /** - * Parent. Only used for supervisor - * - * @var PHPExcel_Style - */ - private $_parent; + protected $_color; /** * Create a new PHPExcel_Style_Font @@ -136,10 +115,10 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable * Leave this value at default unless you understand exactly what * its ramifications are */ - public function __construct($isSupervisor = false, $isConditional = false) + public function __construct($isSupervisor = FALSE, $isConditional = FALSE) { // Supervisor? - $this->_isSupervisor = $isSupervisor; + parent::__construct($isSupervisor); // Initialise values if ($isConditional) { @@ -161,27 +140,6 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } } - /** - * Bind parent. Only used for supervisor - * - * @param PHPExcel_Style $parent - * @return PHPExcel_Style_Font - */ - public function bindParent($parent) - { - $this->_parent = $parent; - } - - /** - * Is this a supervisor or a real style component? - * - * @return boolean - */ - public function getIsSupervisor() - { - return $this->_isSupervisor; - } - /** * Get the shared style component for the currently active cell in currently active sheet. * Only used for style supervisor @@ -193,38 +151,6 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable return $this->_parent->getSharedComponent()->getFont(); } - /** - * Get the currently active sheet. Only used for supervisor - * - * @return PHPExcel_Worksheet - */ - public function getActiveSheet() - { - return $this->_parent->getActiveSheet(); - } - - /** - * Get the currently active cell coordinate in currently active sheet. - * Only used for supervisor - * - * @return string E.g. 'A1' - */ - public function getSelectedCells() - { - return $this->getActiveSheet()->getSelectedCells(); - } - - /** - * Get the currently active cell coordinate in currently active sheet. - * Only used for supervisor - * - * @return string E.g. 'A1' - */ - public function getActiveCell() - { - return $this->getActiveSheet()->getActiveCell(); - } - /** * Build style array from subcomponents * @@ -242,12 +168,12 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable * * $objPHPExcel->getActiveSheet()->getStyle('B2')->getFont()->applyFromArray( * array( - * 'name' => 'Arial', - * 'bold' => true, - * 'italic' => false, + * 'name' => 'Arial', + * 'bold' => TRUE, + * 'italic' => FALSE, * 'underline' => PHPExcel_Style_Font::UNDERLINE_DOUBLE, - * 'strike' => false, - * 'color' => array( + * 'strike' => FALSE, + * 'color' => array( * 'rgb' => '808080' * ) * ) @@ -255,7 +181,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable * * * @param array $pStyles Array containing style information - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Style_Font */ public function applyFromArray($pStyles = null) { @@ -292,7 +218,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable } } } else { - throw new Exception("Invalid style array passed."); + throw new PHPExcel_Exception("Invalid style array passed."); } return $this; } @@ -501,7 +427,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable * Set Underline * * @param string|boolean $pValue PHPExcel_Style_Font underline type - * If a boolean is passed, then true equates to UNDERLINE_SINGLE, + * If a boolean is passed, then TRUE equates to UNDERLINE_SINGLE, * false equates to UNDERLINE_NONE * @return PHPExcel_Style_Font */ @@ -520,27 +446,6 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable return $this; } - /** - * Get Striketrough - * - * @deprecated Use getStrikethrough() instead. - * @return boolean - */ - public function getStriketrough() { - return $this->getStrikethrough(); - } - - /** - * Set Striketrough - * - * @deprecated Use setStrikethrough() instead. - * @param boolean $pValue - * @return PHPExcel_Style_Font - */ - public function setStriketrough($pValue = false) { - return $this->setStrikethrough($pValue); - } - /** * Get Strikethrough * @@ -585,7 +490,7 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable * Set Color * * @param PHPExcel_Style_Color $pValue - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Style_Font */ public function setColor(PHPExcel_Style_Color $pValue = null) { @@ -624,17 +529,4 @@ class PHPExcel_Style_Font implements PHPExcel_IComparable ); } - /** - * Implement PHP __clone to create a deep clone, not just a shallow copy. - */ - public function __clone() { - $vars = get_object_vars($this); - foreach ($vars as $key => $value) { - if ((is_object($value)) && ($key != '_parent')) { - $this->$key = clone $value; - } else { - $this->$key = $value; - } - } - } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Style/NumberFormat.php b/htdocs/includes/phpexcel/PHPExcel/Style/NumberFormat.php index 19e064e4de8..e8a978fb28c 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Style/NumberFormat.php +++ b/htdocs/includes/phpexcel/PHPExcel/Style/NumberFormat.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,9 +31,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable +class PHPExcel_Style_NumberFormat extends PHPExcel_Style_Supervisor implements PHPExcel_IComparable { /* Pre-defined formats */ const FORMAT_GENERAL = 'General'; @@ -80,49 +80,28 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable * * @var array */ - private static $_builtInFormats; + protected static $_builtInFormats; /** * Excel built-in number formats (flipped, for faster lookups) * * @var array */ - private static $_flippedBuiltInFormats; + protected static $_flippedBuiltInFormats; /** * Format Code * * @var string */ - private $_formatCode = PHPExcel_Style_NumberFormat::FORMAT_GENERAL; + protected $_formatCode = PHPExcel_Style_NumberFormat::FORMAT_GENERAL; /** * Built-in format Code * * @var string */ - private $_builtInFormatCode = 0; - - /** - * Parent Borders - * - * @var _parentPropertyName string - */ - private $_parentPropertyName; - - /** - * Supervisor? - * - * @var boolean - */ - private $_isSupervisor; - - /** - * Parent. Only used for supervisor - * - * @var PHPExcel_Style - */ - private $_parent; + protected $_builtInFormatCode = 0; /** * Create a new PHPExcel_Style_NumberFormat @@ -134,37 +113,16 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable * Leave this value at default unless you understand exactly what * its ramifications are */ - public function __construct($isSupervisor = false, $isConditional = false) + public function __construct($isSupervisor = FALSE, $isConditional = FALSE) { // Supervisor? - $this->_isSupervisor = $isSupervisor; + parent::__construct($isSupervisor); if ($isConditional) { $this->_formatCode = NULL; } } - /** - * Bind parent. Only used for supervisor - * - * @param PHPExcel_Style $parent - * @return PHPExcel_Style_NumberFormat - */ - public function bindParent($parent) - { - $this->_parent = $parent; - } - - /** - * Is this a supervisor or a real style component? - * - * @return boolean - */ - public function getIsSupervisor() - { - return $this->_isSupervisor; - } - /** * Get the shared style component for the currently active cell in currently active sheet. * Only used for style supervisor @@ -176,38 +134,6 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable return $this->_parent->getSharedComponent()->getNumberFormat(); } - /** - * Get the currently active sheet. Only used for supervisor - * - * @return PHPExcel_Worksheet - */ - public function getActiveSheet() - { - return $this->_parent->getActiveSheet(); - } - - /** - * Get the currently active cell coordinate in currently active sheet. - * Only used for supervisor - * - * @return string E.g. 'A1' - */ - public function getSelectedCells() - { - return $this->getActiveSheet()->getSelectedCells(); - } - - /** - * Get the currently active cell coordinate in currently active sheet. - * Only used for supervisor - * - * @return string E.g. 'A1' - */ - public function getActiveCell() - { - return $this->getActiveSheet()->getActiveCell(); - } - /** * Build style array from subcomponents * @@ -231,7 +157,7 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable * * * @param array $pStyles Array containing style information - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Style_NumberFormat */ public function applyFromArray($pStyles = null) @@ -245,7 +171,7 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable } } } else { - throw new Exception("Invalid style array passed."); + throw new PHPExcel_Exception("Invalid style array passed."); } return $this; } @@ -443,21 +369,6 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable ); } - /** - * Implement PHP __clone to create a deep clone, not just a shallow copy. - */ - public function __clone() - { - $vars = get_object_vars($this); - foreach ($vars as $key => $value) { - if ((is_object($value)) && ($key != '_parent')) { - $this->$key = clone $value; - } else { - $this->$key = $value; - } - } - } - /** * Search/replace values to convert Excel date/time format masks to PHP format masks * @@ -479,8 +390,11 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable 'mmmm' => 'F', // short month name 'mmm' => 'M', - // mm is minutes if time or month w/leading zero + // mm is minutes if time, but can also be month w/leading zero + // so we try to identify times be the inclusion of a : separator in the mask + // It isn't perfect, but the best way I know how ':mm' => ':i', + 'mm:' => 'i:', // month leading zero 'mm' => 'm', // month no leading zero @@ -517,6 +431,108 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable 'h' => 'g' ); + private static function _formatAsDate(&$value, &$format) + { + // dvc: convert Excel formats to PHP date formats + + // strip off first part containing e.g. [$-F800] or [$USD-409] + // general syntax: [$-] + // language info is in hexadecimal + $format = preg_replace('/^(\[\$[A-Z]*-[0-9A-F]*\])/i', '', $format); + + // OpenOffice.org uses upper-case number formats, e.g. 'YYYY', convert to lower-case + $format = strtolower($format); + + $format = strtr($format,self::$_dateFormatReplacements); + if (!strpos($format,'A')) { // 24-hour time format + $format = strtr($format,self::$_dateFormatReplacements24); + } else { // 12-hour time format + $format = strtr($format,self::$_dateFormatReplacements12); + } + + $dateObj = PHPExcel_Shared_Date::ExcelToPHPObject($value); + $value = $dateObj->format($format); + } + + private static function _formatAsPercentage(&$value, &$format) + { + if ($format === self::FORMAT_PERCENTAGE) { + $value = round( (100 * $value), 0) . '%'; + } else { + if (preg_match('/\.[#0]+/i', $format, $m)) { + $s = substr($m[0], 0, 1) . (strlen($m[0]) - 1); + $format = str_replace($m[0], $s, $format); + } + if (preg_match('/^[#0]+/', $format, $m)) { + $format = str_replace($m[0], strlen($m[0]), $format); + } + $format = '%' . str_replace('%', 'f%%', $format); + + $value = sprintf($format, 100 * $value); + } + } + + private static function _formatAsFraction(&$value, &$format) + { + $sign = ($value < 0) ? '-' : ''; + + $integerPart = floor(abs($value)); + $decimalPart = trim(fmod(abs($value),1),'0.'); + $decimalLength = strlen($decimalPart); + $decimalDivisor = pow(10,$decimalLength); + + $GCD = PHPExcel_Calculation_MathTrig::GCD($decimalPart,$decimalDivisor); + + $adjustedDecimalPart = $decimalPart/$GCD; + $adjustedDecimalDivisor = $decimalDivisor/$GCD; + + if ((strpos($format,'0') !== false) || (strpos($format,'#') !== false) || (substr($format,0,3) == '? ?')) { + if ($integerPart == 0) { + $integerPart = ''; + } + $value = "$sign$integerPart $adjustedDecimalPart/$adjustedDecimalDivisor"; + } else { + $adjustedDecimalPart += $integerPart * $adjustedDecimalDivisor; + $value = "$sign$adjustedDecimalPart/$adjustedDecimalDivisor"; + } + } + + private static function _complexNumberFormatMask($number, $mask) { + if (strpos($mask,'.') !== false) { + $numbers = explode('.', $number . '.0'); + $masks = explode('.', $mask . '.0'); + $result1 = self::_complexNumberFormatMask($numbers[0], $masks[0]); + $result2 = strrev(self::_complexNumberFormatMask(strrev($numbers[1]), strrev($masks[1]))); + return $result1 . '.' . $result2; + } + + $r = preg_match_all('/0+/', $mask, $result, PREG_OFFSET_CAPTURE); + if ($r > 1) { + $result = array_reverse($result[0]); + + foreach($result as $block) { + $divisor = 1 . $block[0]; + $size = strlen($block[0]); + $offset = $block[1]; + + $blockValue = sprintf( + '%0' . $size . 'd', + fmod($number, $divisor) + ); + $number = floor($number / $divisor); + $mask = substr_replace($mask,$blockValue, $offset, $size); + } + if ($number > 0) { + $mask = substr_replace($mask, $number, $offset, 0); + } + $result = $mask; + } else { + $result = $number; + } + + return $result; + } + /** * Convert a value in a pre-defined format to a PHP string * @@ -525,7 +541,7 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable * @param array $callBack Callback function for additional formatting of string * @return string Formatted string */ - public static function toFormattedString($value = '', $format = '', $callBack = null) + public static function toFormattedString($value = '0', $format = PHPExcel_Style_NumberFormat::FORMAT_GENERAL, $callBack = null) { // For now we do not treat strings although section 4 of a format code affects strings if (!is_numeric($value)) return $value; @@ -585,46 +601,12 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable // Let's begin inspecting the format and converting the value to a formatted string if (preg_match('/^(\[\$[A-Z]*-[0-9A-F]*\])*[hmsdy]/i', $format)) { // datetime format - // dvc: convert Excel formats to PHP date formats - - // strip off first part containing e.g. [$-F800] or [$USD-409] - // general syntax: [$-] - // language info is in hexadecimal - $format = preg_replace('/^(\[\$[A-Z]*-[0-9A-F]*\])/i', '', $format); - - // OpenOffice.org uses upper-case number formats, e.g. 'YYYY', convert to lower-case - $format = strtolower($format); - - $format = strtr($format,self::$_dateFormatReplacements); - if (!strpos($format,'A')) { // 24-hour time format - $format = strtr($format,self::$_dateFormatReplacements24); - } else { // 12-hour time format - $format = strtr($format,self::$_dateFormatReplacements12); - } - - $dateObj = PHPExcel_Shared_Date::ExcelToPHPObject($value); - $value = $dateObj->format($format); - + self::_formatAsDate($value, $format); } else if (preg_match('/%$/', $format)) { // % number format - if ($format === self::FORMAT_PERCENTAGE) { - $value = round( (100 * $value), 0) . '%'; - } else { - if (preg_match('/\.[#0]+/i', $format, $m)) { - $s = substr($m[0], 0, 1) . (strlen($m[0]) - 1); - $format = str_replace($m[0], $s, $format); - } - if (preg_match('/^[#0]+/', $format, $m)) { - $format = str_replace($m[0], strlen($m[0]), $format); - } - $format = '%' . str_replace('%', 'f%%', $format); - - $value = sprintf($format, 100 * $value); - } - + self::_formatAsPercentage($value, $format); } else { if ($format === self::FORMAT_CURRENCY_EUR_SIMPLE) { $value = 'EUR ' . sprintf('%1.2f', $value); - } else { // In Excel formats, "_" is used to add spacing, which we can't do in HTML $format = preg_replace('/_./', '', $format); @@ -660,25 +642,7 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable if (preg_match('/#?.*\?\/\?/', $format, $m)) { //echo 'Format mask is fractional '.$format.'
'; if ($value != (int)$value) { - $sign = ($value < 0) ? '-' : ''; - - $integerPart = floor(abs($value)); - $decimalPart = trim(fmod(abs($value),1),'0.'); - $decimalLength = strlen($decimalPart); - $decimalDivisor = pow(10,$decimalLength); - - $GCD = PHPExcel_Calculation_MathTrig::GCD($decimalPart,$decimalDivisor); - - $adjustedDecimalPart = $decimalPart/$GCD; - $adjustedDecimalDivisor = $decimalDivisor/$GCD; - - if ((strpos($format,'0') !== false) || (strpos($format,'#') !== false) || (substr($format,0,3) == '? ?')) { - if ($integerPart == 0) { $integerPart = ''; } - $value = "$sign$integerPart $adjustedDecimalPart/$adjustedDecimalDivisor"; - } else { - $adjustedDecimalPart += $integerPart * $adjustedDecimalDivisor; - $value = "$sign$adjustedDecimalPart/$adjustedDecimalDivisor"; - } + self::_formatAsFraction($value, $format); } } else { @@ -688,7 +652,7 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable $value = $value / $scale; // Strip # - $format = preg_replace('/\\#/', '', $format); + $format = preg_replace('/\\#/', '0', $format); $n = "/\[[^\]]+\]/"; $m = preg_replace($n, '', $format); @@ -700,7 +664,6 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable // minimun width of formatted number (including dot) $minWidth = strlen($left) + strlen($dec) + strlen($right); - if ($useThousands) { $value = number_format( $value @@ -708,12 +671,19 @@ class PHPExcel_Style_NumberFormat implements PHPExcel_IComparable , PHPExcel_Shared_String::getDecimalSeparator() , PHPExcel_Shared_String::getThousandsSeparator() ); + $value = preg_replace($number_regex, $value, $format); } else { - $sprintf_pattern = "%0$minWidth." . strlen($right) . "f"; - $value = sprintf($sprintf_pattern, $value); + if (preg_match('/[0#]E[+-]0/i', $format)) { + // Scientific format + $value = sprintf('%5.2E', $value); + } elseif (preg_match('/0([^\d\.]+)0/', $format)) { + $value = self::_complexNumberFormatMask($value, $format); + } else { + $sprintf_pattern = "%0$minWidth." . strlen($right) . "f"; + $value = sprintf($sprintf_pattern, $value); + $value = preg_replace($number_regex, $value, $format); + } } - - $value = preg_replace($number_regex, $value, $format); } } if (preg_match('/\[\$(.*)\]/u', $format, $m)) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Style/Protection.php b/htdocs/includes/phpexcel/PHPExcel/Style/Protection.php index 477742bd3f5..8dc1f31ad70 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Style/Protection.php +++ b/htdocs/includes/phpexcel/PHPExcel/Style/Protection.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,7 +20,7 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL * @version 1.4.5, 2007-08-23 */ @@ -31,9 +31,9 @@ * * @category PHPExcel * @package PHPExcel_Style - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Style_Protection implements PHPExcel_IComparable +class PHPExcel_Style_Protection extends PHPExcel_Style_Supervisor implements PHPExcel_IComparable { /** Protection styles */ const PROTECTION_INHERIT = 'inherit'; @@ -45,37 +45,16 @@ class PHPExcel_Style_Protection implements PHPExcel_IComparable * * @var string */ - private $_locked; + protected $_locked; /** * Hidden * * @var string */ - private $_hidden; + protected $_hidden; /** - * Parent Borders - * - * @var _parentPropertyName string - */ - private $_parentPropertyName; - - /** - * Supervisor? - * - * @var boolean - */ - private $_isSupervisor; - - /** - * Parent. Only used for supervisor - * - * @var PHPExcel_Style - */ - private $_parent; - - /** * Create a new PHPExcel_Style_Protection * * @param boolean $isSupervisor Flag indicating if this is a supervisor or not @@ -85,10 +64,10 @@ class PHPExcel_Style_Protection implements PHPExcel_IComparable * Leave this value at default unless you understand exactly what * its ramifications are */ - public function __construct($isSupervisor = false, $isConditional = false) + public function __construct($isSupervisor = FALSE, $isConditional = FALSE) { // Supervisor? - $this->_isSupervisor = $isSupervisor; + parent::__construct($isSupervisor); // Initialise values if (!$isConditional) { @@ -97,28 +76,6 @@ class PHPExcel_Style_Protection implements PHPExcel_IComparable } } - /** - * Bind parent. Only used for supervisor - * - * @param PHPExcel_Style $parent - * @return PHPExcel_Style_Protection - */ - public function bindParent($parent) - { - $this->_parent = $parent; - return $this; - } - - /** - * Is this a supervisor or a real style component? - * - * @return boolean - */ - public function getIsSupervisor() - { - return $this->_isSupervisor; - } - /** * Get the shared style component for the currently active cell in currently active sheet. * Only used for style supervisor @@ -130,38 +87,6 @@ class PHPExcel_Style_Protection implements PHPExcel_IComparable return $this->_parent->getSharedComponent()->getProtection(); } - /** - * Get the currently active sheet. Only used for supervisor - * - * @return PHPExcel_Worksheet - */ - public function getActiveSheet() - { - return $this->_parent->getActiveSheet(); - } - - /** - * Get the currently active cell coordinate in currently active sheet. - * Only used for supervisor - * - * @return string E.g. 'A1' - */ - public function getSelectedCells() - { - return $this->getActiveSheet()->getSelectedCells(); - } - - /** - * Get the currently active cell coordinate in currently active sheet. - * Only used for supervisor - * - * @return string E.g. 'A1' - */ - public function getActiveCell() - { - return $this->getActiveSheet()->getActiveCell(); - } - /** * Build style array from subcomponents * @@ -177,27 +102,32 @@ class PHPExcel_Style_Protection implements PHPExcel_IComparable * Apply styles from array * * - * $objPHPExcel->getActiveSheet()->getStyle('B2')->getLocked()->applyFromArray( array('locked' => true, 'hidden' => false) ); + * $objPHPExcel->getActiveSheet()->getStyle('B2')->getLocked()->applyFromArray( + * array( + * 'locked' => TRUE, + * 'hidden' => FALSE + * ) + * ); * * * @param array $pStyles Array containing style information - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Style_Protection */ - public function applyFromArray($pStyles = null) { + public function applyFromArray($pStyles = NULL) { if (is_array($pStyles)) { if ($this->_isSupervisor) { $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); } else { - if (array_key_exists('locked', $pStyles)) { + if (isset($pStyles['locked'])) { $this->setLocked($pStyles['locked']); } - if (array_key_exists('hidden', $pStyles)) { + if (isset($pStyles['hidden'])) { $this->setHidden($pStyles['hidden']); } } } else { - throw new Exception("Invalid style array passed."); + throw new PHPExcel_Exception("Invalid style array passed."); } return $this; } @@ -274,17 +204,4 @@ class PHPExcel_Style_Protection implements PHPExcel_IComparable ); } - /** - * Implement PHP __clone to create a deep clone, not just a shallow copy. - */ - public function __clone() { - $vars = get_object_vars($this); - foreach ($vars as $key => $value) { - if ((is_object($value)) && ($key != '_parent')) { - $this->$key = clone $value; - } else { - $this->$key = $value; - } - } - } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Style/Supervisor.php b/htdocs/includes/phpexcel/PHPExcel/Style/Supervisor.php new file mode 100644 index 00000000000..c2ce9c035ab --- /dev/null +++ b/htdocs/includes/phpexcel/PHPExcel/Style/Supervisor.php @@ -0,0 +1,132 @@ +_isSupervisor = $isSupervisor; + } + + /** + * Bind parent. Only used for supervisor + * + * @param PHPExcel $parent + * @return PHPExcel_Style_Supervisor + */ + public function bindParent($parent, $parentPropertyName=NULL) + { + $this->_parent = $parent; + return $this; + } + + /** + * Is this a supervisor or a cell style component? + * + * @return boolean + */ + public function getIsSupervisor() + { + return $this->_isSupervisor; + } + + /** + * Get the currently active sheet. Only used for supervisor + * + * @return PHPExcel_Worksheet + */ + public function getActiveSheet() + { + return $this->_parent->getActiveSheet(); + } + + /** + * Get the currently active cell coordinate in currently active sheet. + * Only used for supervisor + * + * @return string E.g. 'A1' + */ + public function getSelectedCells() + { + return $this->getActiveSheet()->getSelectedCells(); + } + + /** + * Get the currently active cell coordinate in currently active sheet. + * Only used for supervisor + * + * @return string E.g. 'A1' + */ + public function getActiveCell() + { + return $this->getActiveSheet()->getActiveCell(); + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if ((is_object($value)) && ($key != '_parent')) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/htdocs/includes/phpexcel/PHPExcel/Worksheet.php b/htdocs/includes/phpexcel/PHPExcel/Worksheet.php index 17ed5da962b..682ad9838ea 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Worksheet.php +++ b/htdocs/includes/phpexcel/PHPExcel/Worksheet.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,10 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * @category PHPExcel - * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.8.0, 2014-03-02 */ @@ -30,779 +30,2846 @@ * PHPExcel_Worksheet * * @category PHPExcel - * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet implements PHPExcel_IComparable { - /* Break types */ - const BREAK_NONE = 0; - const BREAK_ROW = 1; - const BREAK_COLUMN = 2; + /* Break types */ + const BREAK_NONE = 0; + const BREAK_ROW = 1; + const BREAK_COLUMN = 2; - /* Sheet state */ - const SHEETSTATE_VISIBLE = 'visible'; - const SHEETSTATE_HIDDEN = 'hidden'; - const SHEETSTATE_VERYHIDDEN = 'veryHidden'; + /* Sheet state */ + const SHEETSTATE_VISIBLE = 'visible'; + const SHEETSTATE_HIDDEN = 'hidden'; + const SHEETSTATE_VERYHIDDEN = 'veryHidden'; + + /** + * Invalid characters in sheet title + * + * @var array + */ + private static $_invalidCharacters = array('*', ':', '/', '\\', '?', '[', ']'); + + /** + * Parent spreadsheet + * + * @var PHPExcel + */ + private $_parent; + + /** + * Cacheable collection of cells + * + * @var PHPExcel_CachedObjectStorage_xxx + */ + private $_cellCollection = null; + + /** + * Collection of row dimensions + * + * @var PHPExcel_Worksheet_RowDimension[] + */ + private $_rowDimensions = array(); + + /** + * Default row dimension + * + * @var PHPExcel_Worksheet_RowDimension + */ + private $_defaultRowDimension = null; + + /** + * Collection of column dimensions + * + * @var PHPExcel_Worksheet_ColumnDimension[] + */ + private $_columnDimensions = array(); + + /** + * Default column dimension + * + * @var PHPExcel_Worksheet_ColumnDimension + */ + private $_defaultColumnDimension = null; + + /** + * Collection of drawings + * + * @var PHPExcel_Worksheet_BaseDrawing[] + */ + private $_drawingCollection = null; + + /** + * Collection of Chart objects + * + * @var PHPExcel_Chart[] + */ + private $_chartCollection = array(); + + /** + * Worksheet title + * + * @var string + */ + private $_title; + + /** + * Sheet state + * + * @var string + */ + private $_sheetState; + + /** + * Page setup + * + * @var PHPExcel_Worksheet_PageSetup + */ + private $_pageSetup; + + /** + * Page margins + * + * @var PHPExcel_Worksheet_PageMargins + */ + private $_pageMargins; + + /** + * Page header/footer + * + * @var PHPExcel_Worksheet_HeaderFooter + */ + private $_headerFooter; + + /** + * Sheet view + * + * @var PHPExcel_Worksheet_SheetView + */ + private $_sheetView; + + /** + * Protection + * + * @var PHPExcel_Worksheet_Protection + */ + private $_protection; + + /** + * Collection of styles + * + * @var PHPExcel_Style[] + */ + private $_styles = array(); + + /** + * Conditional styles. Indexed by cell coordinate, e.g. 'A1' + * + * @var array + */ + private $_conditionalStylesCollection = array(); + + /** + * Is the current cell collection sorted already? + * + * @var boolean + */ + private $_cellCollectionIsSorted = false; + + /** + * Collection of breaks + * + * @var array + */ + private $_breaks = array(); + + /** + * Collection of merged cell ranges + * + * @var array + */ + private $_mergeCells = array(); + + /** + * Collection of protected cell ranges + * + * @var array + */ + private $_protectedCells = array(); + + /** + * Autofilter Range and selection + * + * @var PHPExcel_Worksheet_AutoFilter + */ + private $_autoFilter = NULL; + + /** + * Freeze pane + * + * @var string + */ + private $_freezePane = ''; + + /** + * Show gridlines? + * + * @var boolean + */ + private $_showGridlines = true; + + /** + * Print gridlines? + * + * @var boolean + */ + private $_printGridlines = false; + + /** + * Show row and column headers? + * + * @var boolean + */ + private $_showRowColHeaders = true; + + /** + * Show summary below? (Row/Column outline) + * + * @var boolean + */ + private $_showSummaryBelow = true; + + /** + * Show summary right? (Row/Column outline) + * + * @var boolean + */ + private $_showSummaryRight = true; + + /** + * Collection of comments + * + * @var PHPExcel_Comment[] + */ + private $_comments = array(); + + /** + * Active cell. (Only one!) + * + * @var string + */ + private $_activeCell = 'A1'; + + /** + * Selected cells + * + * @var string + */ + private $_selectedCells = 'A1'; + + /** + * Cached highest column + * + * @var string + */ + private $_cachedHighestColumn = 'A'; + + /** + * Cached highest row + * + * @var int + */ + private $_cachedHighestRow = 1; + + /** + * Right-to-left? + * + * @var boolean + */ + private $_rightToLeft = false; + + /** + * Hyperlinks. Indexed by cell coordinate, e.g. 'A1' + * + * @var array + */ + private $_hyperlinkCollection = array(); + + /** + * Data validation objects. Indexed by cell coordinate, e.g. 'A1' + * + * @var array + */ + private $_dataValidationCollection = array(); + + /** + * Tab color + * + * @var PHPExcel_Style_Color + */ + private $_tabColor; + + /** + * Dirty flag + * + * @var boolean + */ + private $_dirty = true; + + /** + * Hash + * + * @var string + */ + private $_hash = null; + + /** + * CodeName + * + * @var string + */ + private $_codeName = null; /** - * Invalid characters in sheet title - * - * @var array - */ - private static $_invalidCharacters = array('*', ':', '/', '\\', '?', '[', ']'); + * Create a new worksheet + * + * @param PHPExcel $pParent + * @param string $pTitle + */ + public function __construct(PHPExcel $pParent = null, $pTitle = 'Worksheet') + { + // Set parent and title + $this->_parent = $pParent; + $this->setTitle($pTitle, FALSE); + // setTitle can change $pTitle + $this->setCodeName($this->getTitle()); + $this->setSheetState(PHPExcel_Worksheet::SHEETSTATE_VISIBLE); - /** - * Parent spreadsheet - * - * @var PHPExcel - */ - private $_parent; + $this->_cellCollection = PHPExcel_CachedObjectStorageFactory::getInstance($this); - /** - * Cacheable collection of cells - * - * @var PHPExcel_CachedObjectStorage_xxx - */ - private $_cellCollection = null; + // Set page setup + $this->_pageSetup = new PHPExcel_Worksheet_PageSetup(); - /** - * Collection of row dimensions - * - * @var PHPExcel_Worksheet_RowDimension[] - */ - private $_rowDimensions = array(); + // Set page margins + $this->_pageMargins = new PHPExcel_Worksheet_PageMargins(); - /** - * Default row dimension - * - * @var PHPExcel_Worksheet_RowDimension - */ - private $_defaultRowDimension = null; + // Set page header/footer + $this->_headerFooter = new PHPExcel_Worksheet_HeaderFooter(); - /** - * Collection of column dimensions - * - * @var PHPExcel_Worksheet_ColumnDimension[] - */ - private $_columnDimensions = array(); + // Set sheet view + $this->_sheetView = new PHPExcel_Worksheet_SheetView(); - /** - * Default column dimension - * - * @var PHPExcel_Worksheet_ColumnDimension - */ - private $_defaultColumnDimension = null; + // Drawing collection + $this->_drawingCollection = new ArrayObject(); - /** - * Collection of drawings - * - * @var PHPExcel_Worksheet_BaseDrawing[] - */ - private $_drawingCollection = null; + // Chart collection + $this->_chartCollection = new ArrayObject(); - /** - * Collection of Chart objects - * - * @var PHPExcel_Chart[] - */ - private $_chartCollection = array(); + // Protection + $this->_protection = new PHPExcel_Worksheet_Protection(); - /** - * Worksheet title - * - * @var string - */ - private $_title; + // Default row dimension + $this->_defaultRowDimension = new PHPExcel_Worksheet_RowDimension(NULL); - /** - * Sheet state - * - * @var string - */ - private $_sheetState; + // Default column dimension + $this->_defaultColumnDimension = new PHPExcel_Worksheet_ColumnDimension(NULL); - /** - * Page setup - * - * @var PHPExcel_Worksheet_PageSetup - */ - private $_pageSetup; - - /** - * Page margins - * - * @var PHPExcel_Worksheet_PageMargins - */ - private $_pageMargins; - - /** - * Page header/footer - * - * @var PHPExcel_Worksheet_HeaderFooter - */ - private $_headerFooter; - - /** - * Sheet view - * - * @var PHPExcel_Worksheet_SheetView - */ - private $_sheetView; - - /** - * Protection - * - * @var PHPExcel_Worksheet_Protection - */ - private $_protection; - - /** - * Collection of styles - * - * @var PHPExcel_Style[] - */ - private $_styles = array(); - - /** - * Conditional styles. Indexed by cell coordinate, e.g. 'A1' - * - * @var array - */ - private $_conditionalStylesCollection = array(); - - /** - * Is the current cell collection sorted already? - * - * @var boolean - */ - private $_cellCollectionIsSorted = false; - - /** - * Collection of breaks - * - * @var array - */ - private $_breaks = array(); - - /** - * Collection of merged cell ranges - * - * @var array - */ - private $_mergeCells = array(); - - /** - * Collection of protected cell ranges - * - * @var array - */ - private $_protectedCells = array(); - - /** - * Autofilter Range and selection - * - * @var PHPExcel_Worksheet_AutoFilter - */ - private $_autoFilter = NULL; - - /** - * Freeze pane - * - * @var string - */ - private $_freezePane = ''; - - /** - * Show gridlines? - * - * @var boolean - */ - private $_showGridlines = true; - - /** - * Print gridlines? - * - * @var boolean - */ - private $_printGridlines = false; - - /** - * Show row and column headers? - * - * @var boolean - */ - private $_showRowColHeaders = true; - - /** - * Show summary below? (Row/Column outline) - * - * @var boolean - */ - private $_showSummaryBelow = true; - - /** - * Show summary right? (Row/Column outline) - * - * @var boolean - */ - private $_showSummaryRight = true; - - /** - * Collection of comments - * - * @var PHPExcel_Comment[] - */ - private $_comments = array(); - - /** - * Active cell. (Only one!) - * - * @var string - */ - private $_activeCell = 'A1'; - - /** - * Selected cells - * - * @var string - */ - private $_selectedCells = 'A1'; - - /** - * Cached highest column - * - * @var string - */ - private $_cachedHighestColumn = 'A'; - - /** - * Cached highest row - * - * @var int - */ - private $_cachedHighestRow = 1; - - /** - * Right-to-left? - * - * @var boolean - */ - private $_rightToLeft = false; - - /** - * Hyperlinks. Indexed by cell coordinate, e.g. 'A1' - * - * @var array - */ - private $_hyperlinkCollection = array(); - - /** - * Data validation objects. Indexed by cell coordinate, e.g. 'A1' - * - * @var array - */ - private $_dataValidationCollection = array(); - - /** - * Tab color - * - * @var PHPExcel_Style_Color - */ - private $_tabColor; - - /** - * Dirty flag - * - * @var boolean - */ - private $_dirty = true; - - /** - * Hash - * - * @var string - */ - private $_hash = null; - - /** - * Create a new worksheet - * - * @param PHPExcel $pParent - * @param string $pTitle - */ - public function __construct(PHPExcel $pParent = null, $pTitle = 'Worksheet') - { - // Set parent and title - $this->_parent = $pParent; - $this->setTitle($pTitle, FALSE); - $this->setSheetState(PHPExcel_Worksheet::SHEETSTATE_VISIBLE); - - $this->_cellCollection = PHPExcel_CachedObjectStorageFactory::getInstance($this); - - // Set page setup - $this->_pageSetup = new PHPExcel_Worksheet_PageSetup(); - - // Set page margins - $this->_pageMargins = new PHPExcel_Worksheet_PageMargins(); - - // Set page header/footer - $this->_headerFooter = new PHPExcel_Worksheet_HeaderFooter(); - - // Set sheet view - $this->_sheetView = new PHPExcel_Worksheet_SheetView(); - - // Drawing collection - $this->_drawingCollection = new ArrayObject(); - - // Chart collection - $this->_chartCollection = new ArrayObject(); - - // Protection - $this->_protection = new PHPExcel_Worksheet_Protection(); - - // Default row dimension - $this->_defaultRowDimension = new PHPExcel_Worksheet_RowDimension(NULL); - - // Default column dimension - $this->_defaultColumnDimension = new PHPExcel_Worksheet_ColumnDimension(NULL); - - $this->_autoFilter = new PHPExcel_Worksheet_AutoFilter(NULL, $this); - } + $this->_autoFilter = new PHPExcel_Worksheet_AutoFilter(NULL, $this); + } - /** - * Disconnect all cells from this PHPExcel_Worksheet object, - * typically so that the worksheet object can be unset - * - */ + /** + * Disconnect all cells from this PHPExcel_Worksheet object, + * typically so that the worksheet object can be unset + * + */ public function disconnectCells() { - $this->_cellCollection->unsetWorksheetCells(); - $this->_cellCollection = null; + if ( $this->_cellCollection !== NULL){ + $this->_cellCollection->unsetWorksheetCells(); + $this->_cellCollection = NULL; + } + // detach ourself from the workbook, so that it can then delete this worksheet successfully + $this->_parent = null; + } - // detach ourself from the workbook, so that it can then delete this worksheet successfully - $this->_parent = null; + /** + * Code to execute when this worksheet is unset() + * + */ + function __destruct() { + PHPExcel_Calculation::getInstance($this->_parent) + ->clearCalculationCacheForWorksheet($this->_title); + + $this->disconnectCells(); } - /** - * Return the cache controller for the cell collection - * - * @return PHPExcel_CachedObjectStorage_xxx - */ + /** + * Return the cache controller for the cell collection + * + * @return PHPExcel_CachedObjectStorage_xxx + */ public function getCellCacheController() { - return $this->_cellCollection; - } // function getCellCacheController() + return $this->_cellCollection; + } // function getCellCacheController() - /** - * Get array of invalid characters for sheet title - * - * @return array - */ - public static function getInvalidCharacters() - { - return self::$_invalidCharacters; - } + /** + * Get array of invalid characters for sheet title + * + * @return array + */ + public static function getInvalidCharacters() + { + return self::$_invalidCharacters; + } - /** - * Check sheet title for valid Excel syntax - * - * @param string $pValue The string to check - * @return string The valid string - * @throws Exception - */ - private static function _checkSheetTitle($pValue) - { - // Some of the printable ASCII characters are invalid: * : / \ ? [ ] - if (str_replace(self::$_invalidCharacters, '', $pValue) !== $pValue) { - throw new Exception('Invalid character found in sheet title'); - } + /** + * Check sheet code name for valid Excel syntax + * + * @param string $pValue The string to check + * @return string The valid string + * @throws Exception + */ + private static function _checkSheetCodeName($pValue) + { + $CharCount = PHPExcel_Shared_String::CountCharacters($pValue); + if ($CharCount == 0) { + throw new PHPExcel_Exception('Sheet code name cannot be empty.'); + } + // Some of the printable ASCII characters are invalid: * : / \ ? [ ] and first and last characters cannot be a "'" + if ((str_replace(self::$_invalidCharacters, '', $pValue) !== $pValue) || + (PHPExcel_Shared_String::Substring($pValue,-1,1)=='\'') || + (PHPExcel_Shared_String::Substring($pValue,0,1)=='\'')) { + throw new PHPExcel_Exception('Invalid character found in sheet code name'); + } + + // Maximum 31 characters allowed for sheet title + if ($CharCount > 31) { + throw new PHPExcel_Exception('Maximum 31 characters allowed in sheet code name.'); + } + + return $pValue; + } - // Maximum 31 characters allowed for sheet title - if (PHPExcel_Shared_String::CountCharacters($pValue) > 31) { - throw new Exception('Maximum 31 characters allowed in sheet title.'); - } + /** + * Check sheet title for valid Excel syntax + * + * @param string $pValue The string to check + * @return string The valid string + * @throws PHPExcel_Exception + */ + private static function _checkSheetTitle($pValue) + { + // Some of the printable ASCII characters are invalid: * : / \ ? [ ] + if (str_replace(self::$_invalidCharacters, '', $pValue) !== $pValue) { + throw new PHPExcel_Exception('Invalid character found in sheet title'); + } - return $pValue; - } + // Maximum 31 characters allowed for sheet title + if (PHPExcel_Shared_String::CountCharacters($pValue) > 31) { + throw new PHPExcel_Exception('Maximum 31 characters allowed in sheet title.'); + } - /** - * Get collection of cells - * - * @param boolean $pSorted Also sort the cell collection? - * @return PHPExcel_Cell[] - */ - public function getCellCollection($pSorted = true) - { - if ($pSorted) { - // Re-order cell collection - return $this->sortCellCollection(); - } - if ($this->_cellCollection !== NULL) { - return $this->_cellCollection->getCellList(); - } - return array(); - } + return $pValue; + } - /** - * Sort collection of cells - * - * @return PHPExcel_Worksheet - */ - public function sortCellCollection() - { - if ($this->_cellCollection !== NULL) { - return $this->_cellCollection->getSortedCellList(); - } - return array(); - } + /** + * Get collection of cells + * + * @param boolean $pSorted Also sort the cell collection? + * @return PHPExcel_Cell[] + */ + public function getCellCollection($pSorted = true) + { + if ($pSorted) { + // Re-order cell collection + return $this->sortCellCollection(); + } + if ($this->_cellCollection !== NULL) { + return $this->_cellCollection->getCellList(); + } + return array(); + } - /** - * Get collection of row dimensions - * - * @return PHPExcel_Worksheet_RowDimension[] - */ - public function getRowDimensions() - { - return $this->_rowDimensions; - } + /** + * Sort collection of cells + * + * @return PHPExcel_Worksheet + */ + public function sortCellCollection() + { + if ($this->_cellCollection !== NULL) { + return $this->_cellCollection->getSortedCellList(); + } + return array(); + } - /** - * Get default row dimension - * - * @return PHPExcel_Worksheet_RowDimension - */ - public function getDefaultRowDimension() - { - return $this->_defaultRowDimension; - } + /** + * Get collection of row dimensions + * + * @return PHPExcel_Worksheet_RowDimension[] + */ + public function getRowDimensions() + { + return $this->_rowDimensions; + } - /** - * Get collection of column dimensions - * - * @return PHPExcel_Worksheet_ColumnDimension[] - */ - public function getColumnDimensions() - { - return $this->_columnDimensions; - } + /** + * Get default row dimension + * + * @return PHPExcel_Worksheet_RowDimension + */ + public function getDefaultRowDimension() + { + return $this->_defaultRowDimension; + } - /** - * Get default column dimension - * - * @return PHPExcel_Worksheet_ColumnDimension - */ - public function getDefaultColumnDimension() - { - return $this->_defaultColumnDimension; - } + /** + * Get collection of column dimensions + * + * @return PHPExcel_Worksheet_ColumnDimension[] + */ + public function getColumnDimensions() + { + return $this->_columnDimensions; + } - /** - * Get collection of drawings - * - * @return PHPExcel_Worksheet_BaseDrawing[] - */ - public function getDrawingCollection() - { - return $this->_drawingCollection; - } + /** + * Get default column dimension + * + * @return PHPExcel_Worksheet_ColumnDimension + */ + public function getDefaultColumnDimension() + { + return $this->_defaultColumnDimension; + } - /** - * Get collection of charts - * - * @return PHPExcel_Chart[] - */ - public function getChartCollection() - { - return $this->_chartCollection; - } + /** + * Get collection of drawings + * + * @return PHPExcel_Worksheet_BaseDrawing[] + */ + public function getDrawingCollection() + { + return $this->_drawingCollection; + } - /** - * Add chart - * - * @param PHPExcel_Chart $pChart - * @param int|null $iChartIndex Index where chart should go (0,1,..., or null for last) - * @return PHPExcel_Chart - * @throws Exception - */ - public function addChart(PHPExcel_Chart $pChart = null, $iChartIndex = null) - { - $pChart->setWorksheet($this); - if (is_null($iChartIndex)) { - $this->_chartCollection[] = $pChart; - } else { - // Insert the chart at the requested index - array_splice($this->_chartCollection, $iChartIndex, 0, array($pChart)); - } + /** + * Get collection of charts + * + * @return PHPExcel_Chart[] + */ + public function getChartCollection() + { + return $this->_chartCollection; + } - return $pChart; - } + /** + * Add chart + * + * @param PHPExcel_Chart $pChart + * @param int|null $iChartIndex Index where chart should go (0,1,..., or null for last) + * @return PHPExcel_Chart + */ + public function addChart(PHPExcel_Chart $pChart = null, $iChartIndex = null) + { + $pChart->setWorksheet($this); + if (is_null($iChartIndex)) { + $this->_chartCollection[] = $pChart; + } else { + // Insert the chart at the requested index + array_splice($this->_chartCollection, $iChartIndex, 0, array($pChart)); + } - /** - * Return the count of charts on this worksheet - * - * @return int The number of charts - * @throws Exception - */ - public function getChartCount() - { - return count($this->_chartCollection); - } + return $pChart; + } - /** - * Get a chart by its index position - * - * @param string $index Chart index position - * @return false|PHPExcel_Chart - * @throws Exception - */ - public function getChartByIndex($index = null) - { - $chartCount = count($this->_chartCollection); - if ($chartCount == 0) { - return false; - } - if (is_null($index)) { - $index = --$chartCount; - } - if (!isset($this->_chartCollection[$index])) { - return false; - } + /** + * Return the count of charts on this worksheet + * + * @return int The number of charts + */ + public function getChartCount() + { + return count($this->_chartCollection); + } - return $this->_chartCollection[$index]; - } + /** + * Get a chart by its index position + * + * @param string $index Chart index position + * @return false|PHPExcel_Chart + * @throws PHPExcel_Exception + */ + public function getChartByIndex($index = null) + { + $chartCount = count($this->_chartCollection); + if ($chartCount == 0) { + return false; + } + if (is_null($index)) { + $index = --$chartCount; + } + if (!isset($this->_chartCollection[$index])) { + return false; + } - /** - * Return an array of the names of charts on this worksheet - * - * @return string[] The names of charts - * @throws Exception - */ - public function getChartNames() - { - $chartNames = array(); - foreach($this->_chartCollection as $chart) { - $chartNames[] = $chart->getName(); - } - return $chartNames; - } + return $this->_chartCollection[$index]; + } - /** - * Get a chart by name - * - * @param string $chartName Chart name - * @return false|PHPExcel_Chart - * @throws Exception - */ - public function getChartByName($chartName = '') - { - $chartCount = count($this->_chartCollection); - if ($chartCount == 0) { - return false; - } - foreach($this->_chartCollection as $index => $chart) { - if ($chart->getName() == $chartName) { - return $this->_chartCollection[$index]; - } - } - return false; - } + /** + * Return an array of the names of charts on this worksheet + * + * @return string[] The names of charts + * @throws PHPExcel_Exception + */ + public function getChartNames() + { + $chartNames = array(); + foreach($this->_chartCollection as $chart) { + $chartNames[] = $chart->getName(); + } + return $chartNames; + } - /** - * Refresh column dimensions - * - * @return PHPExcel_Worksheet - */ - public function refreshColumnDimensions() - { - $currentColumnDimensions = $this->getColumnDimensions(); - $newColumnDimensions = array(); + /** + * Get a chart by name + * + * @param string $chartName Chart name + * @return false|PHPExcel_Chart + * @throws PHPExcel_Exception + */ + public function getChartByName($chartName = '') + { + $chartCount = count($this->_chartCollection); + if ($chartCount == 0) { + return false; + } + foreach($this->_chartCollection as $index => $chart) { + if ($chart->getName() == $chartName) { + return $this->_chartCollection[$index]; + } + } + return false; + } - foreach ($currentColumnDimensions as $objColumnDimension) { - $newColumnDimensions[$objColumnDimension->getColumnIndex()] = $objColumnDimension; - } + /** + * Refresh column dimensions + * + * @return PHPExcel_Worksheet + */ + public function refreshColumnDimensions() + { + $currentColumnDimensions = $this->getColumnDimensions(); + $newColumnDimensions = array(); - $this->_columnDimensions = $newColumnDimensions; + foreach ($currentColumnDimensions as $objColumnDimension) { + $newColumnDimensions[$objColumnDimension->getColumnIndex()] = $objColumnDimension; + } - return $this; - } + $this->_columnDimensions = $newColumnDimensions; - /** - * Refresh row dimensions - * - * @return PHPExcel_Worksheet - */ - public function refreshRowDimensions() - { - $currentRowDimensions = $this->getRowDimensions(); - $newRowDimensions = array(); + return $this; + } - foreach ($currentRowDimensions as $objRowDimension) { - $newRowDimensions[$objRowDimension->getRowIndex()] = $objRowDimension; - } + /** + * Refresh row dimensions + * + * @return PHPExcel_Worksheet + */ + public function refreshRowDimensions() + { + $currentRowDimensions = $this->getRowDimensions(); + $newRowDimensions = array(); - $this->_rowDimensions = $newRowDimensions; + foreach ($currentRowDimensions as $objRowDimension) { + $newRowDimensions[$objRowDimension->getRowIndex()] = $objRowDimension; + } - return $this; - } + $this->_rowDimensions = $newRowDimensions; - /** - * Calculate worksheet dimension - * - * @return string String containing the dimension of this worksheet - */ - public function calculateWorksheetDimension() - { - // Return - return 'A1' . ':' . $this->getHighestColumn() . $this->getHighestRow(); - } + return $this; + } - /** - * Calculate worksheet data dimension - * - * @return string String containing the dimension of this worksheet that actually contain data - */ - public function calculateWorksheetDataDimension() - { - // Return - return 'A1' . ':' . $this->getHighestDataColumn() . $this->getHighestDataRow(); - } + /** + * Calculate worksheet dimension + * + * @return string String containing the dimension of this worksheet + */ + public function calculateWorksheetDimension() + { + // Return + return 'A1' . ':' . $this->getHighestColumn() . $this->getHighestRow(); + } - /** - * Calculate widths for auto-size columns - * - * @param boolean $calculateMergeCells Calculate merge cell width - * @return PHPExcel_Worksheet; - */ - public function calculateColumnWidths($calculateMergeCells = false) - { - // initialize $autoSizes array - $autoSizes = array(); - foreach ($this->getColumnDimensions() as $colDimension) { - if ($colDimension->getAutoSize()) { - $autoSizes[$colDimension->getColumnIndex()] = -1; - } - } + /** + * Calculate worksheet data dimension + * + * @return string String containing the dimension of this worksheet that actually contain data + */ + public function calculateWorksheetDataDimension() + { + // Return + return 'A1' . ':' . $this->getHighestDataColumn() . $this->getHighestDataRow(); + } - // There is only something to do if there are some auto-size columns - if (!empty($autoSizes)) { + /** + * Calculate widths for auto-size columns + * + * @param boolean $calculateMergeCells Calculate merge cell width + * @return PHPExcel_Worksheet; + */ + public function calculateColumnWidths($calculateMergeCells = false) + { + // initialize $autoSizes array + $autoSizes = array(); + foreach ($this->getColumnDimensions() as $colDimension) { + if ($colDimension->getAutoSize()) { + $autoSizes[$colDimension->getColumnIndex()] = -1; + } + } - // build list of cells references that participate in a merge - $isMergeCell = array(); - foreach ($this->getMergeCells() as $cells) { - foreach (PHPExcel_Cell::extractAllCellReferencesInRange($cells) as $cellReference) { - $isMergeCell[$cellReference] = true; - } - } + // There is only something to do if there are some auto-size columns + if (!empty($autoSizes)) { - // loop through all cells in the worksheet - foreach ($this->getCellCollection(false) as $cellID) { - $cell = $this->getCell($cellID); - if (isset($autoSizes[$cell->getColumn()])) { - // Determine width if cell does not participate in a merge - if (!isset($isMergeCell[$cell->getCoordinate()])) { - // Calculated value - $cellValue = $cell->getCalculatedValue(); + // build list of cells references that participate in a merge + $isMergeCell = array(); + foreach ($this->getMergeCells() as $cells) { + foreach (PHPExcel_Cell::extractAllCellReferencesInRange($cells) as $cellReference) { + $isMergeCell[$cellReference] = true; + } + } - // To formatted string - $cellValue = PHPExcel_Style_NumberFormat::toFormattedString($cellValue, $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode()); - - $autoSizes[$cell->getColumn()] = max( - (float)$autoSizes[$cell->getColumn()], - (float)PHPExcel_Shared_Font::calculateColumnWidth( - $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont(), - $cellValue, - $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getAlignment()->getTextRotation(), - $this->getDefaultStyle()->getFont() - ) + // loop through all cells in the worksheet + foreach ($this->getCellCollection(false) as $cellID) { + $cell = $this->getCell($cellID); + if (isset($autoSizes[$this->_cellCollection->getCurrentColumn()])) { + // Determine width if cell does not participate in a merge + if (!isset($isMergeCell[$this->_cellCollection->getCurrentAddress()])) { + // Calculated value + // To formatted string + $cellValue = PHPExcel_Style_NumberFormat::toFormattedString( + $cell->getCalculatedValue(), + $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode() ); - } - } - } - // adjust column widths - foreach ($autoSizes as $columnIndex => $width) { - if ($width == -1) $width = $this->getDefaultColumnDimension()->getWidth(); - $this->getColumnDimension($columnIndex)->setWidth($width); - } - } + $autoSizes[$this->_cellCollection->getCurrentColumn()] = max( + (float) $autoSizes[$this->_cellCollection->getCurrentColumn()], + (float)PHPExcel_Shared_Font::calculateColumnWidth( + $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont(), + $cellValue, + $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getAlignment()->getTextRotation(), + $this->getDefaultStyle()->getFont() + ) + ); + } + } + } - return $this; - } + // adjust column widths + foreach ($autoSizes as $columnIndex => $width) { + if ($width == -1) $width = $this->getDefaultColumnDimension()->getWidth(); + $this->getColumnDimension($columnIndex)->setWidth($width); + } + } - /** - * Get parent - * - * @return PHPExcel - */ + return $this; + } + + /** + * Get parent + * + * @return PHPExcel + */ public function getParent() { - return $this->_parent; - } + return $this->_parent; + } - /** - * Re-bind parent - * - * @param PHPExcel $parent - * @return PHPExcel_Worksheet - */ + /** + * Re-bind parent + * + * @param PHPExcel $parent + * @return PHPExcel_Worksheet + */ public function rebindParent(PHPExcel $parent) { - $namedRanges = $this->_parent->getNamedRanges(); - foreach ($namedRanges as $namedRange) { - $parent->addNamedRange($namedRange); - } + if ($this->_parent !== null) { + $namedRanges = $this->_parent->getNamedRanges(); + foreach ($namedRanges as $namedRange) { + $parent->addNamedRange($namedRange); + } - $this->_parent->removeSheetByIndex( - $this->_parent->getIndex($this) + $this->_parent->removeSheetByIndex( + $this->_parent->getIndex($this) + ); + } + $this->_parent = $parent; + + return $this; + } + + /** + * Get title + * + * @return string + */ + public function getTitle() + { + return $this->_title; + } + + /** + * Set title + * + * @param string $pValue String containing the dimension of this worksheet + * @param string $updateFormulaCellReferences boolean Flag indicating whether cell references in formulae should + * be updated to reflect the new sheet name. + * This should be left as the default true, unless you are + * certain that no formula cells on any worksheet contain + * references to this worksheet + * @return PHPExcel_Worksheet + */ + public function setTitle($pValue = 'Worksheet', $updateFormulaCellReferences = true) + { + // Is this a 'rename' or not? + if ($this->getTitle() == $pValue) { + return $this; + } + + // Syntax check + self::_checkSheetTitle($pValue); + + // Old title + $oldTitle = $this->getTitle(); + + if ($this->_parent) { + // Is there already such sheet name? + if ($this->_parent->sheetNameExists($pValue)) { + // Use name, but append with lowest possible integer + + if (PHPExcel_Shared_String::CountCharacters($pValue) > 29) { + $pValue = PHPExcel_Shared_String::Substring($pValue,0,29); + } + $i = 1; + while ($this->_parent->sheetNameExists($pValue . ' ' . $i)) { + ++$i; + if ($i == 10) { + if (PHPExcel_Shared_String::CountCharacters($pValue) > 28) { + $pValue = PHPExcel_Shared_String::Substring($pValue,0,28); + } + } elseif ($i == 100) { + if (PHPExcel_Shared_String::CountCharacters($pValue) > 27) { + $pValue = PHPExcel_Shared_String::Substring($pValue,0,27); + } + } + } + + $altTitle = $pValue . ' ' . $i; + return $this->setTitle($altTitle,$updateFormulaCellReferences); + } + } + + // Set title + $this->_title = $pValue; + $this->_dirty = true; + + if ($this->_parent) { + // New title + $newTitle = $this->getTitle(); + PHPExcel_Calculation::getInstance($this->_parent) + ->renameCalculationCacheForWorksheet($oldTitle, $newTitle); + if ($updateFormulaCellReferences) + PHPExcel_ReferenceHelper::getInstance()->updateNamedFormulas($this->_parent, $oldTitle, $newTitle); + } + + return $this; + } + + /** + * Get sheet state + * + * @return string Sheet state (visible, hidden, veryHidden) + */ + public function getSheetState() { + return $this->_sheetState; + } + + /** + * Set sheet state + * + * @param string $value Sheet state (visible, hidden, veryHidden) + * @return PHPExcel_Worksheet + */ + public function setSheetState($value = PHPExcel_Worksheet::SHEETSTATE_VISIBLE) { + $this->_sheetState = $value; + return $this; + } + + /** + * Get page setup + * + * @return PHPExcel_Worksheet_PageSetup + */ + public function getPageSetup() + { + return $this->_pageSetup; + } + + /** + * Set page setup + * + * @param PHPExcel_Worksheet_PageSetup $pValue + * @return PHPExcel_Worksheet + */ + public function setPageSetup(PHPExcel_Worksheet_PageSetup $pValue) + { + $this->_pageSetup = $pValue; + return $this; + } + + /** + * Get page margins + * + * @return PHPExcel_Worksheet_PageMargins + */ + public function getPageMargins() + { + return $this->_pageMargins; + } + + /** + * Set page margins + * + * @param PHPExcel_Worksheet_PageMargins $pValue + * @return PHPExcel_Worksheet + */ + public function setPageMargins(PHPExcel_Worksheet_PageMargins $pValue) + { + $this->_pageMargins = $pValue; + return $this; + } + + /** + * Get page header/footer + * + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function getHeaderFooter() + { + return $this->_headerFooter; + } + + /** + * Set page header/footer + * + * @param PHPExcel_Worksheet_HeaderFooter $pValue + * @return PHPExcel_Worksheet + */ + public function setHeaderFooter(PHPExcel_Worksheet_HeaderFooter $pValue) + { + $this->_headerFooter = $pValue; + return $this; + } + + /** + * Get sheet view + * + * @return PHPExcel_Worksheet_SheetView + */ + public function getSheetView() + { + return $this->_sheetView; + } + + /** + * Set sheet view + * + * @param PHPExcel_Worksheet_SheetView $pValue + * @return PHPExcel_Worksheet + */ + public function setSheetView(PHPExcel_Worksheet_SheetView $pValue) + { + $this->_sheetView = $pValue; + return $this; + } + + /** + * Get Protection + * + * @return PHPExcel_Worksheet_Protection + */ + public function getProtection() + { + return $this->_protection; + } + + /** + * Set Protection + * + * @param PHPExcel_Worksheet_Protection $pValue + * @return PHPExcel_Worksheet + */ + public function setProtection(PHPExcel_Worksheet_Protection $pValue) + { + $this->_protection = $pValue; + $this->_dirty = true; + + return $this; + } + + /** + * Get highest worksheet column + * + * @param string $row Return the data highest column for the specified row, + * or the highest column of any row if no row number is passed + * @return string Highest column name + */ + public function getHighestColumn($row = null) + { + if ($row == null) { + return $this->_cachedHighestColumn; + } + return $this->getHighestDataColumn($row); + } + + /** + * Get highest worksheet column that contains data + * + * @param string $row Return the highest data column for the specified row, + * or the highest data column of any row if no row number is passed + * @return string Highest column name that contains data + */ + public function getHighestDataColumn($row = null) + { + return $this->_cellCollection->getHighestColumn($row); + } + + /** + * Get highest worksheet row + * + * @param string $column Return the highest data row for the specified column, + * or the highest row of any column if no column letter is passed + * @return int Highest row number + */ + public function getHighestRow($column = null) + { + if ($column == null) { + return $this->_cachedHighestRow; + } + return $this->getHighestDataRow($column); + } + + /** + * Get highest worksheet row that contains data + * + * @param string $column Return the highest data row for the specified column, + * or the highest data row of any column if no column letter is passed + * @return string Highest row number that contains data + */ + public function getHighestDataRow($column = null) + { + return $this->_cellCollection->getHighestRow($column); + } + + /** + * Get highest worksheet column and highest row that have cell records + * + * @return array Highest column name and highest row number + */ + public function getHighestRowAndColumn() + { + return $this->_cellCollection->getHighestRowAndColumn(); + } + + /** + * Set a cell value + * + * @param string $pCoordinate Coordinate of the cell + * @param mixed $pValue Value of the cell + * @param bool $returnCell Return the worksheet (false, default) or the cell (true) + * @return PHPExcel_Worksheet|PHPExcel_Cell Depending on the last parameter being specified + */ + public function setCellValue($pCoordinate = 'A1', $pValue = null, $returnCell = false) + { + $cell = $this->getCell($pCoordinate)->setValue($pValue); + return ($returnCell) ? $cell : $this; + } + + /** + * Set a cell value by using numeric cell coordinates + * + * @param string $pColumn Numeric column coordinate of the cell (A = 0) + * @param string $pRow Numeric row coordinate of the cell + * @param mixed $pValue Value of the cell + * @param bool $returnCell Return the worksheet (false, default) or the cell (true) + * @return PHPExcel_Worksheet|PHPExcel_Cell Depending on the last parameter being specified + */ + public function setCellValueByColumnAndRow($pColumn = 0, $pRow = 1, $pValue = null, $returnCell = false) + { + $cell = $this->getCellByColumnAndRow($pColumn, $pRow)->setValue($pValue); + return ($returnCell) ? $cell : $this; + } + + /** + * Set a cell value + * + * @param string $pCoordinate Coordinate of the cell + * @param mixed $pValue Value of the cell + * @param string $pDataType Explicit data type + * @param bool $returnCell Return the worksheet (false, default) or the cell (true) + * @return PHPExcel_Worksheet|PHPExcel_Cell Depending on the last parameter being specified + */ + public function setCellValueExplicit($pCoordinate = 'A1', $pValue = null, $pDataType = PHPExcel_Cell_DataType::TYPE_STRING, $returnCell = false) + { + // Set value + $cell = $this->getCell($pCoordinate)->setValueExplicit($pValue, $pDataType); + return ($returnCell) ? $cell : $this; + } + + /** + * Set a cell value by using numeric cell coordinates + * + * @param string $pColumn Numeric column coordinate of the cell + * @param string $pRow Numeric row coordinate of the cell + * @param mixed $pValue Value of the cell + * @param string $pDataType Explicit data type + * @param bool $returnCell Return the worksheet (false, default) or the cell (true) + * @return PHPExcel_Worksheet|PHPExcel_Cell Depending on the last parameter being specified + */ + public function setCellValueExplicitByColumnAndRow($pColumn = 0, $pRow = 1, $pValue = null, $pDataType = PHPExcel_Cell_DataType::TYPE_STRING, $returnCell = false) + { + $cell = $this->getCellByColumnAndRow($pColumn, $pRow)->setValueExplicit($pValue, $pDataType); + return ($returnCell) ? $cell : $this; + } + + /** + * Get cell at a specific coordinate + * + * @param string $pCoordinate Coordinate of the cell + * @throws PHPExcel_Exception + * @return PHPExcel_Cell Cell that was found + */ + public function getCell($pCoordinate = 'A1') + { + // Check cell collection + if ($this->_cellCollection->isDataSet($pCoordinate)) { + return $this->_cellCollection->getCacheData($pCoordinate); + } + + // Worksheet reference? + if (strpos($pCoordinate, '!') !== false) { + $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pCoordinate, true); + return $this->_parent->getSheetByName($worksheetReference[0])->getCell($worksheetReference[1]); + } + + // Named range? + if ((!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $pCoordinate, $matches)) && + (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_NAMEDRANGE.'$/i', $pCoordinate, $matches))) { + $namedRange = PHPExcel_NamedRange::resolveRange($pCoordinate, $this); + if ($namedRange !== NULL) { + $pCoordinate = $namedRange->getRange(); + return $namedRange->getWorksheet()->getCell($pCoordinate); + } + } + + // Uppercase coordinate + $pCoordinate = strtoupper($pCoordinate); + + if (strpos($pCoordinate, ':') !== false || strpos($pCoordinate, ',') !== false) { + throw new PHPExcel_Exception('Cell coordinate can not be a range of cells.'); + } elseif (strpos($pCoordinate, '$') !== false) { + throw new PHPExcel_Exception('Cell coordinate must not be absolute.'); + } + + // Create new cell object + return $this->_createNewCell($pCoordinate); + } + + /** + * Get cell at a specific coordinate by using numeric cell coordinates + * + * @param string $pColumn Numeric column coordinate of the cell + * @param string $pRow Numeric row coordinate of the cell + * @return PHPExcel_Cell Cell that was found + */ + public function getCellByColumnAndRow($pColumn = 0, $pRow = 1) + { + $columnLetter = PHPExcel_Cell::stringFromColumnIndex($pColumn); + $coordinate = $columnLetter . $pRow; + + if ($this->_cellCollection->isDataSet($coordinate)) { + return $this->_cellCollection->getCacheData($coordinate); + } + + return $this->_createNewCell($coordinate); + } + + /** + * Create a new cell at the specified coordinate + * + * @param string $pCoordinate Coordinate of the cell + * @return PHPExcel_Cell Cell that was created + */ + private function _createNewCell($pCoordinate) + { + $cell = $this->_cellCollection->addCacheData( + $pCoordinate, + new PHPExcel_Cell( + NULL, + PHPExcel_Cell_DataType::TYPE_NULL, + $this + ) ); - $this->_parent = $parent; + $this->_cellCollectionIsSorted = false; - return $this; + // Coordinates + $aCoordinates = PHPExcel_Cell::coordinateFromString($pCoordinate); + if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < PHPExcel_Cell::columnIndexFromString($aCoordinates[0])) + $this->_cachedHighestColumn = $aCoordinates[0]; + $this->_cachedHighestRow = max($this->_cachedHighestRow, $aCoordinates[1]); + + // Cell needs appropriate xfIndex from dimensions records + // but don't create dimension records if they don't already exist + $rowDimension = $this->getRowDimension($aCoordinates[1], FALSE); + $columnDimension = $this->getColumnDimension($aCoordinates[0], FALSE); + + if ($rowDimension !== NULL && $rowDimension->getXfIndex() > 0) { + // then there is a row dimension with explicit style, assign it to the cell + $cell->setXfIndex($rowDimension->getXfIndex()); + } elseif ($columnDimension !== NULL && $columnDimension->getXfIndex() > 0) { + // then there is a column dimension, assign it to the cell + $cell->setXfIndex($columnDimension->getXfIndex()); + } + + return $cell; } + + /** + * Does the cell at a specific coordinate exist? + * + * @param string $pCoordinate Coordinate of the cell + * @throws PHPExcel_Exception + * @return boolean + */ + public function cellExists($pCoordinate = 'A1') + { + // Worksheet reference? + if (strpos($pCoordinate, '!') !== false) { + $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pCoordinate, true); + return $this->_parent->getSheetByName($worksheetReference[0])->cellExists($worksheetReference[1]); + } - /** - * Get title - * - * @return string - */ - public function getTitle() - { - return $this->_title; - } + // Named range? + if ((!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $pCoordinate, $matches)) && + (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_NAMEDRANGE.'$/i', $pCoordinate, $matches))) { + $namedRange = PHPExcel_NamedRange::resolveRange($pCoordinate, $this); + if ($namedRange !== NULL) { + $pCoordinate = $namedRange->getRange(); + if ($this->getHashCode() != $namedRange->getWorksheet()->getHashCode()) { + if (!$namedRange->getLocalOnly()) { + return $namedRange->getWorksheet()->cellExists($pCoordinate); + } else { + throw new PHPExcel_Exception('Named range ' . $namedRange->getName() . ' is not accessible from within sheet ' . $this->getTitle()); + } + } + } + else { return false; } + } - /** - * Set title + // Uppercase coordinate + $pCoordinate = strtoupper($pCoordinate); + + if (strpos($pCoordinate,':') !== false || strpos($pCoordinate,',') !== false) { + throw new PHPExcel_Exception('Cell coordinate can not be a range of cells.'); + } elseif (strpos($pCoordinate,'$') !== false) { + throw new PHPExcel_Exception('Cell coordinate must not be absolute.'); + } else { + // Coordinates + $aCoordinates = PHPExcel_Cell::coordinateFromString($pCoordinate); + + // Cell exists? + return $this->_cellCollection->isDataSet($pCoordinate); + } + } + + /** + * Cell at a specific coordinate by using numeric cell coordinates exists? + * + * @param string $pColumn Numeric column coordinate of the cell + * @param string $pRow Numeric row coordinate of the cell + * @return boolean + */ + public function cellExistsByColumnAndRow($pColumn = 0, $pRow = 1) + { + return $this->cellExists(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); + } + + /** + * Get row dimension at a specific row + * + * @param int $pRow Numeric index of the row + * @return PHPExcel_Worksheet_RowDimension + */ + public function getRowDimension($pRow = 1, $create = TRUE) + { + // Found + $found = null; + + // Get row dimension + if (!isset($this->_rowDimensions[$pRow])) { + if (!$create) + return NULL; + $this->_rowDimensions[$pRow] = new PHPExcel_Worksheet_RowDimension($pRow); + + $this->_cachedHighestRow = max($this->_cachedHighestRow,$pRow); + } + return $this->_rowDimensions[$pRow]; + } + + /** + * Get column dimension at a specific column + * + * @param string $pColumn String index of the column + * @return PHPExcel_Worksheet_ColumnDimension + */ + public function getColumnDimension($pColumn = 'A', $create = TRUE) + { + // Uppercase coordinate + $pColumn = strtoupper($pColumn); + + // Fetch dimensions + if (!isset($this->_columnDimensions[$pColumn])) { + if (!$create) + return NULL; + $this->_columnDimensions[$pColumn] = new PHPExcel_Worksheet_ColumnDimension($pColumn); + + if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < PHPExcel_Cell::columnIndexFromString($pColumn)) + $this->_cachedHighestColumn = $pColumn; + } + return $this->_columnDimensions[$pColumn]; + } + + /** + * Get column dimension at a specific column by using numeric cell coordinates + * + * @param string $pColumn Numeric column coordinate of the cell + * @return PHPExcel_Worksheet_ColumnDimension + */ + public function getColumnDimensionByColumn($pColumn = 0) + { + return $this->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($pColumn)); + } + + /** + * Get styles + * + * @return PHPExcel_Style[] + */ + public function getStyles() + { + return $this->_styles; + } + + /** + * Get default style of workbook. + * + * @deprecated + * @return PHPExcel_Style + * @throws PHPExcel_Exception + */ + public function getDefaultStyle() + { + return $this->_parent->getDefaultStyle(); + } + + /** + * Set default style - should only be used by PHPExcel_IReader implementations! + * + * @deprecated + * @param PHPExcel_Style $pValue + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setDefaultStyle(PHPExcel_Style $pValue) + { + $this->_parent->getDefaultStyle()->applyFromArray(array( + 'font' => array( + 'name' => $pValue->getFont()->getName(), + 'size' => $pValue->getFont()->getSize(), + ), + )); + return $this; + } + + /** + * Get style for cell + * + * @param string $pCellCoordinate Cell coordinate to get style for + * @return PHPExcel_Style + * @throws PHPExcel_Exception + */ + public function getStyle($pCellCoordinate = 'A1') + { + // set this sheet as active + $this->_parent->setActiveSheetIndex($this->_parent->getIndex($this)); + + // set cell coordinate as active + $this->setSelectedCells($pCellCoordinate); + + return $this->_parent->getCellXfSupervisor(); + } + + /** + * Get conditional styles for a cell + * + * @param string $pCoordinate + * @return PHPExcel_Style_Conditional[] + */ + public function getConditionalStyles($pCoordinate = 'A1') + { + if (!isset($this->_conditionalStylesCollection[$pCoordinate])) { + $this->_conditionalStylesCollection[$pCoordinate] = array(); + } + return $this->_conditionalStylesCollection[$pCoordinate]; + } + + /** + * Do conditional styles exist for this cell? + * + * @param string $pCoordinate + * @return boolean + */ + public function conditionalStylesExists($pCoordinate = 'A1') + { + if (isset($this->_conditionalStylesCollection[$pCoordinate])) { + return true; + } + return false; + } + + /** + * Removes conditional styles for a cell + * + * @param string $pCoordinate + * @return PHPExcel_Worksheet + */ + public function removeConditionalStyles($pCoordinate = 'A1') + { + unset($this->_conditionalStylesCollection[$pCoordinate]); + return $this; + } + + /** + * Get collection of conditional styles + * + * @return array + */ + public function getConditionalStylesCollection() + { + return $this->_conditionalStylesCollection; + } + + /** + * Set conditional styles + * + * @param $pCoordinate string E.g. 'A1' + * @param $pValue PHPExcel_Style_Conditional[] + * @return PHPExcel_Worksheet + */ + public function setConditionalStyles($pCoordinate = 'A1', $pValue) + { + $this->_conditionalStylesCollection[$pCoordinate] = $pValue; + return $this; + } + + /** + * Get style for cell by using numeric cell coordinates + * + * @param int $pColumn Numeric column coordinate of the cell + * @param int $pRow Numeric row coordinate of the cell + * @return PHPExcel_Style + */ + public function getStyleByColumnAndRow($pColumn = 0, $pRow = 1) + { + return $this->getStyle(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); + } + + /** + * Set shared cell style to a range of cells + * + * Please note that this will overwrite existing cell styles for cells in range! + * + * @deprecated + * @param PHPExcel_Style $pSharedCellStyle Cell style to share + * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setSharedStyle(PHPExcel_Style $pSharedCellStyle = null, $pRange = '') + { + $this->duplicateStyle($pSharedCellStyle, $pRange); + return $this; + } + + /** + * Duplicate cell style to a range of cells + * + * Please note that this will overwrite existing cell styles for cells in range! + * + * @param PHPExcel_Style $pCellStyle Cell style to duplicate + * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function duplicateStyle(PHPExcel_Style $pCellStyle = null, $pRange = '') + { + // make sure we have a real style and not supervisor + $style = $pCellStyle->getIsSupervisor() ? $pCellStyle->getSharedComponent() : $pCellStyle; + + // Add the style to the workbook if necessary + $workbook = $this->_parent; + if ($existingStyle = $this->_parent->getCellXfByHashCode($pCellStyle->getHashCode())) { + // there is already such cell Xf in our collection + $xfIndex = $existingStyle->getIndex(); + } else { + // we don't have such a cell Xf, need to add + $workbook->addCellXf($pCellStyle); + $xfIndex = $pCellStyle->getIndex(); + } + + // Calculate range outer borders + list($rangeStart, $rangeEnd) = PHPExcel_Cell::rangeBoundaries($pRange . ':' . $pRange); + + // Make sure we can loop upwards on rows and columns + if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) { + $tmp = $rangeStart; + $rangeStart = $rangeEnd; + $rangeEnd = $tmp; + } + + // Loop through cells and apply styles + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + $this->getCell(PHPExcel_Cell::stringFromColumnIndex($col - 1) . $row)->setXfIndex($xfIndex); + } + } + + return $this; + } + + /** + * Duplicate conditional style to a range of cells + * + * Please note that this will overwrite existing cell styles for cells in range! + * + * @param array of PHPExcel_Style_Conditional $pCellStyle Cell style to duplicate + * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function duplicateConditionalStyle(array $pCellStyle = null, $pRange = '') + { + foreach($pCellStyle as $cellStyle) { + if (!($cellStyle instanceof PHPExcel_Style_Conditional)) { + throw new PHPExcel_Exception('Style is not a conditional style'); + } + } + + // Calculate range outer borders + list($rangeStart, $rangeEnd) = PHPExcel_Cell::rangeBoundaries($pRange . ':' . $pRange); + + // Make sure we can loop upwards on rows and columns + if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) { + $tmp = $rangeStart; + $rangeStart = $rangeEnd; + $rangeEnd = $tmp; + } + + // Loop through cells and apply styles + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + $this->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($col - 1) . $row, $pCellStyle); + } + } + + return $this; + } + + /** + * Duplicate cell style array to a range of cells + * + * Please note that this will overwrite existing cell styles for cells in range, + * if they are in the styles array. For example, if you decide to set a range of + * cells to font bold, only include font bold in the styles array. + * + * @deprecated + * @param array $pStyles Array containing style information + * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") + * @param boolean $pAdvanced Advanced mode for setting borders. + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function duplicateStyleArray($pStyles = null, $pRange = '', $pAdvanced = true) + { + $this->getStyle($pRange)->applyFromArray($pStyles, $pAdvanced); + return $this; + } + + /** + * Set break on a cell + * + * @param string $pCell Cell coordinate (e.g. A1) + * @param int $pBreak Break type (type of PHPExcel_Worksheet::BREAK_*) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setBreak($pCell = 'A1', $pBreak = PHPExcel_Worksheet::BREAK_NONE) + { + // Uppercase coordinate + $pCell = strtoupper($pCell); + + if ($pCell != '') { + if ($pBreak == PHPExcel_Worksheet::BREAK_NONE) { + if (isset($this->_breaks[$pCell])) { + unset($this->_breaks[$pCell]); + } + } else { + $this->_breaks[$pCell] = $pBreak; + } + } else { + throw new PHPExcel_Exception('No cell coordinate specified.'); + } + + return $this; + } + + /** + * Set break on a cell by using numeric cell coordinates + * + * @param integer $pColumn Numeric column coordinate of the cell + * @param integer $pRow Numeric row coordinate of the cell + * @param integer $pBreak Break type (type of PHPExcel_Worksheet::BREAK_*) + * @return PHPExcel_Worksheet + */ + public function setBreakByColumnAndRow($pColumn = 0, $pRow = 1, $pBreak = PHPExcel_Worksheet::BREAK_NONE) + { + return $this->setBreak(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow, $pBreak); + } + + /** + * Get breaks + * + * @return array[] + */ + public function getBreaks() + { + return $this->_breaks; + } + + /** + * Set merge on a cell range + * + * @param string $pRange Cell range (e.g. A1:E1) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function mergeCells($pRange = 'A1:A1') + { + // Uppercase coordinate + $pRange = strtoupper($pRange); + + if (strpos($pRange,':') !== false) { + $this->_mergeCells[$pRange] = $pRange; + + // make sure cells are created + + // get the cells in the range + $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($pRange); + + // create upper left cell if it does not already exist + $upperLeft = $aReferences[0]; + if (!$this->cellExists($upperLeft)) { + $this->getCell($upperLeft)->setValueExplicit(null, PHPExcel_Cell_DataType::TYPE_NULL); + } + + // create or blank out the rest of the cells in the range + $count = count($aReferences); + for ($i = 1; $i < $count; $i++) { + $this->getCell($aReferences[$i])->setValueExplicit(null, PHPExcel_Cell_DataType::TYPE_NULL); + } + + } else { + throw new PHPExcel_Exception('Merge must be set on a range of cells.'); + } + + return $this; + } + + /** + * Set merge on a cell range by using numeric cell coordinates + * + * @param int $pColumn1 Numeric column coordinate of the first cell + * @param int $pRow1 Numeric row coordinate of the first cell + * @param int $pColumn2 Numeric column coordinate of the last cell + * @param int $pRow2 Numeric row coordinate of the last cell + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function mergeCellsByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1) + { + $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 . ':' . PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2; + return $this->mergeCells($cellRange); + } + + /** + * Remove merge on a cell range + * + * @param string $pRange Cell range (e.g. A1:E1) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function unmergeCells($pRange = 'A1:A1') + { + // Uppercase coordinate + $pRange = strtoupper($pRange); + + if (strpos($pRange,':') !== false) { + if (isset($this->_mergeCells[$pRange])) { + unset($this->_mergeCells[$pRange]); + } else { + throw new PHPExcel_Exception('Cell range ' . $pRange . ' not known as merged.'); + } + } else { + throw new PHPExcel_Exception('Merge can only be removed from a range of cells.'); + } + + return $this; + } + + /** + * Remove merge on a cell range by using numeric cell coordinates + * + * @param int $pColumn1 Numeric column coordinate of the first cell + * @param int $pRow1 Numeric row coordinate of the first cell + * @param int $pColumn2 Numeric column coordinate of the last cell + * @param int $pRow2 Numeric row coordinate of the last cell + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function unmergeCellsByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1) + { + $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 . ':' . PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2; + return $this->unmergeCells($cellRange); + } + + /** + * Get merge cells array. + * + * @return array[] + */ + public function getMergeCells() + { + return $this->_mergeCells; + } + + /** + * Set merge cells array for the entire sheet. Use instead mergeCells() to merge + * a single cell range. + * + * @param array + */ + public function setMergeCells($pValue = array()) + { + $this->_mergeCells = $pValue; + + return $this; + } + + /** + * Set protection on a cell range + * + * @param string $pRange Cell (e.g. A1) or cell range (e.g. A1:E1) + * @param string $pPassword Password to unlock the protection + * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function protectCells($pRange = 'A1', $pPassword = '', $pAlreadyHashed = false) + { + // Uppercase coordinate + $pRange = strtoupper($pRange); + + if (!$pAlreadyHashed) { + $pPassword = PHPExcel_Shared_PasswordHasher::hashPassword($pPassword); + } + $this->_protectedCells[$pRange] = $pPassword; + + return $this; + } + + /** + * Set protection on a cell range by using numeric cell coordinates + * + * @param int $pColumn1 Numeric column coordinate of the first cell + * @param int $pRow1 Numeric row coordinate of the first cell + * @param int $pColumn2 Numeric column coordinate of the last cell + * @param int $pRow2 Numeric row coordinate of the last cell + * @param string $pPassword Password to unlock the protection + * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function protectCellsByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1, $pPassword = '', $pAlreadyHashed = false) + { + $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 . ':' . PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2; + return $this->protectCells($cellRange, $pPassword, $pAlreadyHashed); + } + + /** + * Remove protection on a cell range + * + * @param string $pRange Cell (e.g. A1) or cell range (e.g. A1:E1) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function unprotectCells($pRange = 'A1') + { + // Uppercase coordinate + $pRange = strtoupper($pRange); + + if (isset($this->_protectedCells[$pRange])) { + unset($this->_protectedCells[$pRange]); + } else { + throw new PHPExcel_Exception('Cell range ' . $pRange . ' not known as protected.'); + } + return $this; + } + + /** + * Remove protection on a cell range by using numeric cell coordinates + * + * @param int $pColumn1 Numeric column coordinate of the first cell + * @param int $pRow1 Numeric row coordinate of the first cell + * @param int $pColumn2 Numeric column coordinate of the last cell + * @param int $pRow2 Numeric row coordinate of the last cell + * @param string $pPassword Password to unlock the protection + * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function unprotectCellsByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1, $pPassword = '', $pAlreadyHashed = false) + { + $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 . ':' . PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2; + return $this->unprotectCells($cellRange, $pPassword, $pAlreadyHashed); + } + + /** + * Get protected cells + * + * @return array[] + */ + public function getProtectedCells() + { + return $this->_protectedCells; + } + + /** + * Get Autofilter + * + * @return PHPExcel_Worksheet_AutoFilter + */ + public function getAutoFilter() + { + return $this->_autoFilter; + } + + /** + * Set AutoFilter + * + * @param PHPExcel_Worksheet_AutoFilter|string $pValue + * A simple string containing a Cell range like 'A1:E10' is permitted for backward compatibility + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setAutoFilter($pValue) + { + if (is_string($pValue)) { + $this->_autoFilter->setRange($pValue); + } elseif(is_object($pValue) && ($pValue instanceof PHPExcel_Worksheet_AutoFilter)) { + $this->_autoFilter = $pValue; + } + return $this; + } + + /** + * Set Autofilter Range by using numeric cell coordinates + * + * @param integer $pColumn1 Numeric column coordinate of the first cell + * @param integer $pRow1 Numeric row coordinate of the first cell + * @param integer $pColumn2 Numeric column coordinate of the second cell + * @param integer $pRow2 Numeric row coordinate of the second cell + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setAutoFilterByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1) + { + return $this->setAutoFilter( + PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 + . ':' . + PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2 + ); + } + + /** + * Remove autofilter + * + * @return PHPExcel_Worksheet + */ + public function removeAutoFilter() + { + $this->_autoFilter->setRange(NULL); + return $this; + } + + /** + * Get Freeze Pane + * + * @return string + */ + public function getFreezePane() + { + return $this->_freezePane; + } + + /** + * Freeze Pane + * + * @param string $pCell Cell (i.e. A2) + * Examples: + * A2 will freeze the rows above cell A2 (i.e row 1) + * B1 will freeze the columns to the left of cell B1 (i.e column A) + * B2 will freeze the rows above and to the left of cell A2 + * (i.e row 1 and column A) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function freezePane($pCell = '') + { + // Uppercase coordinate + $pCell = strtoupper($pCell); + + if (strpos($pCell,':') === false && strpos($pCell,',') === false) { + $this->_freezePane = $pCell; + } else { + throw new PHPExcel_Exception('Freeze pane can not be set on a range of cells.'); + } + return $this; + } + + /** + * Freeze Pane by using numeric cell coordinates + * + * @param int $pColumn Numeric column coordinate of the cell + * @param int $pRow Numeric row coordinate of the cell + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function freezePaneByColumnAndRow($pColumn = 0, $pRow = 1) + { + return $this->freezePane(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); + } + + /** + * Unfreeze Pane + * + * @return PHPExcel_Worksheet + */ + public function unfreezePane() + { + return $this->freezePane(''); + } + + /** + * Insert a new row, updating all possible related data + * + * @param int $pBefore Insert before this one + * @param int $pNumRows Number of rows to insert + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function insertNewRowBefore($pBefore = 1, $pNumRows = 1) { + if ($pBefore >= 1) { + $objReferenceHelper = PHPExcel_ReferenceHelper::getInstance(); + $objReferenceHelper->insertNewBefore('A' . $pBefore, 0, $pNumRows, $this); + } else { + throw new PHPExcel_Exception("Rows can only be inserted before at least row 1."); + } + return $this; + } + + /** + * Insert a new column, updating all possible related data + * + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to insert + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function insertNewColumnBefore($pBefore = 'A', $pNumCols = 1) { + if (!is_numeric($pBefore)) { + $objReferenceHelper = PHPExcel_ReferenceHelper::getInstance(); + $objReferenceHelper->insertNewBefore($pBefore . '1', $pNumCols, 0, $this); + } else { + throw new PHPExcel_Exception("Column references should not be numeric."); + } + return $this; + } + + /** + * Insert a new column, updating all possible related data + * + * @param int $pBefore Insert before this one (numeric column coordinate of the cell) + * @param int $pNumCols Number of columns to insert + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function insertNewColumnBeforeByIndex($pBefore = 0, $pNumCols = 1) { + if ($pBefore >= 0) { + return $this->insertNewColumnBefore(PHPExcel_Cell::stringFromColumnIndex($pBefore), $pNumCols); + } else { + throw new PHPExcel_Exception("Columns can only be inserted before at least column A (0)."); + } + } + + /** + * Delete a row, updating all possible related data + * + * @param int $pRow Remove starting with this one + * @param int $pNumRows Number of rows to remove + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function removeRow($pRow = 1, $pNumRows = 1) { + if ($pRow >= 1) { + $objReferenceHelper = PHPExcel_ReferenceHelper::getInstance(); + $objReferenceHelper->insertNewBefore('A' . ($pRow + $pNumRows), 0, -$pNumRows, $this); + } else { + throw new PHPExcel_Exception("Rows to be deleted should at least start from row 1."); + } + return $this; + } + + /** + * Remove a column, updating all possible related data + * + * @param int $pColumn Remove starting with this one + * @param int $pNumCols Number of columns to remove + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function removeColumn($pColumn = 'A', $pNumCols = 1) { + if (!is_numeric($pColumn)) { + $pColumn = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($pColumn) - 1 + $pNumCols); + $objReferenceHelper = PHPExcel_ReferenceHelper::getInstance(); + $objReferenceHelper->insertNewBefore($pColumn . '1', -$pNumCols, 0, $this); + } else { + throw new PHPExcel_Exception("Column references should not be numeric."); + } + return $this; + } + + /** + * Remove a column, updating all possible related data + * + * @param int $pColumn Remove starting with this one (numeric column coordinate of the cell) + * @param int $pNumCols Number of columns to remove + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function removeColumnByIndex($pColumn = 0, $pNumCols = 1) { + if ($pColumn >= 0) { + return $this->removeColumn(PHPExcel_Cell::stringFromColumnIndex($pColumn), $pNumCols); + } else { + throw new PHPExcel_Exception("Columns to be deleted should at least start from column 0"); + } + } + + /** + * Show gridlines? + * + * @return boolean + */ + public function getShowGridlines() { + return $this->_showGridlines; + } + + /** + * Set show gridlines + * + * @param boolean $pValue Show gridlines (true/false) + * @return PHPExcel_Worksheet + */ + public function setShowGridlines($pValue = false) { + $this->_showGridlines = $pValue; + return $this; + } + + /** + * Print gridlines? + * + * @return boolean + */ + public function getPrintGridlines() { + return $this->_printGridlines; + } + + /** + * Set print gridlines + * + * @param boolean $pValue Print gridlines (true/false) + * @return PHPExcel_Worksheet + */ + public function setPrintGridlines($pValue = false) { + $this->_printGridlines = $pValue; + return $this; + } + + /** + * Show row and column headers? + * + * @return boolean + */ + public function getShowRowColHeaders() { + return $this->_showRowColHeaders; + } + + /** + * Set show row and column headers + * + * @param boolean $pValue Show row and column headers (true/false) + * @return PHPExcel_Worksheet + */ + public function setShowRowColHeaders($pValue = false) { + $this->_showRowColHeaders = $pValue; + return $this; + } + + /** + * Show summary below? (Row/Column outlining) + * + * @return boolean + */ + public function getShowSummaryBelow() { + return $this->_showSummaryBelow; + } + + /** + * Set show summary below + * + * @param boolean $pValue Show summary below (true/false) + * @return PHPExcel_Worksheet + */ + public function setShowSummaryBelow($pValue = true) { + $this->_showSummaryBelow = $pValue; + return $this; + } + + /** + * Show summary right? (Row/Column outlining) + * + * @return boolean + */ + public function getShowSummaryRight() { + return $this->_showSummaryRight; + } + + /** + * Set show summary right + * + * @param boolean $pValue Show summary right (true/false) + * @return PHPExcel_Worksheet + */ + public function setShowSummaryRight($pValue = true) { + $this->_showSummaryRight = $pValue; + return $this; + } + + /** + * Get comments + * + * @return PHPExcel_Comment[] + */ + public function getComments() + { + return $this->_comments; + } + + /** + * Set comments array for the entire sheet. + * + * @param array of PHPExcel_Comment + * @return PHPExcel_Worksheet + */ + public function setComments($pValue = array()) + { + $this->_comments = $pValue; + + return $this; + } + + /** + * Get comment for cell + * + * @param string $pCellCoordinate Cell coordinate to get comment for + * @return PHPExcel_Comment + * @throws PHPExcel_Exception + */ + public function getComment($pCellCoordinate = 'A1') + { + // Uppercase coordinate + $pCellCoordinate = strtoupper($pCellCoordinate); + + if (strpos($pCellCoordinate,':') !== false || strpos($pCellCoordinate,',') !== false) { + throw new PHPExcel_Exception('Cell coordinate string can not be a range of cells.'); + } else if (strpos($pCellCoordinate,'$') !== false) { + throw new PHPExcel_Exception('Cell coordinate string must not be absolute.'); + } else if ($pCellCoordinate == '') { + throw new PHPExcel_Exception('Cell coordinate can not be zero-length string.'); + } else { + // Check if we already have a comment for this cell. + // If not, create a new comment. + if (isset($this->_comments[$pCellCoordinate])) { + return $this->_comments[$pCellCoordinate]; + } else { + $newComment = new PHPExcel_Comment(); + $this->_comments[$pCellCoordinate] = $newComment; + return $newComment; + } + } + } + + /** + * Get comment for cell by using numeric cell coordinates + * + * @param int $pColumn Numeric column coordinate of the cell + * @param int $pRow Numeric row coordinate of the cell + * @return PHPExcel_Comment + */ + public function getCommentByColumnAndRow($pColumn = 0, $pRow = 1) + { + return $this->getComment(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); + } + + /** + * Get selected cell + * + * @deprecated + * @return string + */ + public function getSelectedCell() + { + return $this->getSelectedCells(); + } + + /** + * Get active cell + * + * @return string Example: 'A1' + */ + public function getActiveCell() + { + return $this->_activeCell; + } + + /** + * Get selected cells + * + * @return string + */ + public function getSelectedCells() + { + return $this->_selectedCells; + } + + /** + * Selected cell + * + * @param string $pCoordinate Cell (i.e. A1) + * @return PHPExcel_Worksheet + */ + public function setSelectedCell($pCoordinate = 'A1') + { + return $this->setSelectedCells($pCoordinate); + } + + /** + * Select a range of cells. + * + * @param string $pCoordinate Cell range, examples: 'A1', 'B2:G5', 'A:C', '3:6' + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setSelectedCells($pCoordinate = 'A1') + { + // Uppercase coordinate + $pCoordinate = strtoupper($pCoordinate); + + // Convert 'A' to 'A:A' + $pCoordinate = preg_replace('/^([A-Z]+)$/', '${1}:${1}', $pCoordinate); + + // Convert '1' to '1:1' + $pCoordinate = preg_replace('/^([0-9]+)$/', '${1}:${1}', $pCoordinate); + + // Convert 'A:C' to 'A1:C1048576' + $pCoordinate = preg_replace('/^([A-Z]+):([A-Z]+)$/', '${1}1:${2}1048576', $pCoordinate); + + // Convert '1:3' to 'A1:XFD3' + $pCoordinate = preg_replace('/^([0-9]+):([0-9]+)$/', 'A${1}:XFD${2}', $pCoordinate); + + if (strpos($pCoordinate,':') !== false || strpos($pCoordinate,',') !== false) { + list($first, ) = PHPExcel_Cell::splitRange($pCoordinate); + $this->_activeCell = $first[0]; + } else { + $this->_activeCell = $pCoordinate; + } + $this->_selectedCells = $pCoordinate; + return $this; + } + + /** + * Selected cell by using numeric cell coordinates + * + * @param int $pColumn Numeric column coordinate of the cell + * @param int $pRow Numeric row coordinate of the cell + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setSelectedCellByColumnAndRow($pColumn = 0, $pRow = 1) + { + return $this->setSelectedCells(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); + } + + /** + * Get right-to-left + * + * @return boolean + */ + public function getRightToLeft() { + return $this->_rightToLeft; + } + + /** + * Set right-to-left + * + * @param boolean $value Right-to-left true/false + * @return PHPExcel_Worksheet + */ + public function setRightToLeft($value = false) { + $this->_rightToLeft = $value; + return $this; + } + + /** + * Fill worksheet from values in array + * + * @param array $source Source array + * @param mixed $nullValue Value in source array that stands for blank cell + * @param string $startCell Insert array starting from this cell address as the top left coordinate + * @param boolean $strictNullComparison Apply strict comparison when testing for null values in the array + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function fromArray($source = null, $nullValue = null, $startCell = 'A1', $strictNullComparison = false) { + if (is_array($source)) { + // Convert a 1-D array to 2-D (for ease of looping) + if (!is_array(end($source))) { + $source = array($source); + } + + // start coordinate + list ($startColumn, $startRow) = PHPExcel_Cell::coordinateFromString($startCell); + + // Loop through $source + foreach ($source as $rowData) { + $currentColumn = $startColumn; + foreach($rowData as $cellValue) { + if ($strictNullComparison) { + if ($cellValue !== $nullValue) { + // Set cell value + $this->getCell($currentColumn . $startRow)->setValue($cellValue); + } + } else { + if ($cellValue != $nullValue) { + // Set cell value + $this->getCell($currentColumn . $startRow)->setValue($cellValue); + } + } + ++$currentColumn; + } + ++$startRow; + } + } else { + throw new PHPExcel_Exception("Parameter \$source should be an array."); + } + return $this; + } + + /** + * Create array from a range of cells + * + * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") + * @param mixed $nullValue Value returned in the array entry if a cell doesn't exist + * @param boolean $calculateFormulas Should formulas be calculated? + * @param boolean $formatData Should formatting be applied to cell values? + * @param boolean $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero + * True - Return rows and columns indexed by their actual row and column IDs + * @return array + */ + public function rangeToArray($pRange = 'A1', $nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) { + // Returnvalue + $returnValue = array(); + // Identify the range that we need to extract from the worksheet + list($rangeStart, $rangeEnd) = PHPExcel_Cell::rangeBoundaries($pRange); + $minCol = PHPExcel_Cell::stringFromColumnIndex($rangeStart[0] -1); + $minRow = $rangeStart[1]; + $maxCol = PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0] -1); + $maxRow = $rangeEnd[1]; + + $maxCol++; + // Loop through rows + $r = -1; + for ($row = $minRow; $row <= $maxRow; ++$row) { + $rRef = ($returnCellRef) ? $row : ++$r; + $c = -1; + // Loop through columns in the current row + for ($col = $minCol; $col != $maxCol; ++$col) { + $cRef = ($returnCellRef) ? $col : ++$c; + // Using getCell() will create a new cell if it doesn't already exist. We don't want that to happen + // so we test and retrieve directly against _cellCollection + if ($this->_cellCollection->isDataSet($col.$row)) { + // Cell exists + $cell = $this->_cellCollection->getCacheData($col.$row); + if ($cell->getValue() !== null) { + if ($cell->getValue() instanceof PHPExcel_RichText) { + $returnValue[$rRef][$cRef] = $cell->getValue()->getPlainText(); + } else { + if ($calculateFormulas) { + $returnValue[$rRef][$cRef] = $cell->getCalculatedValue(); + } else { + $returnValue[$rRef][$cRef] = $cell->getValue(); + } + } + + if ($formatData) { + $style = $this->_parent->getCellXfByIndex($cell->getXfIndex()); + $returnValue[$rRef][$cRef] = PHPExcel_Style_NumberFormat::toFormattedString( + $returnValue[$rRef][$cRef], + ($style && $style->getNumberFormat()) ? + $style->getNumberFormat()->getFormatCode() : + PHPExcel_Style_NumberFormat::FORMAT_GENERAL + ); + } + } else { + // Cell holds a NULL + $returnValue[$rRef][$cRef] = $nullValue; + } + } else { + // Cell doesn't exist + $returnValue[$rRef][$cRef] = $nullValue; + } + } + } + + // Return + return $returnValue; + } + + + /** + * Create array from a range of cells + * + * @param string $pNamedRange Name of the Named Range + * @param mixed $nullValue Value returned in the array entry if a cell doesn't exist + * @param boolean $calculateFormulas Should formulas be calculated? + * @param boolean $formatData Should formatting be applied to cell values? + * @param boolean $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero + * True - Return rows and columns indexed by their actual row and column IDs + * @return array + * @throws PHPExcel_Exception + */ + public function namedRangeToArray($pNamedRange = '', $nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) { + $namedRange = PHPExcel_NamedRange::resolveRange($pNamedRange, $this); + if ($namedRange !== NULL) { + $pWorkSheet = $namedRange->getWorksheet(); + $pCellRange = $namedRange->getRange(); + + return $pWorkSheet->rangeToArray( $pCellRange, + $nullValue, $calculateFormulas, $formatData, $returnCellRef); + } + + throw new PHPExcel_Exception('Named Range '.$pNamedRange.' does not exist.'); + } + + + /** + * Create array from worksheet + * + * @param mixed $nullValue Value returned in the array entry if a cell doesn't exist + * @param boolean $calculateFormulas Should formulas be calculated? + * @param boolean $formatData Should formatting be applied to cell values? + * @param boolean $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero + * True - Return rows and columns indexed by their actual row and column IDs + * @return array + */ + public function toArray($nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) { + // Garbage collect... + $this->garbageCollect(); + + // Identify the range that we need to extract from the worksheet + $maxCol = $this->getHighestColumn(); + $maxRow = $this->getHighestRow(); + // Return + return $this->rangeToArray( 'A1:'.$maxCol.$maxRow, + $nullValue, $calculateFormulas, $formatData, $returnCellRef); + } + + /** + * Get row iterator + * + * @param integer $startRow The row number at which to start iterating + * @return PHPExcel_Worksheet_RowIterator + */ + public function getRowIterator($startRow = 1) { + return new PHPExcel_Worksheet_RowIterator($this,$startRow); + } + + /** + * Run PHPExcel garabage collector. + * + * @return PHPExcel_Worksheet + */ + public function garbageCollect() { + // Flush cache + $this->_cellCollection->getCacheData('A1'); + // Build a reference table from images +// $imageCoordinates = array(); +// $iterator = $this->getDrawingCollection()->getIterator(); +// while ($iterator->valid()) { +// $imageCoordinates[$iterator->current()->getCoordinates()] = true; +// +// $iterator->next(); +// } +// + // Lookup highest column and highest row if cells are cleaned + $colRow = $this->_cellCollection->getHighestRowAndColumn(); + $highestRow = $colRow['row']; + $highestColumn = PHPExcel_Cell::columnIndexFromString($colRow['column']); + + // Loop through column dimensions + foreach ($this->_columnDimensions as $dimension) { + $highestColumn = max($highestColumn,PHPExcel_Cell::columnIndexFromString($dimension->getColumnIndex())); + } + + // Loop through row dimensions + foreach ($this->_rowDimensions as $dimension) { + $highestRow = max($highestRow,$dimension->getRowIndex()); + } + + // Cache values + if ($highestColumn < 0) { + $this->_cachedHighestColumn = 'A'; + } else { + $this->_cachedHighestColumn = PHPExcel_Cell::stringFromColumnIndex(--$highestColumn); + } + $this->_cachedHighestRow = $highestRow; + + // Return + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + if ($this->_dirty) { + $this->_hash = md5( $this->_title . + $this->_autoFilter . + ($this->_protection->isProtectionEnabled() ? 't' : 'f') . + __CLASS__ + ); + $this->_dirty = false; + } + return $this->_hash; + } + + /** + * Extract worksheet title from range. + * + * Example: extractSheetTitle("testSheet!A1") ==> 'A1' + * Example: extractSheetTitle("'testSheet 1'!A1", true) ==> array('testSheet 1', 'A1'); + * + * @param string $pRange Range to extract title from + * @param bool $returnRange Return range? (see example) + * @return mixed + */ + public static function extractSheetTitle($pRange, $returnRange = false) { + // Sheet title included? + if (($sep = strpos($pRange, '!')) === false) { + return ''; + } + + if ($returnRange) { + return array( trim(substr($pRange, 0, $sep),"'"), + substr($pRange, $sep + 1) + ); + } + + return substr($pRange, $sep + 1); + } + + /** + * Get hyperlink + * + * @param string $pCellCoordinate Cell coordinate to get hyperlink for + */ + public function getHyperlink($pCellCoordinate = 'A1') + { + // return hyperlink if we already have one + if (isset($this->_hyperlinkCollection[$pCellCoordinate])) { + return $this->_hyperlinkCollection[$pCellCoordinate]; + } + + // else create hyperlink + $this->_hyperlinkCollection[$pCellCoordinate] = new PHPExcel_Cell_Hyperlink(); + return $this->_hyperlinkCollection[$pCellCoordinate]; + } + + /** + * Set hyperlnk + * + * @param string $pCellCoordinate Cell coordinate to insert hyperlink + * @param PHPExcel_Cell_Hyperlink $pHyperlink + * @return PHPExcel_Worksheet + */ + public function setHyperlink($pCellCoordinate = 'A1', PHPExcel_Cell_Hyperlink $pHyperlink = null) + { + if ($pHyperlink === null) { + unset($this->_hyperlinkCollection[$pCellCoordinate]); + } else { + $this->_hyperlinkCollection[$pCellCoordinate] = $pHyperlink; + } + return $this; + } + + /** + * Hyperlink at a specific coordinate exists? + * + * @param string $pCoordinate + * @return boolean + */ + public function hyperlinkExists($pCoordinate = 'A1') + { + return isset($this->_hyperlinkCollection[$pCoordinate]); + } + + /** + * Get collection of hyperlinks + * + * @return PHPExcel_Cell_Hyperlink[] + */ + public function getHyperlinkCollection() + { + return $this->_hyperlinkCollection; + } + + /** + * Get data validation + * + * @param string $pCellCoordinate Cell coordinate to get data validation for + */ + public function getDataValidation($pCellCoordinate = 'A1') + { + // return data validation if we already have one + if (isset($this->_dataValidationCollection[$pCellCoordinate])) { + return $this->_dataValidationCollection[$pCellCoordinate]; + } + + // else create data validation + $this->_dataValidationCollection[$pCellCoordinate] = new PHPExcel_Cell_DataValidation(); + return $this->_dataValidationCollection[$pCellCoordinate]; + } + + /** + * Set data validation + * + * @param string $pCellCoordinate Cell coordinate to insert data validation + * @param PHPExcel_Cell_DataValidation $pDataValidation + * @return PHPExcel_Worksheet + */ + public function setDataValidation($pCellCoordinate = 'A1', PHPExcel_Cell_DataValidation $pDataValidation = null) + { + if ($pDataValidation === null) { + unset($this->_dataValidationCollection[$pCellCoordinate]); + } else { + $this->_dataValidationCollection[$pCellCoordinate] = $pDataValidation; + } + return $this; + } + + /** + * Data validation at a specific coordinate exists? + * + * @param string $pCoordinate + * @return boolean + */ + public function dataValidationExists($pCoordinate = 'A1') + { + return isset($this->_dataValidationCollection[$pCoordinate]); + } + + /** + * Get collection of data validations + * + * @return PHPExcel_Cell_DataValidation[] + */ + public function getDataValidationCollection() + { + return $this->_dataValidationCollection; + } + + /** + * Accepts a range, returning it as a range that falls within the current highest row and column of the worksheet + * + * @param string $range + * @return string Adjusted range value + */ + public function shrinkRangeToFit($range) { + $maxCol = $this->getHighestColumn(); + $maxRow = $this->getHighestRow(); + $maxCol = PHPExcel_Cell::columnIndexFromString($maxCol); + + $rangeBlocks = explode(' ',$range); + foreach ($rangeBlocks as &$rangeSet) { + $rangeBoundaries = PHPExcel_Cell::getRangeBoundaries($rangeSet); + + if (PHPExcel_Cell::columnIndexFromString($rangeBoundaries[0][0]) > $maxCol) { $rangeBoundaries[0][0] = PHPExcel_Cell::stringFromColumnIndex($maxCol); } + if ($rangeBoundaries[0][1] > $maxRow) { $rangeBoundaries[0][1] = $maxRow; } + if (PHPExcel_Cell::columnIndexFromString($rangeBoundaries[1][0]) > $maxCol) { $rangeBoundaries[1][0] = PHPExcel_Cell::stringFromColumnIndex($maxCol); } + if ($rangeBoundaries[1][1] > $maxRow) { $rangeBoundaries[1][1] = $maxRow; } + $rangeSet = $rangeBoundaries[0][0].$rangeBoundaries[0][1].':'.$rangeBoundaries[1][0].$rangeBoundaries[1][1]; + } + unset($rangeSet); + $stRange = implode(' ',$rangeBlocks); + + return $stRange; + } + + /** + * Get tab color + * + * @return PHPExcel_Style_Color + */ + public function getTabColor() + { + if ($this->_tabColor === NULL) + $this->_tabColor = new PHPExcel_Style_Color(); + + return $this->_tabColor; + } + + /** + * Reset tab color + * + * @return PHPExcel_Worksheet + */ + public function resetTabColor() + { + $this->_tabColor = null; + unset($this->_tabColor); + + return $this; + } + + /** + * Tab color set? + * + * @return boolean + */ + public function isTabColorSet() + { + return ($this->_tabColor !== NULL); + } + + /** + * Copy worksheet (!= clone!) + * + * @return PHPExcel_Worksheet + */ + public function copy() { + $copied = clone $this; + + return $copied; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + foreach ($this as $key => $val) { + if ($key == '_parent') { + continue; + } + + if (is_object($val) || (is_array($val))) { + if ($key == '_cellCollection') { + $newCollection = clone $this->_cellCollection; + $newCollection->copyCellCollection($this); + $this->_cellCollection = $newCollection; + } elseif ($key == '_drawingCollection') { + $newCollection = clone $this->_drawingCollection; + $this->_drawingCollection = $newCollection; + } elseif (($key == '_autoFilter') && ($this->_autoFilter instanceof PHPExcel_Worksheet_AutoFilter)) { + $newAutoFilter = clone $this->_autoFilter; + $this->_autoFilter = $newAutoFilter; + $this->_autoFilter->setParent($this); + } else { + $this->{$key} = unserialize(serialize($val)); + } + } + } + } +/** + * Define the code name of the sheet * - * @param string $pValue String containing the dimension of this worksheet - * @param string $updateFormulaCellReferences boolean Flag indicating whether cell references in formulae should - * be updated to reflect the new sheet name. - * This should be left as the default true, unless you are - * certain that no formula cells on any worksheet contain - * references to this worksheet - * @return PHPExcel_Worksheet - */ - public function setTitle($pValue = 'Worksheet', $updateFormulaCellReferences = true) - { + * @param null|string Same rule as Title minus space not allowed (but, like Excel, change silently space to underscore) + * @return objWorksheet + * @throws PHPExcel_Exception + */ + public function setCodeName($pValue=null){ // Is this a 'rename' or not? - if ($this->getTitle() == $pValue) { + if ($this->getCodeName() == $pValue) { return $this; } - + $pValue = str_replace(' ', '_', $pValue);//Excel does this automatically without flinching, we are doing the same // Syntax check - self::_checkSheetTitle($pValue); - - // Old title - $oldTitle = $this->getTitle(); + // throw an exception if not valid + self::_checkSheetCodeName($pValue); + // We use the same code that setTitle to find a valid codeName else not using a space (Excel don't like) but a '_' + if ($this->getParent()) { // Is there already such sheet name? - if ($this->getParent()->sheetNameExists($pValue)) { + if ($this->getParent()->sheetCodeNameExists($pValue)) { // Use name, but append with lowest possible integer if (PHPExcel_Shared_String::CountCharacters($pValue) > 29) { $pValue = PHPExcel_Shared_String::Substring($pValue,0,29); } $i = 1; - while ($this->getParent()->sheetNameExists($pValue . ' ' . $i)) { + while ($this->getParent()->sheetCodeNameExists($pValue . '_' . $i)) { ++$i; if ($i == 10) { if (PHPExcel_Shared_String::CountCharacters($pValue) > 28) { @@ -815,1981 +2882,28 @@ class PHPExcel_Worksheet implements PHPExcel_IComparable } } - $altTitle = $pValue . ' ' . $i; - return $this->setTitle($altTitle,$updateFormulaCellReferences); + $pValue = $pValue . '_' . $i;// ok, we have a valid name + //codeName is'nt used in formula : no need to call for an update + //return $this->setTitle($altTitle,$updateFormulaCellReferences); } } - // Set title - $this->_title = $pValue; - $this->_dirty = true; - - if ($this->getParent()) { - // New title - $newTitle = $this->getTitle(); - if ($updateFormulaCellReferences) - PHPExcel_ReferenceHelper::getInstance()->updateNamedFormulas($this->getParent(), $oldTitle, $newTitle); - } - + $this->_codeName=$pValue; return $this; } - /** - * Get sheet state + * Return the code name of the sheet * - * @return string Sheet state (visible, hidden, veryHidden) - */ - public function getSheetState() { - return $this->_sheetState; - } - - /** - * Set sheet state - * - * @param string $value Sheet state (visible, hidden, veryHidden) - * @return PHPExcel_Worksheet - */ - public function setSheetState($value = PHPExcel_Worksheet::SHEETSTATE_VISIBLE) { - $this->_sheetState = $value; - return $this; - } - - /** - * Get page setup - * - * @return PHPExcel_Worksheet_PageSetup - */ - public function getPageSetup() - { - return $this->_pageSetup; - } - - /** - * Set page setup - * - * @param PHPExcel_Worksheet_PageSetup $pValue - * @return PHPExcel_Worksheet - */ - public function setPageSetup(PHPExcel_Worksheet_PageSetup $pValue) - { - $this->_pageSetup = $pValue; - return $this; - } - - /** - * Get page margins - * - * @return PHPExcel_Worksheet_PageMargins - */ - public function getPageMargins() - { - return $this->_pageMargins; - } - - /** - * Set page margins - * - * @param PHPExcel_Worksheet_PageMargins $pValue - * @return PHPExcel_Worksheet - */ - public function setPageMargins(PHPExcel_Worksheet_PageMargins $pValue) - { - $this->_pageMargins = $pValue; - return $this; - } - - /** - * Get page header/footer - * - * @return PHPExcel_Worksheet_HeaderFooter - */ - public function getHeaderFooter() - { - return $this->_headerFooter; - } - - /** - * Set page header/footer - * - * @param PHPExcel_Worksheet_HeaderFooter $pValue - * @return PHPExcel_Worksheet - */ - public function setHeaderFooter(PHPExcel_Worksheet_HeaderFooter $pValue) - { - $this->_headerFooter = $pValue; - return $this; - } - - /** - * Get sheet view - * - * @return PHPExcel_Worksheet_HeaderFooter - */ - public function getSheetView() - { - return $this->_sheetView; - } - - /** - * Set sheet view - * - * @param PHPExcel_Worksheet_SheetView $pValue - * @return PHPExcel_Worksheet - */ - public function setSheetView(PHPExcel_Worksheet_SheetView $pValue) - { - $this->_sheetView = $pValue; - return $this; - } - - /** - * Get Protection - * - * @return PHPExcel_Worksheet_Protection - */ - public function getProtection() - { - return $this->_protection; - } - - /** - * Set Protection - * - * @param PHPExcel_Worksheet_Protection $pValue - * @return PHPExcel_Worksheet - */ - public function setProtection(PHPExcel_Worksheet_Protection $pValue) - { - $this->_protection = $pValue; - $this->_dirty = true; - - return $this; - } - - /** - * Get highest worksheet column - * - * @return string Highest column name - */ - public function getHighestColumn() - { - return $this->_cachedHighestColumn; - } - - /** - * Get highest worksheet column that contains data - * - * @return string Highest column name that contains data - */ - public function getHighestDataColumn() - { - return $this->_cellCollection->getHighestColumn(); - } - - /** - * Get highest worksheet row - * - * @return int Highest row number - */ - public function getHighestRow() - { - return $this->_cachedHighestRow; - } - - /** - * Get highest worksheet row that contains data - * - * @return string Highest row number that contains data - */ - public function getHighestDataRow() - { - return $this->_cellCollection->getHighestRow(); - } - - /** - * Get highest worksheet column and highest row that have cell records - * - * @return array Highest column name and highest row number - */ - public function getHighestRowAndColumn() - { - return $this->_cellCollection->getHighestRowAndColumn(); - } - - /** - * Set a cell value - * - * @param string $pCoordinate Coordinate of the cell - * @param mixed $pValue Value of the cell - * @param bool $returnCell Return the worksheet (false, default) or the cell (true) - * @return PHPExcel_Worksheet|PHPExcel_Cell Depending on the last parameter being specified - */ - public function setCellValue($pCoordinate = 'A1', $pValue = null, $returnCell = false) - { - $cell = $this->getCell($pCoordinate)->setValue($pValue); - return ($returnCell) ? $cell : $this; - } - - /** - * Set a cell value by using numeric cell coordinates - * - * @param string $pColumn Numeric column coordinate of the cell - * @param string $pRow Numeric row coordinate of the cell - * @param mixed $pValue Value of the cell - * @param bool $returnCell Return the worksheet (false, default) or the cell (true) - * @return PHPExcel_Worksheet|PHPExcel_Cell Depending on the last parameter being specified - */ - public function setCellValueByColumnAndRow($pColumn = 0, $pRow = 1, $pValue = null, $returnCell = false) - { - $cell = $this->getCell(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow)->setValue($pValue); - return ($returnCell) ? $cell : $this; - } - - /** - * Set a cell value - * - * @param string $pCoordinate Coordinate of the cell - * @param mixed $pValue Value of the cell - * @param string $pDataType Explicit data type - * @param bool $returnCell Return the worksheet (false, default) or the cell (true) - * @return PHPExcel_Worksheet|PHPExcel_Cell Depending on the last parameter being specified - */ - public function setCellValueExplicit($pCoordinate = 'A1', $pValue = null, $pDataType = PHPExcel_Cell_DataType::TYPE_STRING, $returnCell = false) - { - // Set value - $cell = $this->getCell($pCoordinate)->setValueExplicit($pValue, $pDataType); - return ($returnCell) ? $cell : $this; - } - - /** - * Set a cell value by using numeric cell coordinates - * - * @param string $pColumn Numeric column coordinate of the cell - * @param string $pRow Numeric row coordinate of the cell - * @param mixed $pValue Value of the cell - * @param string $pDataType Explicit data type - * @param bool $returnCell Return the worksheet (false, default) or the cell (true) - * @return PHPExcel_Worksheet|PHPExcel_Cell Depending on the last parameter being specified - */ - public function setCellValueExplicitByColumnAndRow($pColumn = 0, $pRow = 1, $pValue = null, $pDataType = PHPExcel_Cell_DataType::TYPE_STRING, $returnCell = false) - { - $cell = $this->getCell(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow)->setValueExplicit($pValue, $pDataType); - return ($returnCell) ? $cell : $this; - } - - /** - * Get cell at a specific coordinate - * - * @param string $pCoordinate Coordinate of the cell - * @throws Exception - * @return PHPExcel_Cell Cell that was found - */ - public function getCell($pCoordinate = 'A1') - { - // Check cell collection - if ($this->_cellCollection->isDataSet($pCoordinate)) { - return $this->_cellCollection->getCacheData($pCoordinate); - } - - // Worksheet reference? - if (strpos($pCoordinate, '!') !== false) { - $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pCoordinate, true); - return $this->getParent()->getSheetByName($worksheetReference[0])->getCell($worksheetReference[1]); - } - - // Named range? - if ((!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $pCoordinate, $matches)) && - (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_NAMEDRANGE.'$/i', $pCoordinate, $matches))) { - $namedRange = PHPExcel_NamedRange::resolveRange($pCoordinate, $this); - if ($namedRange !== NULL) { - $pCoordinate = $namedRange->getRange(); - return $namedRange->getWorksheet()->getCell($pCoordinate); - } - } - - // Uppercase coordinate - $pCoordinate = strtoupper($pCoordinate); - - if (strpos($pCoordinate,':') !== false || strpos($pCoordinate,',') !== false) { - throw new Exception('Cell coordinate can not be a range of cells.'); - } elseif (strpos($pCoordinate,'$') !== false) { - throw new Exception('Cell coordinate must not be absolute.'); - } else { - // Create new cell object - - // Coordinates - $aCoordinates = PHPExcel_Cell::coordinateFromString($pCoordinate); - - $cell = $this->_cellCollection->addCacheData($pCoordinate,new PHPExcel_Cell($aCoordinates[0], $aCoordinates[1], null, PHPExcel_Cell_DataType::TYPE_NULL, $this)); - $this->_cellCollectionIsSorted = false; - - if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < PHPExcel_Cell::columnIndexFromString($aCoordinates[0])) - $this->_cachedHighestColumn = $aCoordinates[0]; - - $this->_cachedHighestRow = max($this->_cachedHighestRow,$aCoordinates[1]); - - // Cell needs appropriate xfIndex - $rowDimensions = $this->getRowDimensions(); - $columnDimensions = $this->getColumnDimensions(); - - if ( isset($rowDimensions[$aCoordinates[1]]) && $rowDimensions[$aCoordinates[1]]->getXfIndex() !== null ) { - // then there is a row dimension with explicit style, assign it to the cell - $cell->setXfIndex($rowDimensions[$aCoordinates[1]]->getXfIndex()); - } else if ( isset($columnDimensions[$aCoordinates[0]]) ) { - // then there is a column dimension, assign it to the cell - $cell->setXfIndex($columnDimensions[$aCoordinates[0]]->getXfIndex()); - } else { - // set to default index - $cell->setXfIndex(0); - } - - return $cell; - } - } - - /** - * Get cell at a specific coordinate by using numeric cell coordinates - * - * @param string $pColumn Numeric column coordinate of the cell - * @param string $pRow Numeric row coordinate of the cell - * @return PHPExcel_Cell Cell that was found - */ - public function getCellByColumnAndRow($pColumn = 0, $pRow = 1) - { - $columnLetter = PHPExcel_Cell::stringFromColumnIndex($pColumn); - $coordinate = $columnLetter . $pRow; - - if (!$this->_cellCollection->isDataSet($coordinate)) { - $cell = $this->_cellCollection->addCacheData($coordinate, new PHPExcel_Cell($columnLetter, $pRow, null, PHPExcel_Cell_DataType::TYPE_NULL, $this)); - $this->_cellCollectionIsSorted = false; - - if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < $pColumn) - $this->_cachedHighestColumn = $columnLetter; - - $this->_cachedHighestRow = max($this->_cachedHighestRow,$pRow); - - return $cell; - } - - return $this->_cellCollection->getCacheData($coordinate); - } - - /** - * Cell at a specific coordinate exists? - * - * @param string $pCoordinate Coordinate of the cell - * @throws Exception - * @return boolean - */ - public function cellExists($pCoordinate = 'A1') - { - // Worksheet reference? - if (strpos($pCoordinate, '!') !== false) { - $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pCoordinate, true); - return $this->getParent()->getSheetByName($worksheetReference[0])->cellExists($worksheetReference[1]); - } - - // Named range? - if ((!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $pCoordinate, $matches)) && - (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_NAMEDRANGE.'$/i', $pCoordinate, $matches))) { - $namedRange = PHPExcel_NamedRange::resolveRange($pCoordinate, $this); - if ($namedRange !== NULL) { - $pCoordinate = $namedRange->getRange(); - if ($this->getHashCode() != $namedRange->getWorksheet()->getHashCode()) { - if (!$namedRange->getLocalOnly()) { - return $namedRange->getWorksheet()->cellExists($pCoordinate); - } else { - throw new Exception('Named range ' . $namedRange->getName() . ' is not accessible from within sheet ' . $this->getTitle()); - } - } - } - } - - // Uppercase coordinate - $pCoordinate = strtoupper($pCoordinate); - - if (strpos($pCoordinate,':') !== false || strpos($pCoordinate,',') !== false) { - throw new Exception('Cell coordinate can not be a range of cells.'); - } elseif (strpos($pCoordinate,'$') !== false) { - throw new Exception('Cell coordinate must not be absolute.'); - } else { - // Coordinates - $aCoordinates = PHPExcel_Cell::coordinateFromString($pCoordinate); - - // Cell exists? - return $this->_cellCollection->isDataSet($pCoordinate); - } - } - - /** - * Cell at a specific coordinate by using numeric cell coordinates exists? - * - * @param string $pColumn Numeric column coordinate of the cell - * @param string $pRow Numeric row coordinate of the cell - * @return boolean - */ - public function cellExistsByColumnAndRow($pColumn = 0, $pRow = 1) - { - return $this->cellExists(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); - } - - /** - * Get row dimension at a specific row - * - * @param int $pRow Numeric index of the row - * @return PHPExcel_Worksheet_RowDimension - */ - public function getRowDimension($pRow = 1) - { - // Found - $found = null; - - // Get row dimension - if (!isset($this->_rowDimensions[$pRow])) { - $this->_rowDimensions[$pRow] = new PHPExcel_Worksheet_RowDimension($pRow); - - $this->_cachedHighestRow = max($this->_cachedHighestRow,$pRow); - } - return $this->_rowDimensions[$pRow]; - } - - /** - * Get column dimension at a specific column - * - * @param string $pColumn String index of the column - * @return PHPExcel_Worksheet_ColumnDimension - */ - public function getColumnDimension($pColumn = 'A') - { - // Uppercase coordinate - $pColumn = strtoupper($pColumn); - - // Fetch dimensions - if (!isset($this->_columnDimensions[$pColumn])) { - $this->_columnDimensions[$pColumn] = new PHPExcel_Worksheet_ColumnDimension($pColumn); - - if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < PHPExcel_Cell::columnIndexFromString($pColumn)) - $this->_cachedHighestColumn = $pColumn; - } - return $this->_columnDimensions[$pColumn]; - } - - /** - * Get column dimension at a specific column by using numeric cell coordinates - * - * @param string $pColumn Numeric column coordinate of the cell - * @return PHPExcel_Worksheet_ColumnDimension - */ - public function getColumnDimensionByColumn($pColumn = 0) - { - return $this->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($pColumn)); - } - - /** - * Get styles - * - * @return PHPExcel_Style[] - */ - public function getStyles() - { - return $this->_styles; - } - - /** - * Get default style of workbork. - * - * @deprecated - * @return PHPExcel_Style - * @throws Exception - */ - public function getDefaultStyle() - { - return $this->_parent->getDefaultStyle(); - } - - /** - * Set default style - should only be used by PHPExcel_IReader implementations! - * - * @deprecated - * @param PHPExcel_Style $pValue - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function setDefaultStyle(PHPExcel_Style $pValue) - { - $this->_parent->getDefaultStyle()->applyFromArray(array( - 'font' => array( - 'name' => $pValue->getFont()->getName(), - 'size' => $pValue->getFont()->getSize(), - ), - )); - return $this; - } - - /** - * Get style for cell - * - * @param string $pCellCoordinate Cell coordinate to get style for - * @return PHPExcel_Style - * @throws Exception - */ - public function getStyle($pCellCoordinate = 'A1') - { - // set this sheet as active - $this->_parent->setActiveSheetIndex($this->_parent->getIndex($this)); - - // set cell coordinate as active - $this->setSelectedCells($pCellCoordinate); - - return $this->_parent->getCellXfSupervisor(); - } - - /** - * Get conditional styles for a cell - * - * @param string $pCoordinate - * @return PHPExcel_Style_Conditional[] - */ - public function getConditionalStyles($pCoordinate = 'A1') - { - if (!isset($this->_conditionalStylesCollection[$pCoordinate])) { - $this->_conditionalStylesCollection[$pCoordinate] = array(); - } - return $this->_conditionalStylesCollection[$pCoordinate]; - } - - /** - * Do conditional styles exist for this cell? - * - * @param string $pCoordinate - * @return boolean - */ - public function conditionalStylesExists($pCoordinate = 'A1') - { - if (isset($this->_conditionalStylesCollection[$pCoordinate])) { - return true; - } - return false; - } - - /** - * Removes conditional styles for a cell - * - * @param string $pCoordinate - * @return PHPExcel_Worksheet - */ - public function removeConditionalStyles($pCoordinate = 'A1') - { - unset($this->_conditionalStylesCollection[$pCoordinate]); - return $this; - } - - /** - * Get collection of conditional styles - * - * @return array - */ - public function getConditionalStylesCollection() - { - return $this->_conditionalStylesCollection; - } - - /** - * Set conditional styles - * - * @param $pCoordinate string E.g. 'A1' - * @param $pValue PHPExcel_Style_Conditional[] - * @return PHPExcel_Worksheet - */ - public function setConditionalStyles($pCoordinate = 'A1', $pValue) - { - $this->_conditionalStylesCollection[$pCoordinate] = $pValue; - return $this; - } - - /** - * Get style for cell by using numeric cell coordinates - * - * @param int $pColumn Numeric column coordinate of the cell - * @param int $pRow Numeric row coordinate of the cell - * @return PHPExcel_Style - */ - public function getStyleByColumnAndRow($pColumn = 0, $pRow = 1) - { - return $this->getStyle(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); - } - - /** - * Set shared cell style to a range of cells - * - * Please note that this will overwrite existing cell styles for cells in range! - * - * @deprecated - * @param PHPExcel_Style $pSharedCellStyle Cell style to share - * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function setSharedStyle(PHPExcel_Style $pSharedCellStyle = null, $pRange = '') - { - $this->duplicateStyle($pSharedCellStyle, $pRange); - return $this; - } - - /** - * Duplicate cell style to a range of cells - * - * Please note that this will overwrite existing cell styles for cells in range! - * - * @param PHPExcel_Style $pCellStyle Cell style to duplicate - * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function duplicateStyle(PHPExcel_Style $pCellStyle = null, $pRange = '') - { - // make sure we have a real style and not supervisor - $style = $pCellStyle->getIsSupervisor() ? $pCellStyle->getSharedComponent() : $pCellStyle; - - // Add the style to the workbook if necessary - $workbook = $this->_parent; - if ($existingStyle = $this->_parent->getCellXfByHashCode($pCellStyle->getHashCode())) { - // there is already such cell Xf in our collection - $xfIndex = $existingStyle->getIndex(); - } else { - // we don't have such a cell Xf, need to add - $workbook->addCellXf($pCellStyle); - $xfIndex = $pCellStyle->getIndex(); - } - - // Uppercase coordinate - $pRange = strtoupper($pRange); - - // Is it a cell range or a single cell? - $rangeA = ''; - $rangeB = ''; - if (strpos($pRange, ':') === false) { - $rangeA = $pRange; - $rangeB = $pRange; - } else { - list($rangeA, $rangeB) = explode(':', $pRange); - } - - // Calculate range outer borders - $rangeStart = PHPExcel_Cell::coordinateFromString($rangeA); - $rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB); - - // Translate column into index - $rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]) - 1; - $rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]) - 1; - - // Make sure we can loop upwards on rows and columns - if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) { - $tmp = $rangeStart; - $rangeStart = $rangeEnd; - $rangeEnd = $tmp; - } - - // Loop through cells and apply styles - for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { - for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { - $this->getCell(PHPExcel_Cell::stringFromColumnIndex($col) . $row)->setXfIndex($xfIndex); - } - } - - return $this; - } - - /** - * Duplicate conditional style to a range of cells - * - * Please note that this will overwrite existing cell styles for cells in range! - * - * @param array of PHPExcel_Style_Conditional $pCellStyle Cell style to duplicate - * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function duplicateConditionalStyle(array $pCellStyle = null, $pRange = '') - { - foreach($pCellStyle as $cellStyle) { - if (!is_a($cellStyle,'PHPExcel_Style_Conditional')) { - throw new Exception('Style is not a conditional style'); - } - } - - // Uppercase coordinate - $pRange = strtoupper($pRange); - - // Is it a cell range or a single cell? - $rangeA = ''; - $rangeB = ''; - if (strpos($pRange, ':') === false) { - $rangeA = $pRange; - $rangeB = $pRange; - } else { - list($rangeA, $rangeB) = explode(':', $pRange); - } - - // Calculate range outer borders - $rangeStart = PHPExcel_Cell::coordinateFromString($rangeA); - $rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB); - - // Translate column into index - $rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]) - 1; - $rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]) - 1; - - // Make sure we can loop upwards on rows and columns - if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) { - $tmp = $rangeStart; - $rangeStart = $rangeEnd; - $rangeEnd = $tmp; - } - - // Loop through cells and apply styles - for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { - for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { - $this->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($col) . $row, $pCellStyle); - } - } - - return $this; - } - - /** - * Duplicate cell style array to a range of cells - * - * Please note that this will overwrite existing cell styles for cells in range, - * if they are in the styles array. For example, if you decide to set a range of - * cells to font bold, only include font bold in the styles array. - * - * @deprecated - * @param array $pStyles Array containing style information - * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") - * @param boolean $pAdvanced Advanced mode for setting borders. - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function duplicateStyleArray($pStyles = null, $pRange = '', $pAdvanced = true) - { - $this->getStyle($pRange)->applyFromArray($pStyles, $pAdvanced); - return $this; - } - - /** - * Set break on a cell - * - * @param string $pCell Cell coordinate (e.g. A1) - * @param int $pBreak Break type (type of PHPExcel_Worksheet::BREAK_*) - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function setBreak($pCell = 'A1', $pBreak = PHPExcel_Worksheet::BREAK_NONE) - { - // Uppercase coordinate - $pCell = strtoupper($pCell); - - if ($pCell != '') { - $this->_breaks[$pCell] = $pBreak; - } else { - throw new Exception('No cell coordinate specified.'); - } - - return $this; - } - - /** - * Set break on a cell by using numeric cell coordinates - * - * @param integer $pColumn Numeric column coordinate of the cell - * @param integer $pRow Numeric row coordinate of the cell - * @param integer $pBreak Break type (type of PHPExcel_Worksheet::BREAK_*) - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function setBreakByColumnAndRow($pColumn = 0, $pRow = 1, $pBreak = PHPExcel_Worksheet::BREAK_NONE) - { - return $this->setBreak(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow, $pBreak); - } - - /** - * Get breaks - * - * @return array[] - */ - public function getBreaks() - { - return $this->_breaks; - } - - /** - * Set merge on a cell range - * - * @param string $pRange Cell range (e.g. A1:E1) - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function mergeCells($pRange = 'A1:A1') - { - // Uppercase coordinate - $pRange = strtoupper($pRange); - - if (strpos($pRange,':') !== false) { - $this->_mergeCells[$pRange] = $pRange; - - // make sure cells are created - - // get the cells in the range - $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($pRange); - - // create upper left cell if it does not already exist - $upperLeft = $aReferences[0]; - if (!$this->cellExists($upperLeft)) { - $this->getCell($upperLeft)->setValueExplicit(null, PHPExcel_Cell_DataType::TYPE_NULL); - } - - // create or blank out the rest of the cells in the range - $count = count($aReferences); - for ($i = 1; $i < $count; $i++) { - $this->getCell($aReferences[$i])->setValueExplicit(null, PHPExcel_Cell_DataType::TYPE_NULL); - } - - } else { - throw new Exception('Merge must be set on a range of cells.'); - } - - return $this; - } - - /** - * Set merge on a cell range by using numeric cell coordinates - * - * @param int $pColumn1 Numeric column coordinate of the first cell - * @param int $pRow1 Numeric row coordinate of the first cell - * @param int $pColumn2 Numeric column coordinate of the last cell - * @param int $pRow2 Numeric row coordinate of the last cell - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function mergeCellsByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1) - { - $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 . ':' . PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2; - return $this->mergeCells($cellRange); - } - - /** - * Remove merge on a cell range - * - * @param string $pRange Cell range (e.g. A1:E1) - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function unmergeCells($pRange = 'A1:A1') - { - // Uppercase coordinate - $pRange = strtoupper($pRange); - - if (strpos($pRange,':') !== false) { - if (isset($this->_mergeCells[$pRange])) { - unset($this->_mergeCells[$pRange]); - } else { - throw new Exception('Cell range ' . $pRange . ' not known as merged.'); - } - } else { - throw new Exception('Merge can only be removed from a range of cells.'); - } - - return $this; - } - - /** - * Remove merge on a cell range by using numeric cell coordinates - * - * @param int $pColumn1 Numeric column coordinate of the first cell - * @param int $pRow1 Numeric row coordinate of the first cell - * @param int $pColumn2 Numeric column coordinate of the last cell - * @param int $pRow2 Numeric row coordinate of the last cell - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function unmergeCellsByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1) - { - $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 . ':' . PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2; - return $this->unmergeCells($cellRange); - } - - /** - * Get merge cells array. - * - * @return array[] - */ - public function getMergeCells() - { - return $this->_mergeCells; - } - - /** - * Set merge cells array for the entire sheet. Use instead mergeCells() to merge - * a single cell range. - * - * @param array - */ - public function setMergeCells($pValue = array()) - { - $this->_mergeCells = $pValue; - - return $this; - } - - /** - * Set protection on a cell range - * - * @param string $pRange Cell (e.g. A1) or cell range (e.g. A1:E1) - * @param string $pPassword Password to unlock the protection - * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function protectCells($pRange = 'A1', $pPassword = '', $pAlreadyHashed = false) - { - // Uppercase coordinate - $pRange = strtoupper($pRange); - - if (!$pAlreadyHashed) { - $pPassword = PHPExcel_Shared_PasswordHasher::hashPassword($pPassword); - } - $this->_protectedCells[$pRange] = $pPassword; - - return $this; - } - - /** - * Set protection on a cell range by using numeric cell coordinates - * - * @param int $pColumn1 Numeric column coordinate of the first cell - * @param int $pRow1 Numeric row coordinate of the first cell - * @param int $pColumn2 Numeric column coordinate of the last cell - * @param int $pRow2 Numeric row coordinate of the last cell - * @param string $pPassword Password to unlock the protection - * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function protectCellsByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1, $pPassword = '', $pAlreadyHashed = false) - { - $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 . ':' . PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2; - return $this->protectCells($cellRange, $pPassword, $pAlreadyHashed); - } - - /** - * Remove protection on a cell range - * - * @param string $pRange Cell (e.g. A1) or cell range (e.g. A1:E1) - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function unprotectCells($pRange = 'A1') - { - // Uppercase coordinate - $pRange = strtoupper($pRange); - - if (isset($this->_protectedCells[$pRange])) { - unset($this->_protectedCells[$pRange]); - } else { - throw new Exception('Cell range ' . $pRange . ' not known as protected.'); - } - return $this; - } - - /** - * Remove protection on a cell range by using numeric cell coordinates - * - * @param int $pColumn1 Numeric column coordinate of the first cell - * @param int $pRow1 Numeric row coordinate of the first cell - * @param int $pColumn2 Numeric column coordinate of the last cell - * @param int $pRow2 Numeric row coordinate of the last cell - * @param string $pPassword Password to unlock the protection - * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function unprotectCellsByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1, $pPassword = '', $pAlreadyHashed = false) - { - $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 . ':' . PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2; - return $this->unprotectCells($cellRange, $pPassword, $pAlreadyHashed); - } - - /** - * Get protected cells - * - * @return array[] - */ - public function getProtectedCells() - { - return $this->_protectedCells; - } - - /** - * Get Autofilter - * - * @return PHPExcel_Worksheet_AutoFilter - */ - public function getAutoFilter() - { - return $this->_autoFilter; - } - - /** - * Set AutoFilter - * - * @param PHPExcel_Worksheet_AutoFilter|string $pValue - * A simple string containing a Cell range like 'A1:E10' is permitted for backward compatibility - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function setAutoFilter($pValue) - { - if (is_string($pValue)) { - $this->_autoFilter->setRange($pValue); - } elseif(is_object($pValue) && ($pValue instanceof PHPExcel_Worksheet_AutoFilter)) { - $this->_autoFilter = $pValue; - } - return $this; - } - - /** - * Set Autofilter Range by using numeric cell coordinates - * - * @param int $pColumn1 Numeric column coordinate of the first cell - * @param int $pRow1 Numeric row coordinate of the first cell - * @param int $pColumn2 Numeric column coordinate of the second cell - * @param int $pRow2 Numeric row coordinate of the second cell - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function setAutoFilterByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1) - { - return $this->setAutoFilter( - PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 - . ':' . - PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2 - ); - } - - /** - * Remove autofilter - * - * @return PHPExcel_Worksheet - */ - public function removeAutoFilter() - { - $this->_autoFilter->setRange(NULL); - return $this; - } - - /** - * Get Freeze Pane - * - * @return string - */ - public function getFreezePane() - { - return $this->_freezePane; - } - - /** - * Freeze Pane - * - * @param string $pCell Cell (i.e. A2) - * Examples: - * A2 will freeze the rows above cell A2 (i.e row 1) - * B1 will freeze the columns to the left of cell B1 (i.e column A) - * B2 will freeze the rows above and to the left of cell A2 - * (i.e row 1 and column A) - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function freezePane($pCell = '') - { - // Uppercase coordinate - $pCell = strtoupper($pCell); - - if (strpos($pCell,':') === false && strpos($pCell,',') === false) { - $this->_freezePane = $pCell; - } else { - throw new Exception('Freeze pane can not be set on a range of cells.'); - } - return $this; - } - - /** - * Freeze Pane by using numeric cell coordinates - * - * @param int $pColumn Numeric column coordinate of the cell - * @param int $pRow Numeric row coordinate of the cell - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function freezePaneByColumnAndRow($pColumn = 0, $pRow = 1) - { - return $this->freezePane(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); - } - - /** - * Unfreeze Pane - * - * @return PHPExcel_Worksheet - */ - public function unfreezePane() - { - return $this->freezePane(''); - } - - /** - * Insert a new row, updating all possible related data - * - * @param int $pBefore Insert before this one - * @param int $pNumRows Number of rows to insert - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function insertNewRowBefore($pBefore = 1, $pNumRows = 1) { - if ($pBefore >= 1) { - $objReferenceHelper = PHPExcel_ReferenceHelper::getInstance(); - $objReferenceHelper->insertNewBefore('A' . $pBefore, 0, $pNumRows, $this); - } else { - throw new Exception("Rows can only be inserted before at least row 1."); - } - return $this; - } - - /** - * Insert a new column, updating all possible related data - * - * @param int $pBefore Insert before this one - * @param int $pNumCols Number of columns to insert - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function insertNewColumnBefore($pBefore = 'A', $pNumCols = 1) { - if (!is_numeric($pBefore)) { - $objReferenceHelper = PHPExcel_ReferenceHelper::getInstance(); - $objReferenceHelper->insertNewBefore($pBefore . '1', $pNumCols, 0, $this); - } else { - throw new Exception("Column references should not be numeric."); - } - return $this; - } - - /** - * Insert a new column, updating all possible related data - * - * @param int $pBefore Insert before this one (numeric column coordinate of the cell) - * @param int $pNumCols Number of columns to insert - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function insertNewColumnBeforeByIndex($pBefore = 0, $pNumCols = 1) { - if ($pBefore >= 0) { - return $this->insertNewColumnBefore(PHPExcel_Cell::stringFromColumnIndex($pBefore), $pNumCols); - } else { - throw new Exception("Columns can only be inserted before at least column A (0)."); - } - } - - /** - * Delete a row, updating all possible related data - * - * @param int $pRow Remove starting with this one - * @param int $pNumRows Number of rows to remove - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function removeRow($pRow = 1, $pNumRows = 1) { - if ($pRow >= 1) { - $objReferenceHelper = PHPExcel_ReferenceHelper::getInstance(); - $objReferenceHelper->insertNewBefore('A' . ($pRow + $pNumRows), 0, -$pNumRows, $this); - } else { - throw new Exception("Rows to be deleted should at least start from row 1."); - } - return $this; - } - - /** - * Remove a column, updating all possible related data - * - * @param int $pColumn Remove starting with this one - * @param int $pNumCols Number of columns to remove - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function removeColumn($pColumn = 'A', $pNumCols = 1) { - if (!is_numeric($pColumn)) { - $pColumn = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($pColumn) - 1 + $pNumCols); - $objReferenceHelper = PHPExcel_ReferenceHelper::getInstance(); - $objReferenceHelper->insertNewBefore($pColumn . '1', -$pNumCols, 0, $this); - } else { - throw new Exception("Column references should not be numeric."); - } - return $this; - } - - /** - * Remove a column, updating all possible related data - * - * @param int $pColumn Remove starting with this one (numeric column coordinate of the cell) - * @param int $pNumCols Number of columns to remove - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function removeColumnByIndex($pColumn = 0, $pNumCols = 1) { - if ($pColumn >= 0) { - return $this->removeColumn(PHPExcel_Cell::stringFromColumnIndex($pColumn), $pNumCols); - } else { - throw new Exception("Columns to be deleted should at least start from column 0"); - } - } - - /** - * Show gridlines? - * - * @return boolean - */ - public function getShowGridlines() { - return $this->_showGridlines; - } - - /** - * Set show gridlines - * - * @param boolean $pValue Show gridlines (true/false) - * @return PHPExcel_Worksheet - */ - public function setShowGridlines($pValue = false) { - $this->_showGridlines = $pValue; - return $this; - } - - /** - * Print gridlines? - * - * @return boolean + * @return null|string */ - public function getPrintGridlines() { - return $this->_printGridlines; + public function getCodeName(){ + return $this->_codeName; } - /** - * Set print gridlines - * - * @param boolean $pValue Print gridlines (true/false) - * @return PHPExcel_Worksheet + * Sheet has a code name ? + * @return boolean */ - public function setPrintGridlines($pValue = false) { - $this->_printGridlines = $pValue; - return $this; - } - - /** - * Show row and column headers? - * - * @return boolean - */ - public function getShowRowColHeaders() { - return $this->_showRowColHeaders; - } - - /** - * Set show row and column headers - * - * @param boolean $pValue Show row and column headers (true/false) - * @return PHPExcel_Worksheet - */ - public function setShowRowColHeaders($pValue = false) { - $this->_showRowColHeaders = $pValue; - return $this; - } - - /** - * Show summary below? (Row/Column outlining) - * - * @return boolean - */ - public function getShowSummaryBelow() { - return $this->_showSummaryBelow; - } - - /** - * Set show summary below - * - * @param boolean $pValue Show summary below (true/false) - * @return PHPExcel_Worksheet - */ - public function setShowSummaryBelow($pValue = true) { - $this->_showSummaryBelow = $pValue; - return $this; - } - - /** - * Show summary right? (Row/Column outlining) - * - * @return boolean - */ - public function getShowSummaryRight() { - return $this->_showSummaryRight; - } - - /** - * Set show summary right - * - * @param boolean $pValue Show summary right (true/false) - * @return PHPExcel_Worksheet - */ - public function setShowSummaryRight($pValue = true) { - $this->_showSummaryRight = $pValue; - return $this; - } - - /** - * Get comments - * - * @return PHPExcel_Comment[] - */ - public function getComments() - { - return $this->_comments; - } - - /** - * Set comments array for the entire sheet. - * - * @param array of PHPExcel_Comment - * @return PHPExcel_Worksheet - */ - public function setComments($pValue = array()) - { - $this->_comments = $pValue; - - return $this; - } - - /** - * Get comment for cell - * - * @param string $pCellCoordinate Cell coordinate to get comment for - * @return PHPExcel_Comment - * @throws Exception - */ - public function getComment($pCellCoordinate = 'A1') - { - // Uppercase coordinate - $pCellCoordinate = strtoupper($pCellCoordinate); - - if (strpos($pCellCoordinate,':') !== false || strpos($pCellCoordinate,',') !== false) { - throw new Exception('Cell coordinate string can not be a range of cells.'); - } else if (strpos($pCellCoordinate,'$') !== false) { - throw new Exception('Cell coordinate string must not be absolute.'); - } else if ($pCellCoordinate == '') { - throw new Exception('Cell coordinate can not be zero-length string.'); - } else { - // Check if we already have a comment for this cell. - // If not, create a new comment. - if (isset($this->_comments[$pCellCoordinate])) { - return $this->_comments[$pCellCoordinate]; - } else { - $newComment = new PHPExcel_Comment(); - $this->_comments[$pCellCoordinate] = $newComment; - return $newComment; - } - } - } - - /** - * Get comment for cell by using numeric cell coordinates - * - * @param int $pColumn Numeric column coordinate of the cell - * @param int $pRow Numeric row coordinate of the cell - * @return PHPExcel_Comment - */ - public function getCommentByColumnAndRow($pColumn = 0, $pRow = 1) - { - return $this->getComment(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); - } - - /** - * Get selected cell - * - * @deprecated - * @return string - */ - public function getSelectedCell() - { - return $this->getSelectedCells(); - } - - /** - * Get active cell - * - * @return string Example: 'A1' - */ - public function getActiveCell() - { - return $this->_activeCell; - } - - /** - * Get selected cells - * - * @return string - */ - public function getSelectedCells() - { - return $this->_selectedCells; - } - - /** - * Selected cell - * - * @param string $pCoordinate Cell (i.e. A1) - * @return PHPExcel_Worksheet - */ - public function setSelectedCell($pCoordinate = 'A1') - { - return $this->setSelectedCells($pCoordinate); - } - - /** - * Select a range of cells. - * - * @param string $pCoordinate Cell range, examples: 'A1', 'B2:G5', 'A:C', '3:6' - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function setSelectedCells($pCoordinate = 'A1') - { - // Uppercase coordinate - $pCoordinate = strtoupper($pCoordinate); - - // Convert 'A' to 'A:A' - $pCoordinate = preg_replace('/^([A-Z]+)$/', '${1}:${1}', $pCoordinate); - - // Convert '1' to '1:1' - $pCoordinate = preg_replace('/^([0-9]+)$/', '${1}:${1}', $pCoordinate); - - // Convert 'A:C' to 'A1:C1048576' - $pCoordinate = preg_replace('/^([A-Z]+):([A-Z]+)$/', '${1}1:${2}1048576', $pCoordinate); - - // Convert '1:3' to 'A1:XFD3' - $pCoordinate = preg_replace('/^([0-9]+):([0-9]+)$/', 'A${1}:XFD${2}', $pCoordinate); - - if (strpos($pCoordinate,':') !== false || strpos($pCoordinate,',') !== false) { - list($first, ) = PHPExcel_Cell::splitRange($pCoordinate); - $this->_activeCell = $first[0]; - } else { - $this->_activeCell = $pCoordinate; - } - $this->_selectedCells = $pCoordinate; - return $this; - } - - /** - * Selected cell by using numeric cell coordinates - * - * @param int $pColumn Numeric column coordinate of the cell - * @param int $pRow Numeric row coordinate of the cell - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function setSelectedCellByColumnAndRow($pColumn = 0, $pRow = 1) - { - return $this->setSelectedCells(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); - } - - /** - * Get right-to-left - * - * @return boolean - */ - public function getRightToLeft() { - return $this->_rightToLeft; - } - - /** - * Set right-to-left - * - * @param boolean $value Right-to-left true/false - * @return PHPExcel_Worksheet - */ - public function setRightToLeft($value = false) { - $this->_rightToLeft = $value; - return $this; - } - - /** - * Fill worksheet from values in array - * - * @param array $source Source array - * @param mixed $nullValue Value in source array that stands for blank cell - * @param string $startCell Insert array starting from this cell address as the top left coordinate - * @param boolean $strictNullComparison Apply strict comparison when testing for null values in the array - * @throws Exception - * @return PHPExcel_Worksheet - */ - public function fromArray($source = null, $nullValue = null, $startCell = 'A1', $strictNullComparison = false) { - if (is_array($source)) { - // Convert a 1-D array to 2-D (for ease of looping) - if (!is_array(end($source))) { - $source = array($source); - } - - // start coordinate - list ($startColumn, $startRow) = PHPExcel_Cell::coordinateFromString($startCell); - - // Loop through $source - foreach ($source as $rowData) { - $currentColumn = $startColumn; - foreach($rowData as $cellValue) { - if ($strictNullComparison) { - if ($cellValue !== $nullValue) { - // Set cell value - $this->getCell($currentColumn . $startRow)->setValue($cellValue); - } - } else { - if ($cellValue != $nullValue) { - // Set cell value - $this->getCell($currentColumn . $startRow)->setValue($cellValue); - } - } - ++$currentColumn; - } - ++$startRow; - } - } else { - throw new Exception("Parameter \$source should be an array."); - } - return $this; - } - - /** - * Create array from a range of cells - * - * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") - * @param mixed $nullValue Value returned in the array entry if a cell doesn't exist - * @param boolean $calculateFormulas Should formulas be calculated? - * @param boolean $formatData Should formatting be applied to cell values? - * @param boolean $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero - * True - Return rows and columns indexed by their actual row and column IDs - * @return array - */ - public function rangeToArray($pRange = 'A1', $nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) { - // Returnvalue - $returnValue = array(); - - // Identify the range that we need to extract from the worksheet - list($rangeStart, $rangeEnd) = PHPExcel_Cell::rangeBoundaries($pRange); - $minCol = PHPExcel_Cell::stringFromColumnIndex($rangeStart[0] -1); - $minRow = $rangeStart[1]; - $maxCol = PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0] -1); - $maxRow = $rangeEnd[1]; - - $maxCol++; - - // Loop through rows - $r = -1; - for ($row = $minRow; $row <= $maxRow; ++$row) { - $rRef = ($returnCellRef) ? $row : ++$r; - $c = -1; - // Loop through columns in the current row - for ($col = $minCol; $col != $maxCol; ++$col) { - $cRef = ($returnCellRef) ? $col : ++$c; - // Using getCell() will create a new cell if it doesn't already exist. We don't want that to happen - // so we test and retrieve directly against _cellCollection - if ($this->_cellCollection->isDataSet($col.$row)) { - // Cell exists - $cell = $this->_cellCollection->getCacheData($col.$row); - if ($cell->getValue() !== null) { - if ($cell->getValue() instanceof PHPExcel_RichText) { - $returnValue[$rRef][$cRef] = $cell->getValue()->getPlainText(); - } else { - if ($calculateFormulas) { - $returnValue[$rRef][$cRef] = $cell->getCalculatedValue(); - } else { - $returnValue[$rRef][$cRef] = $cell->getValue(); - } - } - - if ($formatData) { - $style = $this->_parent->getCellXfByIndex($cell->getXfIndex()); - $returnValue[$rRef][$cRef] = PHPExcel_Style_NumberFormat::toFormattedString($returnValue[$rRef][$cRef], $style->getNumberFormat()->getFormatCode()); - } - } else { - // Cell holds a NULL - $returnValue[$rRef][$cRef] = $nullValue; - } - } else { - // Cell doesn't exist - $returnValue[$rRef][$cRef] = $nullValue; - } - } - } - - // Return - return $returnValue; - } - - - /** - * Create array from a range of cells - * - * @param string $pNamedRange Name of the Named Range - * @param mixed $nullValue Value returned in the array entry if a cell doesn't exist - * @param boolean $calculateFormulas Should formulas be calculated? - * @param boolean $formatData Should formatting be applied to cell values? - * @param boolean $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero - * True - Return rows and columns indexed by their actual row and column IDs - * @return array - * @throws Exception - */ - public function namedRangeToArray($pNamedRange = '', $nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) { - $namedRange = PHPExcel_NamedRange::resolveRange($pNamedRange, $this); - if ($namedRange !== NULL) { - $pWorkSheet = $namedRange->getWorksheet(); - $pCellRange = $namedRange->getRange(); - - return $pWorkSheet->rangeToArray( $pCellRange, - $nullValue, $calculateFormulas, $formatData, $returnCellRef); - } - - throw new Exception('Named Range '.$pNamedRange.' does not exist.'); - } - - - /** - * Create array from worksheet - * - * @param mixed $nullValue Value returned in the array entry if a cell doesn't exist - * @param boolean $calculateFormulas Should formulas be calculated? - * @param boolean $formatData Should formatting be applied to cell values? - * @param boolean $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero - * True - Return rows and columns indexed by their actual row and column IDs - * @return array - */ - public function toArray($nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) { - // Garbage collect... - $this->garbageCollect(); - - // Identify the range that we need to extract from the worksheet - $maxCol = $this->getHighestColumn(); - $maxRow = $this->getHighestRow(); - // Return - return $this->rangeToArray( 'A1:'.$maxCol.$maxRow, - $nullValue, $calculateFormulas, $formatData, $returnCellRef); - } - - /** - * Get row iterator - * - * @param integer $startRow The row number at which to start iterating - * @return PHPExcel_Worksheet_RowIterator - */ - public function getRowIterator($startRow = 1) { - return new PHPExcel_Worksheet_RowIterator($this,$startRow); - } - - /** - * Run PHPExcel garabage collector. - * - * @return PHPExcel_Worksheet - */ - public function garbageCollect() { - // Build a reference table from images -// $imageCoordinates = array(); -// $iterator = $this->getDrawingCollection()->getIterator(); -// while ($iterator->valid()) { -// $imageCoordinates[$iterator->current()->getCoordinates()] = true; -// -// $iterator->next(); -// } -// - // Lookup highest column and highest row if cells are cleaned - $colRow = $this->_cellCollection->getHighestRowAndColumn(); - $highestRow = $colRow['row']; - $highestColumn = PHPExcel_Cell::columnIndexFromString($colRow['column']); - - // Loop through column dimensions - foreach ($this->_columnDimensions as $dimension) { - $highestColumn = max($highestColumn,PHPExcel_Cell::columnIndexFromString($dimension->getColumnIndex())); - } - - // Loop through row dimensions - foreach ($this->_rowDimensions as $dimension) { - $highestRow = max($highestRow,$dimension->getRowIndex()); - } - - // Cache values - if ($highestColumn < 0) { - $this->_cachedHighestColumn = 'A'; - } else { - $this->_cachedHighestColumn = PHPExcel_Cell::stringFromColumnIndex(--$highestColumn); - } - $this->_cachedHighestRow = $highestRow; - - // Return - return $this; - } - - /** - * Get hash code - * - * @return string Hash code - */ - public function getHashCode() { - if ($this->_dirty) { - $this->_hash = md5( $this->_title . - $this->_autoFilter . - ($this->_protection->isProtectionEnabled() ? 't' : 'f') . - __CLASS__ - ); - $this->_dirty = false; - } - return $this->_hash; - } - - /** - * Extract worksheet title from range. - * - * Example: extractSheetTitle("testSheet!A1") ==> 'A1' - * Example: extractSheetTitle("'testSheet 1'!A1", true) ==> array('testSheet 1', 'A1'); - * - * @param string $pRange Range to extract title from - * @param bool $returnRange Return range? (see example) - * @return mixed - */ - public static function extractSheetTitle($pRange, $returnRange = false) { - // Sheet title included? - if (($sep = strpos($pRange, '!')) === false) { - return ''; - } - - if ($returnRange) { - return array( trim(substr($pRange, 0, $sep),"'"), - substr($pRange, $sep + 1) - ); - } - - return substr($pRange, $sep + 1); - } - - /** - * Get hyperlink - * - * @param string $pCellCoordinate Cell coordinate to get hyperlink for - */ - public function getHyperlink($pCellCoordinate = 'A1') - { - // return hyperlink if we already have one - if (isset($this->_hyperlinkCollection[$pCellCoordinate])) { - return $this->_hyperlinkCollection[$pCellCoordinate]; - } - - // else create hyperlink - $this->_hyperlinkCollection[$pCellCoordinate] = new PHPExcel_Cell_Hyperlink(); - return $this->_hyperlinkCollection[$pCellCoordinate]; - } - - /** - * Set hyperlnk - * - * @param string $pCellCoordinate Cell coordinate to insert hyperlink - * @param PHPExcel_Cell_Hyperlink $pHyperlink - * @return PHPExcel_Worksheet - */ - public function setHyperlink($pCellCoordinate = 'A1', PHPExcel_Cell_Hyperlink $pHyperlink = null) - { - if ($pHyperlink === null) { - unset($this->_hyperlinkCollection[$pCellCoordinate]); - } else { - $this->_hyperlinkCollection[$pCellCoordinate] = $pHyperlink; - } - return $this; - } - - /** - * Hyperlink at a specific coordinate exists? - * - * @param string $pCoordinate - * @return boolean - */ - public function hyperlinkExists($pCoordinate = 'A1') - { - return isset($this->_hyperlinkCollection[$pCoordinate]); - } - - /** - * Get collection of hyperlinks - * - * @return PHPExcel_Cell_Hyperlink[] - */ - public function getHyperlinkCollection() - { - return $this->_hyperlinkCollection; - } - - /** - * Get data validation - * - * @param string $pCellCoordinate Cell coordinate to get data validation for - */ - public function getDataValidation($pCellCoordinate = 'A1') - { - // return data validation if we already have one - if (isset($this->_dataValidationCollection[$pCellCoordinate])) { - return $this->_dataValidationCollection[$pCellCoordinate]; - } - - // else create data validation - $this->_dataValidationCollection[$pCellCoordinate] = new PHPExcel_Cell_DataValidation(); - return $this->_dataValidationCollection[$pCellCoordinate]; - } - - /** - * Set data validation - * - * @param string $pCellCoordinate Cell coordinate to insert data validation - * @param PHPExcel_Cell_DataValidation $pDataValidation - * @return PHPExcel_Worksheet - */ - public function setDataValidation($pCellCoordinate = 'A1', PHPExcel_Cell_DataValidation $pDataValidation = null) - { - if ($pDataValidation === null) { - unset($this->_dataValidationCollection[$pCellCoordinate]); - } else { - $this->_dataValidationCollection[$pCellCoordinate] = $pDataValidation; - } - return $this; - } - - /** - * Data validation at a specific coordinate exists? - * - * @param string $pCoordinate - * @return boolean - */ - public function dataValidationExists($pCoordinate = 'A1') - { - return isset($this->_dataValidationCollection[$pCoordinate]); - } - - /** - * Get collection of data validations - * - * @return PHPExcel_Cell_DataValidation[] - */ - public function getDataValidationCollection() - { - return $this->_dataValidationCollection; - } - - /** - * Accepts a range, returning it as a range that falls within the current highest row and column of the worksheet - * - * @param string $range - * @return string Adjusted range value - */ - public function shrinkRangeToFit($range) { - $maxCol = $this->getHighestColumn(); - $maxRow = $this->getHighestRow(); - $maxCol = PHPExcel_Cell::columnIndexFromString($maxCol); - - $rangeBlocks = explode(' ',$range); - foreach ($rangeBlocks as &$rangeSet) { - $rangeBoundaries = PHPExcel_Cell::getRangeBoundaries($rangeSet); - - if (PHPExcel_Cell::columnIndexFromString($rangeBoundaries[0][0]) > $maxCol) { $rangeBoundaries[0][0] = PHPExcel_Cell::stringFromColumnIndex($maxCol); } - if ($rangeBoundaries[0][1] > $maxRow) { $rangeBoundaries[0][1] = $maxRow; } - if (PHPExcel_Cell::columnIndexFromString($rangeBoundaries[1][0]) > $maxCol) { $rangeBoundaries[1][0] = PHPExcel_Cell::stringFromColumnIndex($maxCol); } - if ($rangeBoundaries[1][1] > $maxRow) { $rangeBoundaries[1][1] = $maxRow; } - $rangeSet = $rangeBoundaries[0][0].$rangeBoundaries[0][1].':'.$rangeBoundaries[1][0].$rangeBoundaries[1][1]; - } - unset($rangeSet); - $stRange = implode(' ',$rangeBlocks); - - return $stRange; - } - - - /** - * Get tab color - * - * @return PHPExcel_Style_Color - */ - public function getTabColor() - { - if ($this->_tabColor === NULL) - $this->_tabColor = new PHPExcel_Style_Color(); - - return $this->_tabColor; - } - - /** - * Reset tab color - * - * @return PHPExcel_Worksheet - */ - public function resetTabColor() - { - $this->_tabColor = null; - unset($this->_tabColor); - - return $this; - } - - /** - * Tab color set? - * - * @return boolean - */ - public function isTabColorSet() - { - return ($this->_tabColor !== NULL); - } - - /** - * Copy worksheet (!= clone!) - * - * @return PHPExcel_Worksheet - */ - public function copy() { - $copied = clone $this; - - return $copied; - } - - /** - * Implement PHP __clone to create a deep clone, not just a shallow copy. - */ - public function __clone() { - foreach ($this as $key => $val) { - if ($key == '_parent') { - continue; - } - - if (is_object($val) || (is_array($val))) { - if ($key == '_cellCollection') { - $newCollection = clone $this->_cellCollection; - $newCollection->copyCellCollection($this); - $this->_cellCollection = $newCollection; - } elseif ($key == '_drawingCollection') { - $newCollection = clone $this->_drawingCollection; - $this->_drawingCollection = $newCollection; - } elseif (($key == '_autoFilter') && (is_a($this->_autoFilter,'PHPExcel_Worksheet_AutoFilter'))) { - $newAutoFilter = clone $this->_autoFilter; - $this->_autoFilter = $newAutoFilter; - $this->_autoFilter->setParent($this); - } else { - $this->{$key} = unserialize(serialize($val)); - } - } - } + public function hasCodeName(){ + return !(is_null($this->_codeName)); } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Worksheet/AutoFilter.php b/htdocs/includes/phpexcel/PHPExcel/Worksheet/AutoFilter.php index e6ea6f207a7..03055e10b99 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Worksheet/AutoFilter.php +++ b/htdocs/includes/phpexcel/PHPExcel/Worksheet/AutoFilter.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_AutoFilter { @@ -61,6 +61,9 @@ class PHPExcel_Worksheet_AutoFilter /** * Create a new PHPExcel_Worksheet_AutoFilter + * + * @param string $pRange Cell range (i.e. A1:E10) + * @param PHPExcel_Worksheet $pSheet */ public function __construct($pRange = '', PHPExcel_Worksheet $pSheet = NULL) { @@ -80,7 +83,7 @@ class PHPExcel_Worksheet_AutoFilter /** * Set AutoFilter Parent Worksheet * - * @param PHPExcel_Worksheet + * @param PHPExcel_Worksheet $pSheet * @return PHPExcel_Worksheet_AutoFilter */ public function setParent(PHPExcel_Worksheet $pSheet = NULL) { @@ -243,7 +246,7 @@ class PHPExcel_Worksheet_AutoFilter /** * Clear a specified AutoFilter Column * - * @param string $pColumn Column name (e.g. A) + * @param string $pColumn Column name (e.g. A) * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_AutoFilter */ @@ -347,10 +350,10 @@ class PHPExcel_Worksheet_AutoFilter * Test if cell value is within a set of values defined by a ruleset * * @param mixed $cellValue - * @param mixed[] $dataSet + * @param mixed[] $ruleSet * @return boolean */ - private static function _filterTestInCustomDataSet($cellValue,$ruleSet) + private static function _filterTestInCustomDataSet($cellValue, $ruleSet) { $dataSet = $ruleSet['filterRules']; $join = $ruleSet['join']; @@ -424,10 +427,10 @@ class PHPExcel_Worksheet_AutoFilter * Test if cell date value is matches a set of values defined by a set of months * * @param mixed $cellValue - * @param mixed[] $dataSet + * @param mixed[] $monthSet * @return boolean */ - private static function _filterTestInPeriodDateSet($cellValue,$monthSet) + private static function _filterTestInPeriodDateSet($cellValue, $monthSet) { // Blank cells are always ignored, so return a FALSE if (($cellValue == '') || ($cellValue === NULL)) { @@ -457,7 +460,7 @@ class PHPExcel_Worksheet_AutoFilter * Convert a dynamic rule daterange to a custom filter range expression for ease of calculation * * @param string $dynamicRuleType - * @param PHPExcel_Worksheet_AutoFilter_Column $filterColumn + * @param PHPExcel_Worksheet_AutoFilter_Column &$filterColumn * @return mixed[] */ private function _dynamicFilterDateRange($dynamicRuleType, &$filterColumn) @@ -725,7 +728,7 @@ class PHPExcel_Worksheet_AutoFilter // Date based if ($dynamicRuleType{0} == 'M' || $dynamicRuleType{0} == 'Q') { // Month or Quarter - list($periodType,$period) = sscanf($dynamicRuleType,'%[A-Z]%d'); + sscanf($dynamicRuleType,'%[A-Z]%d', $periodType, $period); if ($periodType == 'M') { $ruleValues = array($period); } else { @@ -826,20 +829,20 @@ class PHPExcel_Worksheet_AutoFilter if (is_object($value)) { if ($key == '_workSheet') { // Detach from worksheet - $this->$key = NULL; + $this->{$key} = NULL; } else { - $this->$key = clone $value; + $this->{$key} = clone $value; } } elseif ((is_array($value)) && ($key == '_columns')) { // The columns array of PHPExcel_Worksheet_AutoFilter objects - $this->$key = array(); + $this->{$key} = array(); foreach ($value as $k => $v) { - $this->$key[$k] = clone $v; + $this->{$key}[$k] = clone $v; // attach the new cloned Column to this new cloned Autofilter object - $this->$key[$k]->setParent($this); + $this->{$key}[$k]->setParent($this); } } else { - $this->$key = $value; + $this->{$key} = $value; } } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Worksheet/AutoFilter/Column.php b/htdocs/includes/phpexcel/PHPExcel/Worksheet/AutoFilter/Column.php index bb70ec672fe..12043d5a0a1 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Worksheet/AutoFilter/Column.php +++ b/htdocs/includes/phpexcel/PHPExcel/Worksheet/AutoFilter/Column.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_AutoFilter_Column { @@ -44,6 +44,11 @@ class PHPExcel_Worksheet_AutoFilter_Column // e.g. filtered by date = TODAY const AUTOFILTER_FILTERTYPE_TOPTENFILTER = 'top10'; + /** + * Types of autofilter rules + * + * @var string[] + */ private static $_filterTypes = array( // Currently we're not handling // colorFilter @@ -59,6 +64,11 @@ class PHPExcel_Worksheet_AutoFilter_Column const AUTOFILTER_COLUMN_JOIN_AND = 'and'; const AUTOFILTER_COLUMN_JOIN_OR = 'or'; + /** + * Join options for autofilter rules + * + * @var string[] + */ private static $_ruleJoins = array( self::AUTOFILTER_COLUMN_JOIN_AND, self::AUTOFILTER_COLUMN_JOIN_OR, @@ -114,6 +124,9 @@ class PHPExcel_Worksheet_AutoFilter_Column /** * Create a new PHPExcel_Worksheet_AutoFilter_Column + * + * @param string $pColumn Column (e.g. A) + * @param PHPExcel_Worksheet_AutoFilter $pParent Autofilter for this column */ public function __construct($pColumn, PHPExcel_Worksheet_AutoFilter $pParent = NULL) { @@ -134,7 +147,7 @@ class PHPExcel_Worksheet_AutoFilter_Column * Set AutoFilter Column Index * * @param string $pColumn Column (e.g. A) - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_AutoFilter_Column */ public function setColumnIndex($pColumn) { @@ -183,7 +196,7 @@ class PHPExcel_Worksheet_AutoFilter_Column * Set AutoFilter Type * * @param string $pFilterType - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_AutoFilter_Column */ public function setFilterType($pFilterType = self::AUTOFILTER_FILTERTYPE_FILTER) { @@ -209,7 +222,7 @@ class PHPExcel_Worksheet_AutoFilter_Column * Set AutoFilter Multiple Rules And/Or * * @param string $pJoin And/Or - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_AutoFilter_Column */ public function setJoin($pJoin = self::AUTOFILTER_COLUMN_JOIN_OR) { @@ -228,7 +241,7 @@ class PHPExcel_Worksheet_AutoFilter_Column * Set AutoFilter Attributes * * @param string[] $pAttributes - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_AutoFilter_Column */ public function setAttributes($pAttributes = array()) { @@ -242,7 +255,7 @@ class PHPExcel_Worksheet_AutoFilter_Column * * @param string $pName Attribute Name * @param string $pValue Attribute Value - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_AutoFilter_Column */ public function setAttribute($pName, $pValue) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Worksheet/AutoFilter/Column/Rule.php b/htdocs/includes/phpexcel/PHPExcel/Worksheet/AutoFilter/Column/Rule.php index 209012ce180..ae33683f708 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Worksheet/AutoFilter/Column/Rule.php +++ b/htdocs/includes/phpexcel/PHPExcel/Worksheet/AutoFilter/Column/Rule.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_AutoFilter_Column_Rule { @@ -269,6 +269,8 @@ class PHPExcel_Worksheet_AutoFilter_Column_Rule /** * Create a new PHPExcel_Worksheet_AutoFilter_Column_Rule + * + * @param PHPExcel_Worksheet_AutoFilter_Column $pParent */ public function __construct(PHPExcel_Worksheet_AutoFilter_Column $pParent = NULL) { @@ -288,7 +290,7 @@ class PHPExcel_Worksheet_AutoFilter_Column_Rule * Set AutoFilter Rule Type * * @param string $pRuleType - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_AutoFilter_Column */ public function setRuleType($pRuleType = self::AUTOFILTER_RULETYPE_FILTER) { @@ -314,7 +316,7 @@ class PHPExcel_Worksheet_AutoFilter_Column_Rule * Set AutoFilter Rule Value * * @param string|string[] $pValue - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_AutoFilter_Column_Rule */ public function setValue($pValue = '') { @@ -354,7 +356,7 @@ class PHPExcel_Worksheet_AutoFilter_Column_Rule * Set AutoFilter Rule Operator * * @param string $pOperator - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_AutoFilter_Column_Rule */ public function setOperator($pOperator = self::AUTOFILTER_COLUMN_RULE_EQUAL) { @@ -382,7 +384,7 @@ class PHPExcel_Worksheet_AutoFilter_Column_Rule * Set AutoFilter Rule Grouping * * @param string $pGrouping - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_AutoFilter_Column_Rule */ public function setGrouping($pGrouping = NULL) { @@ -404,7 +406,7 @@ class PHPExcel_Worksheet_AutoFilter_Column_Rule * @param string $pOperator * @param string|string[] $pValue * @param string $pGrouping - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_AutoFilter_Column_Rule */ public function setRule($pOperator = self::AUTOFILTER_COLUMN_RULE_EQUAL, $pValue = '', $pGrouping = NULL) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Worksheet/BaseDrawing.php b/htdocs/includes/phpexcel/PHPExcel/Worksheet/BaseDrawing.php index 1e6725a38ad..4db0f8825a9 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Worksheet/BaseDrawing.php +++ b/htdocs/includes/phpexcel/PHPExcel/Worksheet/BaseDrawing.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable { @@ -212,7 +212,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable * * @param PHPExcel_Worksheet $pValue * @param bool $pOverrideOld If a Worksheet has already been assigned, overwrite it and remove image from old Worksheet? - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_BaseDrawing */ public function setWorksheet(PHPExcel_Worksheet $pValue = null, $pOverrideOld = false) { @@ -237,7 +237,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable // Set new PHPExcel_Worksheet $this->setWorksheet($pValue); } else { - throw new Exception("A PHPExcel_Worksheet has already been assigned. Drawings can only exist on one PHPExcel_Worksheet."); + throw new PHPExcel_Exception("A PHPExcel_Worksheet has already been assigned. Drawings can only exist on one PHPExcel_Worksheet."); } } return $this; @@ -440,7 +440,7 @@ class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable * Set Shadow * * @param PHPExcel_Worksheet_Drawing_Shadow $pValue - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_BaseDrawing */ public function setShadow(PHPExcel_Worksheet_Drawing_Shadow $pValue = null) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Worksheet/CellIterator.php b/htdocs/includes/phpexcel/PHPExcel/Worksheet/CellIterator.php index a612d550c62..4b968167a8d 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Worksheet/CellIterator.php +++ b/htdocs/includes/phpexcel/PHPExcel/Worksheet/CellIterator.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -33,7 +33,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_CellIterator implements Iterator { diff --git a/htdocs/includes/phpexcel/PHPExcel/Worksheet/ColumnDimension.php b/htdocs/includes/phpexcel/PHPExcel/Worksheet/ColumnDimension.php index 0915a359961..79db1c58ffa 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Worksheet/ColumnDimension.php +++ b/htdocs/includes/phpexcel/PHPExcel/Worksheet/ColumnDimension.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_ColumnDimension { @@ -195,12 +195,12 @@ class PHPExcel_Worksheet_ColumnDimension * Value must be between 0 and 7 * * @param int $pValue - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_ColumnDimension */ public function setOutlineLevel($pValue) { if ($pValue < 0 || $pValue > 7) { - throw new Exception("Outline level must range between 0 and 7."); + throw new PHPExcel_Exception("Outline level must range between 0 and 7."); } $this->_outlineLevel = $pValue; diff --git a/htdocs/includes/phpexcel/PHPExcel/Worksheet/Drawing.php b/htdocs/includes/phpexcel/PHPExcel/Worksheet/Drawing.php index 1d4e4b53fb0..56f0cfde13e 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Worksheet/Drawing.php +++ b/htdocs/includes/phpexcel/PHPExcel/Worksheet/Drawing.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet_Drawing - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet_Drawing - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_Drawing extends PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable { @@ -98,7 +98,7 @@ class PHPExcel_Worksheet_Drawing extends PHPExcel_Worksheet_BaseDrawing implemen * * @param string $pValue File path * @param boolean $pVerifyFile Verify file - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_Drawing */ public function setPath($pValue = '', $pVerifyFile = true) { @@ -111,7 +111,7 @@ class PHPExcel_Worksheet_Drawing extends PHPExcel_Worksheet_BaseDrawing implemen list($this->_width, $this->_height) = getimagesize($pValue); } } else { - throw new Exception("File $pValue not found!"); + throw new PHPExcel_Exception("File $pValue not found!"); } } else { $this->_path = $pValue; diff --git a/htdocs/includes/phpexcel/PHPExcel/Worksheet/Drawing/Shadow.php b/htdocs/includes/phpexcel/PHPExcel/Worksheet/Drawing/Shadow.php index d4a53733dc3..5df448964b0 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Worksheet/Drawing/Shadow.php +++ b/htdocs/includes/phpexcel/PHPExcel/Worksheet/Drawing/Shadow.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet_Drawing - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet_Drawing - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable { @@ -226,7 +226,7 @@ class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable * Set Color * * @param PHPExcel_Style_Color $pValue - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_Drawing_Shadow */ public function setColor(PHPExcel_Style_Color $pValue = null) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Worksheet/HeaderFooter.php b/htdocs/includes/phpexcel/PHPExcel/Worksheet/HeaderFooter.php index e2524e1f951..82d7faf6d4e 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Worksheet/HeaderFooter.php +++ b/htdocs/includes/phpexcel/PHPExcel/Worksheet/HeaderFooter.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -91,7 +91,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_HeaderFooter { @@ -392,7 +392,7 @@ class PHPExcel_Worksheet_HeaderFooter * * @param PHPExcel_Worksheet_HeaderFooterDrawing $image * @param string $location - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_HeaderFooter */ public function addImage(PHPExcel_Worksheet_HeaderFooterDrawing $image = null, $location = self::IMAGE_HEADER_LEFT) { @@ -404,7 +404,7 @@ class PHPExcel_Worksheet_HeaderFooter * Remove header/footer image * * @param string $location - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_HeaderFooter */ public function removeImage($location = self::IMAGE_HEADER_LEFT) { @@ -418,12 +418,12 @@ class PHPExcel_Worksheet_HeaderFooter * Set header/footer images * * @param PHPExcel_Worksheet_HeaderFooterDrawing[] $images - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_HeaderFooter */ public function setImages($images) { if (!is_array($images)) { - throw new Exception('Invalid parameter!'); + throw new PHPExcel_Exception('Invalid parameter!'); } $this->_headerFooterImages = $images; diff --git a/htdocs/includes/phpexcel/PHPExcel/Worksheet/HeaderFooterDrawing.php b/htdocs/includes/phpexcel/PHPExcel/Worksheet/HeaderFooterDrawing.php index 94672da4722..1c6f4e19087 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Worksheet/HeaderFooterDrawing.php +++ b/htdocs/includes/phpexcel/PHPExcel/Worksheet/HeaderFooterDrawing.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing implements PHPExcel_IComparable { @@ -296,7 +296,7 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing * * @param string $pValue File path * @param boolean $pVerifyFile Verify file - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_HeaderFooterDrawing */ public function setPath($pValue = '', $pVerifyFile = true) { @@ -309,7 +309,7 @@ class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing list($this->_width, $this->_height) = getimagesize($pValue); } } else { - throw new Exception("File $pValue not found!"); + throw new PHPExcel_Exception("File $pValue not found!"); } } else { $this->_path = $pValue; diff --git a/htdocs/includes/phpexcel/PHPExcel/Worksheet/MemoryDrawing.php b/htdocs/includes/phpexcel/PHPExcel/Worksheet/MemoryDrawing.php index 223a29f06b0..93266d210c9 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Worksheet/MemoryDrawing.php +++ b/htdocs/includes/phpexcel/PHPExcel/Worksheet/MemoryDrawing.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_MemoryDrawing extends PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable { diff --git a/htdocs/includes/phpexcel/PHPExcel/Worksheet/PageMargins.php b/htdocs/includes/phpexcel/PHPExcel/Worksheet/PageMargins.php index 7d31a5f6291..671711ff50e 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Worksheet/PageMargins.php +++ b/htdocs/includes/phpexcel/PHPExcel/Worksheet/PageMargins.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_PageMargins { diff --git a/htdocs/includes/phpexcel/PHPExcel/Worksheet/PageSetup.php b/htdocs/includes/phpexcel/PHPExcel/Worksheet/PageSetup.php index 693f1c6a83f..9512dbe48df 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Worksheet/PageSetup.php +++ b/htdocs/includes/phpexcel/PHPExcel/Worksheet/PageSetup.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -102,7 +102,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_PageSetup { @@ -339,7 +339,7 @@ class PHPExcel_Worksheet_PageSetup * @param int? $pValue * @param boolean $pUpdate Update fitToPage so scaling applies rather than fitToHeight / fitToWidth * @return PHPExcel_Worksheet_PageSetup - * @throws Exception + * @throws PHPExcel_Exception */ public function setScale($pValue = 100, $pUpdate = true) { // Microsoft Office Excel 2007 only allows setting a scale between 10 and 400 via the user interface, @@ -350,7 +350,7 @@ class PHPExcel_Worksheet_PageSetup $this->_fitToPage = false; } } else { - throw new Exception("Scale must not be negative"); + throw new PHPExcel_Exception("Scale must not be negative"); } return $this; } @@ -568,7 +568,7 @@ class PHPExcel_Worksheet_PageSetup * Default behaviour, or a index value of 0, will return all ranges as a comma-separated string * Otherwise, the specific range identified by the value of $index will be returned * Print areas are numbered from 1 - * @throws Exception + * @throws PHPExcel_Exception * @return string */ public function getPrintArea($index = 0) { @@ -579,7 +579,7 @@ class PHPExcel_Worksheet_PageSetup if (isset($printAreas[$index-1])) { return $printAreas[$index-1]; } - throw new Exception("Requested Print Area does not exist"); + throw new PHPExcel_Exception("Requested Print Area does not exist"); } /** @@ -640,15 +640,15 @@ class PHPExcel_Worksheet_PageSetup * Default behaviour, or the "O" method, overwrites existing print area * The "I" method, inserts the new print area before any specified index, or at the end of the list * @return PHPExcel_Worksheet_PageSetup - * @throws Exception + * @throws PHPExcel_Exception */ public function setPrintArea($value, $index = 0, $method = self::SETPRINTRANGE_OVERWRITE) { if (strpos($value,'!') !== false) { - throw new Exception('Cell coordinate must not specify a worksheet.'); + throw new PHPExcel_Exception('Cell coordinate must not specify a worksheet.'); } elseif (strpos($value,':') === false) { - throw new Exception('Cell coordinate must be a range of cells.'); + throw new PHPExcel_Exception('Cell coordinate must be a range of cells.'); } elseif (strpos($value,'$') !== false) { - throw new Exception('Cell coordinate must not be absolute.'); + throw new PHPExcel_Exception('Cell coordinate must not be absolute.'); } $value = strtoupper($value); @@ -661,7 +661,7 @@ class PHPExcel_Worksheet_PageSetup $index = count($printAreas) - abs($index) + 1; } if (($index <= 0) || ($index > count($printAreas))) { - throw new Exception('Invalid index for setting print range.'); + throw new PHPExcel_Exception('Invalid index for setting print range.'); } $printAreas[$index-1] = $value; $this->_printArea = implode(',',$printAreas); @@ -675,13 +675,13 @@ class PHPExcel_Worksheet_PageSetup $index = abs($index) - 1; } if ($index > count($printAreas)) { - throw new Exception('Invalid index for setting print range.'); + throw new PHPExcel_Exception('Invalid index for setting print range.'); } $printAreas = array_merge(array_slice($printAreas,0,$index),array($value),array_slice($printAreas,$index)); $this->_printArea = implode(',',$printAreas); } } else { - throw new Exception('Invalid method for setting print range.'); + throw new PHPExcel_Exception('Invalid method for setting print range.'); } return $this; @@ -698,7 +698,7 @@ class PHPExcel_Worksheet_PageSetup * list. * Print areas are numbered from 1 * @return PHPExcel_Worksheet_PageSetup - * @throws Exception + * @throws PHPExcel_Exception */ public function addPrintArea($value, $index = -1) { return $this->setPrintArea($value, $index, self::SETPRINTRANGE_INSERT); @@ -725,7 +725,7 @@ class PHPExcel_Worksheet_PageSetup * Default behaviour, or the "O" method, overwrites existing print area * The "I" method, inserts the new print area before any specified index, or at the end of the list * @return PHPExcel_Worksheet_PageSetup - * @throws Exception + * @throws PHPExcel_Exception */ public function setPrintAreaByColumnAndRow($column1, $row1, $column2, $row2, $index = 0, $method = self::SETPRINTRANGE_OVERWRITE) { @@ -746,7 +746,7 @@ class PHPExcel_Worksheet_PageSetup * list. * Print areas are numbered from 1 * @return PHPExcel_Worksheet_PageSetup - * @throws Exception + * @throws PHPExcel_Exception */ public function addPrintAreaByColumnAndRow($column1, $row1, $column2, $row2, $index = -1) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Worksheet/Protection.php b/htdocs/includes/phpexcel/PHPExcel/Worksheet/Protection.php index e7c3436f179..f41dd53a2a0 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Worksheet/Protection.php +++ b/htdocs/includes/phpexcel/PHPExcel/Worksheet/Protection.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_Protection { diff --git a/htdocs/includes/phpexcel/PHPExcel/Worksheet/Row.php b/htdocs/includes/phpexcel/PHPExcel/Worksheet/Row.php index ba9d8530b48..2e9bd132867 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Worksheet/Row.php +++ b/htdocs/includes/phpexcel/PHPExcel/Worksheet/Row.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -33,7 +33,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_Row { diff --git a/htdocs/includes/phpexcel/PHPExcel/Worksheet/RowDimension.php b/htdocs/includes/phpexcel/PHPExcel/Worksheet/RowDimension.php index 7bacabd2378..69b7ba813eb 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Worksheet/RowDimension.php +++ b/htdocs/includes/phpexcel/PHPExcel/Worksheet/RowDimension.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_RowDimension { @@ -195,12 +195,12 @@ class PHPExcel_Worksheet_RowDimension * Value must be between 0 and 7 * * @param int $pValue - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_RowDimension */ public function setOutlineLevel($pValue) { if ($pValue < 0 || $pValue > 7) { - throw new Exception("Outline level must range between 0 and 7."); + throw new PHPExcel_Exception("Outline level must range between 0 and 7."); } $this->_outlineLevel = $pValue; diff --git a/htdocs/includes/phpexcel/PHPExcel/Worksheet/RowIterator.php b/htdocs/includes/phpexcel/PHPExcel/Worksheet/RowIterator.php index c8e832ed72c..f2d962f5741 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Worksheet/RowIterator.php +++ b/htdocs/includes/phpexcel/PHPExcel/Worksheet/RowIterator.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -33,7 +33,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_RowIterator implements Iterator { diff --git a/htdocs/includes/phpexcel/PHPExcel/Worksheet/SheetView.php b/htdocs/includes/phpexcel/PHPExcel/Worksheet/SheetView.php index bdaf323b264..05fbf286b06 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Worksheet/SheetView.php +++ b/htdocs/includes/phpexcel/PHPExcel/Worksheet/SheetView.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Worksheet - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Worksheet_SheetView { @@ -96,7 +96,7 @@ class PHPExcel_Worksheet_SheetView * Valid values range from 10 to 400. * * @param int $pValue - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_SheetView */ public function setZoomScale($pValue = 100) { @@ -105,7 +105,7 @@ class PHPExcel_Worksheet_SheetView if (($pValue >= 1) || is_null($pValue)) { $this->_zoomScale = $pValue; } else { - throw new Exception("Scale must be greater than or equal to 1."); + throw new PHPExcel_Exception("Scale must be greater than or equal to 1."); } return $this; } @@ -125,14 +125,14 @@ class PHPExcel_Worksheet_SheetView * Valid values range from 10 to 400. * * @param int $pValue - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_SheetView */ public function setZoomScaleNormal($pValue = 100) { if (($pValue >= 1) || is_null($pValue)) { $this->_zoomScaleNormal = $pValue; } else { - throw new Exception("Scale must be greater than or equal to 1."); + throw new PHPExcel_Exception("Scale must be greater than or equal to 1."); } return $this; } @@ -155,7 +155,7 @@ class PHPExcel_Worksheet_SheetView * 'pageBreakPreview' self::SHEETVIEW_PAGE_BREAK_PREVIEW * * @param string $pValue - * @throws Exception + * @throws PHPExcel_Exception * @return PHPExcel_Worksheet_SheetView */ public function setView($pValue = NULL) { @@ -166,7 +166,7 @@ class PHPExcel_Worksheet_SheetView if (in_array($pValue, self::$_sheetViewTypes)) { $this->_sheetviewType = $pValue; } else { - throw new Exception("Invalid sheetview layout type."); + throw new PHPExcel_Exception("Invalid sheetview layout type."); } return $this; diff --git a/htdocs/includes/phpexcel/PHPExcel/WorksheetIterator.php b/htdocs/includes/phpexcel/PHPExcel/WorksheetIterator.php index 9eff5382dd9..624b49b6208 100644 --- a/htdocs/includes/phpexcel/PHPExcel/WorksheetIterator.php +++ b/htdocs/includes/phpexcel/PHPExcel/WorksheetIterator.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) - * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.8.0, 2014-03-02 */ @@ -33,45 +33,48 @@ * * @category PHPExcel * @package PHPExcel - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_WorksheetIterator implements Iterator { - /** - * Spreadsheet to iterate - * - * @var PHPExcel - */ - private $_subject; + /** + * Spreadsheet to iterate + * + * @var PHPExcel + */ + private $_subject; - /** - * Current iterator position - * - * @var int - */ - private $_position = 0; + /** + * Current iterator position + * + * @var int + */ + private $_position = 0; - /** - * Create a new worksheet iterator - * - * @param PHPExcel $subject - */ - public function __construct(PHPExcel $subject = null) { - // Set subject - $this->_subject = $subject; - } + /** + * Create a new worksheet iterator + * + * @param PHPExcel $subject + */ + public function __construct(PHPExcel $subject = null) + { + // Set subject + $this->_subject = $subject; + } - /** - * Destructor - */ - public function __destruct() { - unset($this->_subject); - } + /** + * Destructor + */ + public function __destruct() + { + unset($this->_subject); + } - /** - * Rewind iterator - */ - public function rewind() { + /** + * Rewind iterator + */ + public function rewind() + { $this->_position = 0; } @@ -80,8 +83,9 @@ class PHPExcel_WorksheetIterator implements Iterator * * @return PHPExcel_Worksheet */ - public function current() { - return $this->_subject->getSheet($this->_position); + public function current() + { + return $this->_subject->getSheet($this->_position); } /** @@ -89,14 +93,16 @@ class PHPExcel_WorksheetIterator implements Iterator * * @return int */ - public function key() { + public function key() + { return $this->_position; } /** * Next value */ - public function next() { + public function next() + { ++$this->_position; } @@ -105,7 +111,8 @@ class PHPExcel_WorksheetIterator implements Iterator * * @return boolean */ - public function valid() { + public function valid() + { return $this->_position < $this->_subject->getSheetCount(); } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Abstract.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Abstract.php new file mode 100644 index 00000000000..7e09ef83a08 --- /dev/null +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Abstract.php @@ -0,0 +1,158 @@ +_includeCharts; + } + + /** + * Set write charts in workbook + * Set to true, to advise the Writer to include any charts that exist in the PHPExcel object. + * Set to false (the default) to ignore charts. + * + * @param boolean $pValue + * @return PHPExcel_Writer_IWriter + */ + public function setIncludeCharts($pValue = FALSE) { + $this->_includeCharts = (boolean) $pValue; + return $this; + } + + /** + * Get Pre-Calculate Formulas flag + * If this is true (the default), then the writer will recalculate all formulae in a workbook when saving, + * so that the pre-calculated values are immediately available to MS Excel or other office spreadsheet + * viewer when opening the file + * If false, then formulae are not calculated on save. This is faster for saving in PHPExcel, but slower + * when opening the resulting file in MS Excel, because Excel has to recalculate the formulae itself + * + * @return boolean + */ + public function getPreCalculateFormulas() { + return $this->_preCalculateFormulas; + } + + /** + * Set Pre-Calculate Formulas + * Set to true (the default) to advise the Writer to calculate all formulae on save + * Set to false to prevent precalculation of formulae on save. + * + * @param boolean $pValue Pre-Calculate Formulas? + * @return PHPExcel_Writer_IWriter + */ + public function setPreCalculateFormulas($pValue = TRUE) { + $this->_preCalculateFormulas = (boolean) $pValue; + return $this; + } + + /** + * Get use disk caching where possible? + * + * @return boolean + */ + public function getUseDiskCaching() { + return $this->_useDiskCaching; + } + + /** + * Set use disk caching where possible? + * + * @param boolean $pValue + * @param string $pDirectory Disk caching directory + * @throws PHPExcel_Writer_Exception when directory does not exist + * @return PHPExcel_Writer_Excel2007 + */ + public function setUseDiskCaching($pValue = FALSE, $pDirectory = NULL) { + $this->_useDiskCaching = $pValue; + + if ($pDirectory !== NULL) { + if (is_dir($pDirectory)) { + $this->_diskCachingDirectory = $pDirectory; + } else { + throw new PHPExcel_Writer_Exception("Directory does not exist: $pDirectory"); + } + } + return $this; + } + + /** + * Get disk caching directory + * + * @return string + */ + public function getDiskCachingDirectory() { + return $this->_diskCachingDirectory; + } +} diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/CSV.php b/htdocs/includes/phpexcel/PHPExcel/Writer/CSV.php index 11a399e3b22..521874f25ed 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/CSV.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/CSV.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,10 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * @category PHPExcel - * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @package PHPExcel_Writer_CSV + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -30,10 +30,10 @@ * PHPExcel_Writer_CSV * * @category PHPExcel - * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @package PHPExcel_Writer_CSV + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Writer_CSV implements PHPExcel_Writer_IWriter { +class PHPExcel_Writer_CSV extends PHPExcel_Writer_Abstract implements PHPExcel_Writer_IWriter { /** * PHPExcel object * @@ -69,13 +69,6 @@ class PHPExcel_Writer_CSV implements PHPExcel_Writer_IWriter { */ private $_sheetIndex = 0; - /** - * Pre-calculate formulas - * - * @var boolean - */ - private $_preCalculateFormulas = true; - /** * Whether to write a BOM (for UTF8). * @@ -103,36 +96,37 @@ class PHPExcel_Writer_CSV implements PHPExcel_Writer_IWriter { * Save PHPExcel to file * * @param string $pFilename - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function save($pFilename = null) { // Fetch sheet $sheet = $this->_phpExcel->getSheet($this->_sheetIndex); - $saveDebugLog = PHPExcel_Calculation::getInstance()->writeDebugLog; - PHPExcel_Calculation::getInstance()->writeDebugLog = false; + $saveDebugLog = PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->getWriteDebugLog(); + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog(FALSE); $saveArrayReturnType = PHPExcel_Calculation::getArrayReturnType(); PHPExcel_Calculation::setArrayReturnType(PHPExcel_Calculation::RETURN_ARRAY_AS_VALUE); // Open file $fileHandle = fopen($pFilename, 'wb+'); if ($fileHandle === false) { - throw new Exception("Could not open file $pFilename for writing."); + throw new PHPExcel_Writer_Exception("Could not open file $pFilename for writing."); } if ($this->_excelCompatibility) { - // Write the UTF-16LE BOM code - fwrite($fileHandle, "\xFF\xFE"); // Excel uses UTF-16LE encoding - $this->setEnclosure(); // Default enclosure is " - $this->setDelimiter("\t"); // Excel delimiter is a TAB + fwrite($fileHandle, "\xEF\xBB\xBF"); // Enforce UTF-8 BOM Header + $this->setEnclosure('"'); // Set enclosure to " + $this->setDelimiter(";"); // Set delimiter to a semi-colon + $this->setLineEnding("\r\n"); + fwrite($fileHandle, 'sep=' . $this->getDelimiter() . $this->_lineEnding); } elseif ($this->_useBOM) { - // Write the UTF-8 BOM code + // Write the UTF-8 BOM code if required fwrite($fileHandle, "\xEF\xBB\xBF"); } // Identify the range that we need to extract from the worksheet - $maxCol = $sheet->getHighestColumn(); - $maxRow = $sheet->getHighestRow(); + $maxCol = $sheet->getHighestDataColumn(); + $maxRow = $sheet->getHighestDataRow(); // Write rows to file for($row = 1; $row <= $maxRow; ++$row) { @@ -146,7 +140,7 @@ class PHPExcel_Writer_CSV implements PHPExcel_Writer_IWriter { fclose($fileHandle); PHPExcel_Calculation::setArrayReturnType($saveArrayReturnType); - PHPExcel_Calculation::getInstance()->writeDebugLog = $saveDebugLog; + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog($saveDebugLog); } /** @@ -278,7 +272,7 @@ class PHPExcel_Writer_CSV implements PHPExcel_Writer_IWriter { * * @param mixed $pFileHandle PHP filehandle * @param array $pValues Array containing values in a row - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeLine($pFileHandle = null, $pValues = null) { if (is_array($pValues)) { @@ -307,33 +301,10 @@ class PHPExcel_Writer_CSV implements PHPExcel_Writer_IWriter { $line .= $this->_lineEnding; // Write to file - if ($this->_excelCompatibility) { - fwrite($pFileHandle, mb_convert_encoding($line,"UTF-16LE","UTF-8")); - } else { - fwrite($pFileHandle, $line); - } + fwrite($pFileHandle, $line); } else { - throw new Exception("Invalid data row passed to CSV writer."); + throw new PHPExcel_Writer_Exception("Invalid data row passed to CSV writer."); } } - /** - * Get Pre-Calculate Formulas - * - * @return boolean - */ - public function getPreCalculateFormulas() { - return $this->_preCalculateFormulas; - } - - /** - * Set Pre-Calculate Formulas - * - * @param boolean $pValue Pre-Calculate Formulas? - * @return PHPExcel_Writer_CSV - */ - public function setPreCalculateFormulas($pValue = true) { - $this->_preCalculateFormulas = $pValue; - return $this; - } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007.php index 6a1b9887d52..a8f7593c106 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -30,25 +30,21 @@ * PHPExcel_Writer_Excel2007 * * @category PHPExcel - * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @package PHPExcel_Writer_2007 + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter +class PHPExcel_Writer_Excel2007 extends PHPExcel_Writer_Abstract implements PHPExcel_Writer_IWriter { - /** - * Write charts that are defined in the workbook? - * Identifies whether the Writer should write definitions for any charts that exist in the PHPExcel object; - * - * @var boolean - */ - private $_includeCharts = false; - /** * Pre-calculate formulas + * Forces PHPExcel to recalculate all formulae in a workbook when saving, so that the pre-calculated values are + * immediately available to MS Excel or other office spreadsheet viewer when opening the file * + * Overrides the default TRUE for this specific writer for performance reasons + * * @var boolean */ - private $_preCalculateFormulas = true; + protected $_preCalculateFormulas = FALSE; /** * Office2003 compatibility @@ -85,6 +81,13 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter */ private $_stylesConditionalHashTable; + /** + * Private unique PHPExcel_Style HashTable + * + * @var PHPExcel_HashTable + */ + private $_styleHashTable; + /** * Private unique PHPExcel_Style_Fill HashTable * @@ -120,20 +123,6 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter */ private $_drawingHashTable; - /** - * Use disk caching where possible? - * - * @var boolean - */ - private $_useDiskCaching = false; - - /** - * Disk caching directory - * - * @var string - */ - private $_diskCachingDirectory = './'; - /** * Create a new PHPExcel_Writer_Excel2007 * @@ -155,6 +144,8 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter 'drawing' => 'PHPExcel_Writer_Excel2007_Drawing', 'comments' => 'PHPExcel_Writer_Excel2007_Comments', 'chart' => 'PHPExcel_Writer_Excel2007_Chart', + 'relsvba' => 'PHPExcel_Writer_Excel2007_RelsVBA', + 'relsribbonobjects' => 'PHPExcel_Writer_Excel2007_RelsRibbon' ); // Initialise writer parts @@ -164,7 +155,8 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter } $hashTablesArray = array( '_stylesConditionalHashTable', '_fillHashTable', '_fontHashTable', - '_bordersHashTable', '_numFmtHashTable', '_drawingHashTable' + '_bordersHashTable', '_numFmtHashTable', '_drawingHashTable', + '_styleHashTable' ); // Set HashTable variables @@ -191,7 +183,7 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter * Save PHPExcel to file * * @param string $pFilename - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function save($pFilename = null) { @@ -208,8 +200,8 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter } } - $saveDebugLog = PHPExcel_Calculation::getInstance()->writeDebugLog; - PHPExcel_Calculation::getInstance()->writeDebugLog = false; + $saveDebugLog = PHPExcel_Calculation::getInstance($this->_spreadSheet)->getDebugLog()->getWriteDebugLog(); + PHPExcel_Calculation::getInstance($this->_spreadSheet)->getDebugLog()->setWriteDebugLog(FALSE); $saveDateReturnType = PHPExcel_Calculation_Functions::getReturnDateType(); PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_EXCEL); @@ -220,6 +212,7 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter } // Create styles dictionaries + $this->_styleHashTable->addFromSource( $this->getWriterPart('Style')->allStyles($this->_spreadSheet) ); $this->_stylesConditionalHashTable->addFromSource( $this->getWriterPart('Style')->allConditionalStyles($this->_spreadSheet) ); $this->_fillHashTable->addFromSource( $this->getWriterPart('Style')->allFills($this->_spreadSheet) ); $this->_fontHashTable->addFromSource( $this->getWriterPart('Style')->allFonts($this->_spreadSheet) ); @@ -245,13 +238,42 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter // Try opening the ZIP file if ($objZip->open($pFilename, $zipOverWrite) !== true) { if ($objZip->open($pFilename, $zipCreate) !== true) { - throw new Exception("Could not open " . $pFilename . " for writing."); + throw new PHPExcel_Writer_Exception("Could not open " . $pFilename . " for writing."); } } // Add [Content_Types].xml to ZIP file $objZip->addFromString('[Content_Types].xml', $this->getWriterPart('ContentTypes')->writeContentTypes($this->_spreadSheet, $this->_includeCharts)); + //if hasMacros, add the vbaProject.bin file, Certificate file(if exists) + if($this->_spreadSheet->hasMacros()){ + $macrosCode=$this->_spreadSheet->getMacrosCode(); + if(!is_null($macrosCode)){// we have the code ? + $objZip->addFromString('xl/vbaProject.bin', $macrosCode);//allways in 'xl', allways named vbaProject.bin + if($this->_spreadSheet->hasMacrosCertificate()){//signed macros ? + // Yes : add the certificate file and the related rels file + $objZip->addFromString('xl/vbaProjectSignature.bin', $this->_spreadSheet->getMacrosCertificate()); + $objZip->addFromString('xl/_rels/vbaProject.bin.rels', + $this->getWriterPart('RelsVBA')->writeVBARelationships($this->_spreadSheet)); + } + } + } + //a custom UI in this workbook ? add it ("base" xml and additional objects (pictures) and rels) + if($this->_spreadSheet->hasRibbon()){ + $tmpRibbonTarget=$this->_spreadSheet->getRibbonXMLData('target'); + $objZip->addFromString($tmpRibbonTarget, $this->_spreadSheet->getRibbonXMLData('data')); + if($this->_spreadSheet->hasRibbonBinObjects()){ + $tmpRootPath=dirname($tmpRibbonTarget).'/'; + $ribbonBinObjects=$this->_spreadSheet->getRibbonBinObjects('data');//the files to write + foreach($ribbonBinObjects as $aPath=>$aContent){ + $objZip->addFromString($tmpRootPath.$aPath, $aContent); + } + //the rels for files + $objZip->addFromString($tmpRootPath.'_rels/'.basename($tmpRibbonTarget).'.rels', + $this->getWriterPart('RelsRibbonObjects')->writeRibbonRelationships($this->_spreadSheet)); + } + } + // Add relationships to ZIP file $objZip->addFromString('_rels/.rels', $this->getWriterPart('Rels')->writeRelationships($this->_spreadSheet)); $objZip->addFromString('xl/_rels/workbook.xml.rels', $this->getWriterPart('Rels')->writeWorkbookRelationships($this->_spreadSheet)); @@ -342,7 +364,6 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter if ($this->getDrawingHashTable()->getByIndex($i) instanceof PHPExcel_Worksheet_Drawing) { $imageContents = null; $imagePath = $this->getDrawingHashTable()->getByIndex($i)->getPath(); - if (strpos($imagePath, 'zip://') !== false) { $imagePath = substr($imagePath, 6); $imagePathSplitted = explode('#', $imagePath); @@ -371,22 +392,22 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter } PHPExcel_Calculation_Functions::setReturnDateType($saveDateReturnType); - PHPExcel_Calculation::getInstance()->writeDebugLog = $saveDebugLog; + PHPExcel_Calculation::getInstance($this->_spreadSheet)->getDebugLog()->setWriteDebugLog($saveDebugLog); // Close file if ($objZip->close() === false) { - throw new Exception("Could not close zip file $pFilename."); + throw new PHPExcel_Writer_Exception("Could not close zip file $pFilename."); } // If a temporary file was used, copy it to the correct file stream if ($originalFilename != $pFilename) { if (copy($pFilename, $originalFilename) === false) { - throw new Exception("Could not copy temporary zip file $pFilename to $originalFilename."); + throw new PHPExcel_Writer_Exception("Could not copy temporary zip file $pFilename to $originalFilename."); } @unlink($pFilename); } } else { - throw new Exception("PHPExcel object unassigned."); + throw new PHPExcel_Writer_Exception("PHPExcel object unassigned."); } } @@ -394,13 +415,13 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter * Get PHPExcel object * * @return PHPExcel - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function getPHPExcel() { if ($this->_spreadSheet !== null) { return $this->_spreadSheet; } else { - throw new Exception("No PHPExcel assigned."); + throw new PHPExcel_Writer_Exception("No PHPExcel assigned."); } } @@ -408,7 +429,7 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter * Set PHPExcel object * * @param PHPExcel $pPHPExcel PHPExcel object - * @throws Exception + * @throws PHPExcel_Writer_Exception * @return PHPExcel_Writer_Excel2007 */ public function setPHPExcel(PHPExcel $pPHPExcel = null) { @@ -425,6 +446,15 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter return $this->_stringTable; } + /** + * Get PHPExcel_Style HashTable + * + * @return PHPExcel_HashTable + */ + public function getStyleHashTable() { + return $this->_styleHashTable; + } + /** * Get PHPExcel_Style_Conditional HashTable * @@ -479,49 +509,6 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter return $this->_drawingHashTable; } - /** - * Write charts in workbook? - * If this is true, then the Writer will write definitions for any charts that exist in the PHPExcel object. - * If false (the default) it will ignore any charts defined in the PHPExcel object. - * - * @return boolean - */ - public function getIncludeCharts() { - return $this->_includeCharts; - } - - /** - * Set write charts in workbook - * Set to true, to advise the Writer to include any charts that exist in the PHPExcel object. - * Set to false (the default) to ignore charts. - * - * @param boolean $pValue - * - * @return PHPExcel_Writer_Excel2007 - */ - public function setIncludeCharts($pValue = false) { - $this->_includeCharts = (boolean) $pValue; - return $this; - } - - /** - * Get Pre-Calculate Formulas - * - * @return boolean - */ - public function getPreCalculateFormulas() { - return $this->_preCalculateFormulas; - } - - /** - * Set Pre-Calculate Formulas - * - * @param boolean $pValue Pre-Calculate Formulas? - */ - public function setPreCalculateFormulas($pValue = true) { - $this->_preCalculateFormulas = $pValue; - } - /** * Get Office2003 compatibility * @@ -532,7 +519,7 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter } /** - * Set Pre-Calculate Formulas + * Set Office2003 compatibility * * @param boolean $pValue Office2003 compatibility? * @return PHPExcel_Writer_Excel2007 @@ -542,42 +529,4 @@ class PHPExcel_Writer_Excel2007 implements PHPExcel_Writer_IWriter return $this; } - /** - * Get use disk caching where possible? - * - * @return boolean - */ - public function getUseDiskCaching() { - return $this->_useDiskCaching; - } - - /** - * Set use disk caching where possible? - * - * @param boolean $pValue - * @param string $pDirectory Disk caching directory - * @throws Exception Exception when directory does not exist - * @return PHPExcel_Writer_Excel2007 - */ - public function setUseDiskCaching($pValue = false, $pDirectory = null) { - $this->_useDiskCaching = $pValue; - - if ($pDirectory !== NULL) { - if (is_dir($pDirectory)) { - $this->_diskCachingDirectory = $pDirectory; - } else { - throw new Exception("Directory does not exist: $pDirectory"); - } - } - return $this; - } - - /** - * Get disk caching directory - * - * @return string - */ - public function getDiskCachingDirectory() { - return $this->_diskCachingDirectory; - } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Chart.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Chart.php index d181d517b94..526daa92d94 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Chart.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Chart.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPart { @@ -40,7 +40,7 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel_Chart $pChart * @return string XML Output - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function writeChart(PHPExcel_Chart $pChart = null) { @@ -120,7 +120,7 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel_Chart_Title $title * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeTitle(PHPExcel_Chart_Title $title = null, $objWriter) { @@ -164,7 +164,7 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel_Chart_Legend $legend * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeLegend(PHPExcel_Chart_Legend $legend = null, $objWriter) { @@ -217,7 +217,7 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa * @param PHPExcel_Chart_Title $xAxisLabel * @param PHPExcel_Chart_Title $yAxisLabel * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writePlotArea(PHPExcel_Chart_PlotArea $plotArea, PHPExcel_Chart_Title $xAxisLabel = NULL, @@ -230,6 +230,7 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa } $id1 = $id2 = 0; + $this->_seriesIndex = 0; $objWriter->startElement('c:plotArea'); $layout = $plotArea->getLayout(); @@ -298,6 +299,20 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->startElement('c:hiLowLines'); $objWriter->endElement(); + + $objWriter->startElement( 'c:upDownBars' ); + + $objWriter->startElement( 'c:gapWidth' ); + $objWriter->writeAttribute('val', 300); + $objWriter->endElement(); + + $objWriter->startElement( 'c:upBars' ); + $objWriter->endElement(); + + $objWriter->startElement( 'c:downBars' ); + $objWriter->endElement(); + + $objWriter->endElement(); } // Generate 2 unique numbers to use for axId values @@ -355,7 +370,7 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Chart_Layout $chartLayout Chart layout - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeDataLbls($objWriter, $chartLayout) { @@ -410,7 +425,7 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa * @param string $id1 * @param string $id2 * @param boolean $isMultiLevelSeries - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeCatAx($objWriter, PHPExcel_Chart_PlotArea $plotArea, $xAxisLabel, $groupType, $id1, $id2, $isMultiLevelSeries) { @@ -463,13 +478,13 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->endElement(); $objWriter->endElement(); + $layout = $xAxisLabel->getLayout(); + $this->_writeLayout($layout, $objWriter); + $objWriter->startElement('c:overlay'); $objWriter->writeAttribute('val', 0); $objWriter->endElement(); - $layout = $xAxisLabel->getLayout(); - $this->_writeLayout($layout, $objWriter); - $objWriter->endElement(); } @@ -533,7 +548,7 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa * @param string $id1 * @param string $id2 * @param boolean $isMultiLevelSeries - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeValAx($objWriter, PHPExcel_Chart_PlotArea $plotArea, $yAxisLabel, $groupType, $id1, $id2, $isMultiLevelSeries) { @@ -589,15 +604,15 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->endElement(); $objWriter->endElement(); - $objWriter->startElement('c:overlay'); - $objWriter->writeAttribute('val', 0); - $objWriter->endElement(); - if ($groupType !== PHPExcel_Chart_DataSeries::TYPE_BUBBLECHART) { $layout = $yAxisLabel->getLayout(); $this->_writeLayout($layout, $objWriter); } + $objWriter->startElement('c:overlay'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + $objWriter->endElement(); } @@ -649,7 +664,7 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel_Chart_PlotArea $plotArea * @return string|array - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private static function _getChartType($plotArea) { @@ -664,7 +679,7 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa } $chartType = array_unique($chartTypes); if (count($chartTypes) == 0) { - throw new Exception('Chart is not yet implemented'); + throw new PHPExcel_Writer_Exception('Chart is not yet implemented'); } } @@ -681,7 +696,7 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa * @param boolean &$valIsMultiLevelSeries Is value set a multi-series set * @param string &$plotGroupingType Type of grouping for multi-series values * @param PHPExcel_Worksheet $pSheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writePlotGroup( $plotGroup, $groupType, @@ -737,11 +752,11 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->startElement('c:ser'); $objWriter->startElement('c:idx'); - $objWriter->writeAttribute('val', $plotSeriesIdx); + $objWriter->writeAttribute('val', $this->_seriesIndex + $plotSeriesIdx); $objWriter->endElement(); $objWriter->startElement('c:order'); - $objWriter->writeAttribute('val', $plotSeriesRef); + $objWriter->writeAttribute('val', $this->_seriesIndex + $plotSeriesRef); $objWriter->endElement(); if (($groupType == PHPExcel_Chart_DataSeries::TYPE_PIECHART) || @@ -778,10 +793,15 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa } // Formatting for the points - if ($groupType == PHPExcel_Chart_DataSeries::TYPE_LINECHART) { + if (($groupType == PHPExcel_Chart_DataSeries::TYPE_LINECHART) || + ($groupType == PHPExcel_Chart_DataSeries::TYPE_STOCKCHART)) { $objWriter->startElement('c:spPr'); $objWriter->startElement('a:ln'); $objWriter->writeAttribute('w', 12700); + if ($groupType == PHPExcel_Chart_DataSeries::TYPE_STOCKCHART) { + $objWriter->startElement('a:noFill'); + $objWriter->endElement(); + } $objWriter->endElement(); $objWriter->endElement(); } @@ -865,6 +885,8 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->endElement(); } + + $this->_seriesIndex += $plotSeriesIdx + 1; } /** @@ -872,7 +894,7 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel_Chart_DataSeriesValues $plotSeriesLabel * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writePlotSeriesLabel($plotSeriesLabel, $objWriter) { @@ -910,7 +932,7 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa * @param string $groupType Type of plot for dataseries * @param string $dataType Datatype of series values * @param PHPExcel_Worksheet $pSheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writePlotSeriesValues( $plotSeriesValues, $objWriter, @@ -1010,7 +1032,7 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel_Chart_DataSeriesValues $plotSeriesValues * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeBubbles($plotSeriesValues, $objWriter, PHPExcel_Worksheet $pSheet) { @@ -1056,7 +1078,7 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel_Chart_Layout $layout * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeLayout(PHPExcel_Chart_Layout $layout = NULL, $objWriter) { @@ -1124,7 +1146,7 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa * Write Alternate Content block * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeAlternateContent($objWriter) { @@ -1153,7 +1175,7 @@ class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPa * Write Printer Settings * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writePrintSettings($objWriter) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Comments.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Comments.php index ec8a2704258..436219c6e90 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Comments.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Comments.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Comments extends PHPExcel_Writer_Excel2007_WriterPart { @@ -40,7 +40,7 @@ class PHPExcel_Writer_Excel2007_Comments extends PHPExcel_Writer_Excel2007_Write * * @param PHPExcel_Worksheet $pWorksheet * @return string XML Output - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function writeComments(PHPExcel_Worksheet $pWorksheet = null) { @@ -98,7 +98,7 @@ class PHPExcel_Writer_Excel2007_Comments extends PHPExcel_Writer_Excel2007_Write * @param string $pCellReference Cell reference * @param PHPExcel_Comment $pComment Comment * @param array $pAuthors Array of authors - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function _writeComment(PHPExcel_Shared_XMLWriter $objWriter = null, $pCellReference = 'A1', PHPExcel_Comment $pComment = null, $pAuthors = null) { @@ -120,7 +120,7 @@ class PHPExcel_Writer_Excel2007_Comments extends PHPExcel_Writer_Excel2007_Write * * @param PHPExcel_Worksheet $pWorksheet * @return string XML Output - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function writeVMLComments(PHPExcel_Worksheet $pWorksheet = null) { @@ -193,7 +193,7 @@ class PHPExcel_Writer_Excel2007_Comments extends PHPExcel_Writer_Excel2007_Write * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param string $pCellReference Cell reference * @param PHPExcel_Comment $pComment Comment - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function _writeVMLComment(PHPExcel_Shared_XMLWriter $objWriter = null, $pCellReference = 'A1', PHPExcel_Comment $pComment = null) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/ContentTypes.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/ContentTypes.php index a6ee53c6d02..3c17a169271 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/ContentTypes.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/ContentTypes.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_ContentTypes extends PHPExcel_Writer_Excel2007_WriterPart { @@ -41,7 +41,7 @@ class PHPExcel_Writer_Excel2007_ContentTypes extends PHPExcel_Writer_Excel2007_W * @param PHPExcel $pPHPExcel * @param boolean $includeCharts Flag indicating if we should include drawing details for charts * @return string XML Output - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function writeContentTypes(PHPExcel $pPHPExcel = null, $includeCharts = FALSE) { @@ -86,9 +86,26 @@ class PHPExcel_Writer_Excel2007_ContentTypes extends PHPExcel_Writer_Excel2007_W ); // Workbook - $this->_writeOverrideContentType( - $objWriter, '/xl/workbook.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml' - ); + if($pPHPExcel->hasMacros()){ //Macros in workbook ? + // Yes : not standard content but "macroEnabled" + $this->_writeOverrideContentType( + $objWriter, '/xl/workbook.xml', 'application/vnd.ms-excel.sheet.macroEnabled.main+xml' + ); + //... and define a new type for the VBA project + $this->_writeDefaultContentType( + $objWriter, 'bin', 'application/vnd.ms-office.vbaProject' + ); + if($pPHPExcel->hasMacrosCertificate()){// signed macros ? + // Yes : add needed information + $this->_writeOverrideContentType( + $objWriter, '/xl/vbaProjectSignature.bin', 'application/vnd.ms-office.vbaProjectSignature' + ); + } + }else{// no macros in workbook, so standard type + $this->_writeOverrideContentType( + $objWriter, '/xl/workbook.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml' + ); + } // DocProps $this->_writeOverrideContentType( @@ -178,7 +195,16 @@ class PHPExcel_Writer_Excel2007_ContentTypes extends PHPExcel_Writer_Excel2007_W ); } } - + if($pPHPExcel->hasRibbonBinObjects()){//Some additional objects in the ribbon ? + //we need to write "Extension" but not already write for media content + $tabRibbonTypes=array_diff($pPHPExcel->getRibbonBinObjects('types'), array_keys($aMediaContentTypes)); + foreach($tabRibbonTypes as $aRibbonType){ + $mimeType='image/.'.$aRibbonType;//we wrote $mimeType like customUI Editor + $this->_writeDefaultContentType( + $objWriter, $aRibbonType, $mimeType + ); + } + } $sheetCount = $pPHPExcel->getSheetCount(); for ($i = 0; $i < $sheetCount; ++$i) { if (count($pPHPExcel->getSheet()->getHeaderFooter()->getImages()) > 0) { @@ -205,7 +231,7 @@ class PHPExcel_Writer_Excel2007_ContentTypes extends PHPExcel_Writer_Excel2007_W * * @param string $pFile Filename * @return string Mime Type - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _getImageMimeType($pFile = '') { @@ -213,7 +239,7 @@ class PHPExcel_Writer_Excel2007_ContentTypes extends PHPExcel_Writer_Excel2007_W $image = getimagesize($pFile); return image_type_to_mime_type($image[2]); } else { - throw new Exception("File $pFile does not exist"); + throw new PHPExcel_Writer_Exception("File $pFile does not exist"); } } @@ -223,7 +249,7 @@ class PHPExcel_Writer_Excel2007_ContentTypes extends PHPExcel_Writer_Excel2007_W * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param string $pPartname Part name * @param string $pContentType Content type - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeDefaultContentType(PHPExcel_Shared_XMLWriter $objWriter = null, $pPartname = '', $pContentType = '') { @@ -234,7 +260,7 @@ class PHPExcel_Writer_Excel2007_ContentTypes extends PHPExcel_Writer_Excel2007_W $objWriter->writeAttribute('ContentType', $pContentType); $objWriter->endElement(); } else { - throw new Exception("Invalid parameters passed."); + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); } } @@ -244,7 +270,7 @@ class PHPExcel_Writer_Excel2007_ContentTypes extends PHPExcel_Writer_Excel2007_W * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param string $pPartname Part name * @param string $pContentType Content type - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeOverrideContentType(PHPExcel_Shared_XMLWriter $objWriter = null, $pPartname = '', $pContentType = '') { @@ -255,7 +281,7 @@ class PHPExcel_Writer_Excel2007_ContentTypes extends PHPExcel_Writer_Excel2007_W $objWriter->writeAttribute('ContentType', $pContentType); $objWriter->endElement(); } else { - throw new Exception("Invalid parameters passed."); + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); } } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/DocProps.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/DocProps.php index 84dd06bc1f2..cfc308909f0 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/DocProps.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/DocProps.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_DocProps extends PHPExcel_Writer_Excel2007_WriterPart { @@ -40,7 +40,7 @@ class PHPExcel_Writer_Excel2007_DocProps extends PHPExcel_Writer_Excel2007_Write * * @param PHPExcel $pPHPExcel * @return string XML Output - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function writeDocPropsApp(PHPExcel $pPHPExcel = null) { @@ -137,7 +137,7 @@ class PHPExcel_Writer_Excel2007_DocProps extends PHPExcel_Writer_Excel2007_Write * * @param PHPExcel $pPHPExcel * @return string XML Output - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function writeDocPropsCore(PHPExcel $pPHPExcel = null) { @@ -204,7 +204,7 @@ class PHPExcel_Writer_Excel2007_DocProps extends PHPExcel_Writer_Excel2007_Write * * @param PHPExcel $pPHPExcel * @return string XML Output - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function writeDocPropsCustom(PHPExcel $pPHPExcel = null) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Drawing.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Drawing.php index 9b618c56301..3c52723a41c 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Drawing.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Drawing.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Drawing extends PHPExcel_Writer_Excel2007_WriterPart { @@ -42,7 +42,7 @@ class PHPExcel_Writer_Excel2007_Drawing extends PHPExcel_Writer_Excel2007_Writer * @param int &$chartRef Chart ID * @param boolean $includeCharts Flag indicating if we should include drawing details for charts * @return string XML Output - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function writeDrawings(PHPExcel_Worksheet $pWorksheet = null, &$chartRef, $includeCharts = FALSE) { @@ -95,7 +95,7 @@ class PHPExcel_Writer_Excel2007_Drawing extends PHPExcel_Writer_Excel2007_Writer * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Chart $pChart * @param int $pRelationId - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function _writeChart(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Chart $pChart = null, $pRelationId = -1) { @@ -167,7 +167,7 @@ class PHPExcel_Writer_Excel2007_Drawing extends PHPExcel_Writer_Excel2007_Writer * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet_BaseDrawing $pDrawing * @param int $pRelationId - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function _writeDrawing(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet_BaseDrawing $pDrawing = null, $pRelationId = -1) { @@ -375,7 +375,7 @@ class PHPExcel_Writer_Excel2007_Drawing extends PHPExcel_Writer_Excel2007_Writer $objWriter->endElement(); } else { - throw new Exception("Invalid parameters passed."); + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); } } @@ -384,7 +384,7 @@ class PHPExcel_Writer_Excel2007_Drawing extends PHPExcel_Writer_Excel2007_Writer * * @param PHPExcel_Worksheet $pWorksheet * @return string XML Output - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function writeVMLHeaderFooterImages(PHPExcel_Worksheet $pWorksheet = null) { @@ -532,7 +532,7 @@ class PHPExcel_Writer_Excel2007_Drawing extends PHPExcel_Writer_Excel2007_Writer * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param string $pReference Reference * @param PHPExcel_Worksheet_HeaderFooterDrawing $pImage Image - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function _writeVMLHeaderFooterImage(PHPExcel_Shared_XMLWriter $objWriter = null, $pReference = '', PHPExcel_Worksheet_HeaderFooterDrawing $pImage = null) { @@ -574,7 +574,7 @@ class PHPExcel_Writer_Excel2007_Drawing extends PHPExcel_Writer_Excel2007_Writer * * @param PHPExcel $pPHPExcel * @return PHPExcel_Worksheet_Drawing[] All drawings in PHPExcel - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function allDrawings(PHPExcel $pPHPExcel = null) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Rels.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Rels.php index ff550a673db..0bdb667c991 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Rels.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Rels.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPart { @@ -40,7 +40,7 @@ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPar * * @param PHPExcel $pPHPExcel * @return string XML Output - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function writeRelationships(PHPExcel $pPHPExcel = null) { @@ -94,6 +94,15 @@ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPar 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument', 'xl/workbook.xml' ); + // a custom UI in workbook ? + if($pPHPExcel->hasRibbon()){ + $this->_writeRelationShip( + $objWriter, + 5, + 'http://schemas.microsoft.com/office/2006/relationships/ui/extensibility', + $pPHPExcel->getRibbonXMLData('target') + ); + } $objWriter->endElement(); @@ -106,7 +115,7 @@ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPar * * @param PHPExcel $pPHPExcel * @return string XML Output - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function writeWorkbookRelationships(PHPExcel $pPHPExcel = null) { @@ -159,6 +168,17 @@ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPar 'worksheets/sheet' . ($i + 1) . '.xml' ); } + // Relationships for vbaProject if needed + // id : just after the last sheet + if($pPHPExcel->hasMacros()){ + $this->_writeRelationShip( + $objWriter, + ($i + 1 + 3), + 'http://schemas.microsoft.com/office/2006/relationships/vbaProject', + 'vbaProject.bin' + ); + ++$i;//increment i if needed for an another relation + } $objWriter->endElement(); @@ -177,7 +197,7 @@ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPar * @param int $pWorksheetId * @param boolean $includeCharts Flag indicating if we should write charts * @return string XML Output - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function writeWorksheetRelationships(PHPExcel_Worksheet $pWorksheet = null, $pWorksheetId = 1, $includeCharts = FALSE) { @@ -286,7 +306,7 @@ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPar * @param int &$chartRef Chart ID * @param boolean $includeCharts Flag indicating if we should write charts * @return string XML Output - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function writeDrawingRelationships(PHPExcel_Worksheet $pWorksheet = null, &$chartRef, $includeCharts = FALSE) { @@ -350,7 +370,7 @@ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPar * * @param PHPExcel_Worksheet $pWorksheet * @return string XML Output - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function writeHeaderFooterDrawingRelationships(PHPExcel_Worksheet $pWorksheet = null) { @@ -394,7 +414,7 @@ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPar * @param string $pType Relationship type * @param string $pTarget Relationship target * @param string $pTargetMode Relationship target mode - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeRelationship(PHPExcel_Shared_XMLWriter $objWriter = null, $pId = 1, $pType = '', $pTarget = '', $pTargetMode = '') { @@ -411,7 +431,7 @@ class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPar $objWriter->endElement(); } else { - throw new Exception("Invalid parameters passed."); + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); } } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/RelsRibbon.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/RelsRibbon.php new file mode 100644 index 00000000000..f924a1d43d1 --- /dev/null +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/RelsRibbon.php @@ -0,0 +1,77 @@ +getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // Relationships + $objWriter->startElement('Relationships'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); + $localRels=$pPHPExcel->getRibbonBinObjects('names'); + if(is_array($localRels)){ + foreach($localRels as $aId=>$aTarget){ + $objWriter->startElement('Relationship'); + $objWriter->writeAttribute('Id', $aId); + $objWriter->writeAttribute('Type', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image'); + $objWriter->writeAttribute('Target', $aTarget); + $objWriter->endElement();//Relationship + } + } + $objWriter->endElement();//Relationships + + // Return + return $objWriter->getData(); + + } + +} diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/RelsVBA.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/RelsVBA.php new file mode 100644 index 00000000000..aecb0b8da3b --- /dev/null +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/RelsVBA.php @@ -0,0 +1,72 @@ +getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // Relationships + $objWriter->startElement('Relationships'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); + $objWriter->startElement('Relationship'); + $objWriter->writeAttribute('Id', 'rId1'); + $objWriter->writeAttribute('Type', 'http://schemas.microsoft.com/office/2006/relationships/vbaProjectSignature'); + $objWriter->writeAttribute('Target', 'vbaProjectSignature.bin'); + $objWriter->endElement();//Relationship + $objWriter->endElement();//Relationships + + // Return + return $objWriter->getData(); + + } + +} diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/StringTable.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/StringTable.php index e9fb6600cd8..0e8a259b1b9 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/StringTable.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/StringTable.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_WriterPart { @@ -41,7 +41,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr * @param PHPExcel_Worksheet $pSheet Worksheet * @param string[] $pExistingTable Existing table to eventually merge with * @return string[] String table for worksheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function createStringTable($pSheet = null, $pExistingTable = null) { @@ -81,7 +81,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr // Return return $aStringTable; } else { - throw new Exception("Invalid PHPExcel_Worksheet object passed."); + throw new PHPExcel_Writer_Exception("Invalid PHPExcel_Worksheet object passed."); } } @@ -90,7 +90,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr * * @param string[] $pStringTable * @return string XML Output - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function writeStringTable($pStringTable = null) { @@ -135,7 +135,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr // Return return $objWriter->getData(); } else { - throw new Exception("Invalid string table array passed."); + throw new PHPExcel_Writer_Exception("Invalid string table array passed."); } } @@ -145,7 +145,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_RichText $pRichText Rich text * @param string $prefix Optional Namespace prefix - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function writeRichText(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_RichText $pRichText = null, $prefix=NULL) { @@ -227,7 +227,7 @@ class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_Wr * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param string|PHPExcel_RichText $pRichText text string or Rich text * @param string $prefix Optional Namespace prefix - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function writeRichTextForCharts(PHPExcel_Shared_XMLWriter $objWriter = null, $pRichText = null, $prefix=NULL) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Style.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Style.php index b24deba9a67..849ad127f58 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Style.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Style.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPart { @@ -40,7 +40,7 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel $pPHPExcel * @return string XML Output - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function writeStyles(PHPExcel $pPHPExcel = null) { @@ -170,7 +170,7 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Style_Fill $pFill Fill style - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeFill(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_Fill $pFill = null) { @@ -190,7 +190,7 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Style_Fill $pFill Fill style - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeGradientFill(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_Fill $pFill = null) { @@ -234,7 +234,7 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Style_Fill $pFill Fill style - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writePatternFill(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_Fill $pFill = null) { @@ -272,7 +272,7 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Style_Font $pFont Font style - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeFont(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_Font $pFont = null) { @@ -352,7 +352,7 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Style_Borders $pBorders Borders style - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeBorder(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_Borders $pBorders = null) { @@ -389,7 +389,7 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Style $pStyle Style * @param PHPExcel $pPHPExcel Workbook - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeCellStyleXf(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style $pStyle = null, PHPExcel $pPHPExcel = null) { @@ -397,6 +397,9 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa $objWriter->startElement('xf'); $objWriter->writeAttribute('xfId', 0); $objWriter->writeAttribute('fontId', (int)$this->getParentWriter()->getFontHashTable()->getIndexForHashCode($pStyle->getFont()->getHashCode())); + if ($pStyle->getQuotePrefix()) { + $objWriter->writeAttribute('quotePrefix', 1); + } if ($pStyle->getNumberFormat()->getBuiltInFormatCode() === false) { $objWriter->writeAttribute('numFmtId', (int)($this->getParentWriter()->getNumFmtHashTable()->getIndexForHashCode($pStyle->getNumberFormat()->getHashCode()) + 164) ); @@ -458,7 +461,7 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Style $pStyle Style - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeCellStyleDxf(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style $pStyle = null) { @@ -524,7 +527,7 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param string $pName Element name * @param PHPExcel_Style_Border $pBorder Border style - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeBorderPr(PHPExcel_Shared_XMLWriter $objWriter = null, $pName = 'left', PHPExcel_Style_Border $pBorder = null) { @@ -548,7 +551,7 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Style_NumberFormat $pNumberFormat Number Format * @param int $pId Number Format identifier - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeNumFmt(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_NumberFormat $pNumberFormat = null, $pId = 0) { @@ -569,7 +572,7 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel $pPHPExcel * @return PHPExcel_Style[] All styles in PHPExcel - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function allStyles(PHPExcel $pPHPExcel = null) { @@ -583,7 +586,7 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel $pPHPExcel * @return PHPExcel_Style_Conditional[] All conditional styles in PHPExcel - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function allConditionalStyles(PHPExcel $pPHPExcel = null) { @@ -607,7 +610,7 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel $pPHPExcel * @return PHPExcel_Style_Fill[] All fills in PHPExcel - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function allFills(PHPExcel $pPHPExcel = null) { @@ -638,7 +641,7 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel $pPHPExcel * @return PHPExcel_Style_Font[] All fonts in PHPExcel - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function allFonts(PHPExcel $pPHPExcel = null) { @@ -660,7 +663,7 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel $pPHPExcel * @return PHPExcel_Style_Borders[] All borders in PHPExcel - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function allBorders(PHPExcel $pPHPExcel = null) { @@ -682,7 +685,7 @@ class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel $pPHPExcel * @return PHPExcel_Style_NumberFormat[] All number formats in PHPExcel - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function allNumberFormats(PHPExcel $pPHPExcel = null) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Theme.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Theme.php index e067efe357e..064c3edcb7a 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Theme.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Theme.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,18 +20,18 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ /** - * PHPExcel_Writer_Excel2007_DocProps + * PHPExcel_Writer_Excel2007_Theme * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPart { @@ -134,7 +134,7 @@ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel $pPHPExcel * @return string XML Output - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function writeTheme(PHPExcel $pPHPExcel = null) { @@ -820,7 +820,7 @@ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPa * @param string $latinFont * @param array of string $fontSet * @return string XML Output - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeFonts($objWriter, $latinFont, $fontSet) { @@ -853,7 +853,7 @@ class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPa * * @param PHPExcel_Shared_XMLWriter $objWriter * @return string XML Output - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeColourScheme($objWriter) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Workbook.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Workbook.php index bbd2f927e9e..d1fe666e84f 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Workbook.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Workbook.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_WriterPart { @@ -41,7 +41,7 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write * @param PHPExcel $pPHPExcel * @param boolean $recalcRequired Indicate whether formulas should be recalculated before writing * @return string XML Output - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function writeWorkbook(PHPExcel $pPHPExcel = null, $recalcRequired = FALSE) { @@ -95,7 +95,7 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write * Write file version * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeFileVersion(PHPExcel_Shared_XMLWriter $objWriter = null) { @@ -111,7 +111,7 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write * Write WorkbookPr * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeWorkbookPr(PHPExcel_Shared_XMLWriter $objWriter = null) { @@ -131,7 +131,7 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel $pPHPExcel - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeBookViews(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel = null) { @@ -161,7 +161,7 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel $pPHPExcel - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeWorkbookProtection(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel = null) { @@ -188,16 +188,20 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param boolean $recalcRequired Indicate whether formulas should be recalculated before writing - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeCalcPr(PHPExcel_Shared_XMLWriter $objWriter = null, $recalcRequired = TRUE) { $objWriter->startElement('calcPr'); - $objWriter->writeAttribute('calcId', '124519'); + // Set the calcid to a higher value than Excel itself will use, otherwise Excel will always recalc + // If MS Excel does do a recalc, then users opening a file in MS Excel will be prompted to save on exit + // because the file has changed + $objWriter->writeAttribute('calcId', '999999'); $objWriter->writeAttribute('calcMode', 'auto'); // fullCalcOnLoad isn't needed if we've recalculating for the save - $objWriter->writeAttribute('fullCalcOnLoad', ($recalcRequired) ? '0' : '1'); + $objWriter->writeAttribute('calcCompleted', ($recalcRequired) ? 1 : 0); + $objWriter->writeAttribute('fullCalcOnLoad', ($recalcRequired) ? 0 : 1); $objWriter->endElement(); } @@ -207,7 +211,7 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel $pPHPExcel - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeSheets(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel = null) { @@ -236,7 +240,7 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write * @param int $pSheetId Sheet id * @param int $pRelId Relationship ID * @param string $sheetState Sheet state (visible, hidden, veryHidden) - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeSheet(PHPExcel_Shared_XMLWriter $objWriter = null, $pSheetname = '', $pSheetId = 1, $pRelId = 1, $sheetState = 'visible') { @@ -251,7 +255,7 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write $objWriter->writeAttribute('r:id', 'rId' . $pRelId); $objWriter->endElement(); } else { - throw new Exception("Invalid parameters passed."); + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); } } @@ -260,7 +264,7 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel $pPHPExcel - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeDefinedNames(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel = null) { @@ -294,7 +298,7 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel $pPHPExcel - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeNamedRanges(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel) { @@ -310,7 +314,7 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_NamedRange $pNamedRange - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeDefinedNameForNamedRange(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_NamedRange $pNamedRange) { @@ -342,7 +346,7 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet * @param int $pSheetId - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeDefinedNameForAutofilter(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pSheetId = 0) { @@ -378,7 +382,7 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet * @param int $pSheetId - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeDefinedNameForPrintTitles(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pSheetId = 0) { @@ -421,7 +425,7 @@ class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_Write * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet * @param int $pSheetId - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeDefinedNameForPrintArea(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pSheetId = 0) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Worksheet.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Worksheet.php index f720af338bf..7d93f5a4e00 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Worksheet.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/Worksheet.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_WriterPart { @@ -42,7 +42,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * @param string[] $pStringTable * @param boolean $includeCharts Flag indicating if we should write charts * @return string XML Output - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function writeWorksheet($pSheet = null, $pStringTable = null, $includeCharts = FALSE) { @@ -132,7 +132,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ // Return return $objWriter->getData(); } else { - throw new Exception("Invalid PHPExcel_Worksheet object passed."); + throw new PHPExcel_Writer_Exception("Invalid PHPExcel_Worksheet object passed."); } } @@ -141,13 +141,19 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeSheetPr(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { // sheetPr $objWriter->startElement('sheetPr'); //$objWriter->writeAttribute('codeName', $pSheet->getTitle()); + if($pSheet->getParent()->hasMacros()){//if the workbook have macros, we need to have codeName for the sheet + if($pSheet->hasCodeName()==false){ + $pSheet->setCodeName($pSheet->getTitle()); + } + $objWriter->writeAttribute('codeName', $pSheet->getCodeName()); + } $autoFilterRange = $pSheet->getAutoFilter()->getRange(); if (!empty($autoFilterRange)) { $objWriter->writeAttribute('filterMode', 1); @@ -182,7 +188,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeDimension(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { @@ -197,7 +203,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeSheetViews(PHPExcel_Shared_XMLWriter $objWriter = NULL, PHPExcel_Worksheet $pSheet = NULL) { @@ -304,7 +310,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeSheetFormatPr(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { @@ -356,7 +362,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeCols(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { @@ -421,7 +427,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeSheetProtection(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { @@ -456,7 +462,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeConditionalFormatting(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { @@ -531,7 +537,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeDataValidations(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { @@ -597,7 +603,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeHyperlinks(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { @@ -638,7 +644,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeProtectedRanges(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { @@ -652,7 +658,9 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $objWriter->startElement('protectedRange'); $objWriter->writeAttribute('name', 'p' . md5($protectedCell)); $objWriter->writeAttribute('sqref', $protectedCell); - $objWriter->writeAttribute('password', $passwordHash); + if (!empty($passwordHash)) { + $objWriter->writeAttribute('password', $passwordHash); + } $objWriter->endElement(); } @@ -665,7 +673,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeMergeCells(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { @@ -690,7 +698,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writePrintOptions(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { @@ -716,7 +724,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writePageMargins(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { @@ -736,7 +744,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeAutoFilter(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { @@ -828,7 +836,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writePageSetup(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { @@ -863,7 +871,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeHeaderFooter(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { @@ -888,7 +896,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeBreaks(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { @@ -946,7 +954,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet Worksheet * @param string[] $pStringTable String table - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeSheetData(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pStringTable = null) { @@ -1031,7 +1039,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $objWriter->endElement(); } else { - throw new Exception("Invalid parameters passed."); + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); } } @@ -1043,7 +1051,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * @param PHPExcel_Cell $pCellAddress Cell Address * @param string[] $pStringTable String table * @param string[] $pFlippedStringTable String table (flipped), for faster index searching - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeCell(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pCellAddress = null, $pStringTable = null, $pFlippedStringTable = null) { @@ -1072,12 +1080,9 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $objWriter->writeAttribute('t', $mappedType); break; case 'f': // Formula - $calculatedValue = null; - if ($this->getParentWriter()->getPreCalculateFormulas()) { - $calculatedValue = $pCell->getCalculatedValue(); - } else { - $calculatedValue = $cellValue; - } + $calculatedValue = ($this->getParentWriter()->getPreCalculateFormulas()) ? + $pCell->getCalculatedValue() : + $cellValue; if (is_string($calculatedValue)) { $objWriter->writeAttribute('t', 'str'); } @@ -1123,7 +1128,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ } if ($this->getParentWriter()->getOffice2003Compatibility() === false) { if ($this->getParentWriter()->getPreCalculateFormulas()) { - $calculatedValue = $pCell->getCalculatedValue(); +// $calculatedValue = $pCell->getCalculatedValue(); if (!is_array($calculatedValue) && substr($calculatedValue, 0, 1) != '#') { $objWriter->writeElement('v', PHPExcel_Shared_String::FormatNumber($calculatedValue)); } else { @@ -1155,7 +1160,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ $objWriter->endElement(); } else { - throw new Exception("Invalid parameters passed."); + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); } } @@ -1165,7 +1170,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet Worksheet * @param boolean $includeCharts Flag indicating if we should include drawing details for charts - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeDrawings(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $includeCharts = FALSE) { @@ -1184,7 +1189,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeLegacyDrawing(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { @@ -1201,7 +1206,7 @@ class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_Writ * * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer * @param PHPExcel_Worksheet $pSheet Worksheet - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _writeLegacyDrawingHF(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/WriterPart.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/WriterPart.php index 3f5069182e2..982117bcf6f 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/WriterPart.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel2007/WriterPart.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel2007 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ abstract class PHPExcel_Writer_Excel2007_WriterPart { @@ -46,7 +46,7 @@ abstract class PHPExcel_Writer_Excel2007_WriterPart * Set parent IWriter object * * @param PHPExcel_Writer_IWriter $pWriter - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function setParentWriter(PHPExcel_Writer_IWriter $pWriter = null) { $this->_parentWriter = $pWriter; @@ -56,13 +56,13 @@ abstract class PHPExcel_Writer_Excel2007_WriterPart * Get parent IWriter object * * @return PHPExcel_Writer_IWriter - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function getParentWriter() { if (!is_null($this->_parentWriter)) { return $this->_parentWriter; } else { - throw new Exception("No parent PHPExcel_Writer_IWriter assigned."); + throw new PHPExcel_Writer_Exception("No parent PHPExcel_Writer_IWriter assigned."); } } @@ -70,7 +70,7 @@ abstract class PHPExcel_Writer_Excel2007_WriterPart * Set parent IWriter object * * @param PHPExcel_Writer_IWriter $pWriter - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function __construct(PHPExcel_Writer_IWriter $pWriter = null) { if (!is_null($pWriter)) { diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5.php index 9297c78baed..3f816fa1f87 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,17 +31,10 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter +class PHPExcel_Writer_Excel5 extends PHPExcel_Writer_Abstract implements PHPExcel_Writer_IWriter { - /** - * Pre-calculate formulas - * - * @var boolean - */ - private $_preCalculateFormulas = true; - /** * PHPExcel object * @@ -120,15 +113,15 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter * Save PHPExcel to file * * @param string $pFilename - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function save($pFilename = null) { // garbage collect $this->_phpExcel->garbageCollect(); - $saveDebugLog = PHPExcel_Calculation::getInstance()->writeDebugLog; - PHPExcel_Calculation::getInstance()->writeDebugLog = false; + $saveDebugLog = PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->getWriteDebugLog(); + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog(FALSE); $saveDateReturnType = PHPExcel_Calculation_Functions::getReturnDateType(); PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_EXCEL); @@ -196,7 +189,7 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter } // add binary data for global workbook stream - $OLE->append( $this->_writerWorkbook->writeWorkbook($worksheetSizes) ); + $OLE->append($this->_writerWorkbook->writeWorkbook($worksheetSizes)); // add binary data for sheet streams for ($i = 0; $i < $countSheets; ++$i) { @@ -233,7 +226,7 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter $res = $root->save($pFilename); PHPExcel_Calculation_Functions::setReturnDateType($saveDateReturnType); - PHPExcel_Calculation::getInstance()->writeDebugLog = $saveDebugLog; + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog($saveDebugLog); } /** @@ -241,31 +234,13 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter * * @deprecated * @param string $pValue Temporary storage directory - * @throws Exception Exception when directory does not exist + * @throws PHPExcel_Writer_Exception when directory does not exist * @return PHPExcel_Writer_Excel5 */ public function setTempDir($pValue = '') { return $this; } - /** - * Get Pre-Calculate Formulas - * - * @return boolean - */ - public function getPreCalculateFormulas() { - return $this->_preCalculateFormulas; - } - - /** - * Set Pre-Calculate Formulas - * - * @param boolean $pValue Pre-Calculate Formulas? - */ - public function setPreCalculateFormulas($pValue = true) { - $this->_preCalculateFormulas = $pValue; - } - /** * Build the Worksheet Escher objects * @@ -621,7 +596,6 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter // GKPIDDSI_CATEGORY : Category if($this->_phpExcel->getProperties()->getCategory()){ $dataProp = $this->_phpExcel->getProperties()->getCategory(); - $dataProp = 'Test result file'; $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x02), 'offset' => array('pack' => 'V'), 'type' => array('pack' => 'V', 'data' => 0x1E), @@ -958,4 +932,4 @@ class PHPExcel_Writer_Excel5 implements PHPExcel_Writer_IWriter return $data; } -} \ No newline at end of file +} diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/BIFFwriter.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/BIFFwriter.php index b6782255047..b3e48bc33d5 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/BIFFwriter.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/BIFFwriter.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ // Original file header of PEAR::Spreadsheet_Excel_Writer_BIFFwriter (used as the base for this class): @@ -65,7 +65,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5_BIFFwriter { @@ -122,7 +122,7 @@ class PHPExcel_Writer_Excel5_BIFFwriter $byte_order = 1; // Big Endian } else { // Give up. I'll fix this in a later version. - throw new Exception("Required floating point format not supported on this platform."); + throw new PHPExcel_Writer_Exception("Required floating point format not supported on this platform."); } self::$_byte_order = $byte_order; } diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Escher.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Escher.php index 94b769ab92b..7e9b73a3d1b 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Escher.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Escher.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5_Escher { diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Font.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Font.php index f67dd11f048..f2dbab2015b 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Font.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Font.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -31,7 +31,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5_Font { diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Parser.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Parser.php index 88b777e0032..04e674a21a2 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Parser.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Parser.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ // Original file header of PEAR::Spreadsheet_Excel_Writer_Parser (used as the base for this class): @@ -55,7 +55,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5_Parser { @@ -564,7 +564,7 @@ class PHPExcel_Writer_Excel5_Parser } // TODO: use real error codes - throw new Exception("Unknown token $token"); + throw new PHPExcel_Writer_Exception("Unknown token $token"); } /** @@ -598,7 +598,7 @@ class PHPExcel_Writer_Excel5_Parser // chop away beggining and ending quotes $string = substr($string, 1, strlen($string) - 2); if (strlen($string) > 255) { - throw new Exception("String is too long"); + throw new PHPExcel_Writer_Exception("String is too long"); } return pack('C', $this->ptg['ptgStr']) . PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($string); @@ -644,7 +644,7 @@ class PHPExcel_Writer_Excel5_Parser list($cell1, $cell2) = explode(':', $range); } else { // TODO: use real error codes - throw new Exception("Unknown range separator"); + throw new PHPExcel_Writer_Exception("Unknown range separator"); } // Convert the cell references @@ -660,7 +660,7 @@ class PHPExcel_Writer_Excel5_Parser $ptgArea = pack("C", $this->ptg['ptgAreaA']); } else { // TODO: use real error codes - throw new Exception("Unknown class $class"); + throw new PHPExcel_Writer_Exception("Unknown class $class"); } return $ptgArea . $row1 . $row2 . $col1. $col2; } @@ -702,7 +702,7 @@ class PHPExcel_Writer_Excel5_Parser // } elseif ($class == 2) { // $ptgArea = pack("C", $this->ptg['ptgArea3dA']); // } else { -// throw new Exception("Unknown class $class"); +// throw new PHPExcel_Writer_Exception("Unknown class $class"); // } return $ptgArea . $ext_ref . $row1 . $row2 . $col1. $col2; @@ -732,7 +732,7 @@ class PHPExcel_Writer_Excel5_Parser $ptgRef = pack("C", $this->ptg['ptgRefA']); // } else { // // TODO: use real error codes -// throw new Exception("Unknown class $class"); +// throw new PHPExcel_Writer_Exception("Unknown class $class"); // } return $ptgRef.$row.$col; } @@ -766,7 +766,7 @@ class PHPExcel_Writer_Excel5_Parser // } elseif ($class == 2) { $ptgRef = pack("C", $this->ptg['ptgRef3dA']); // } else { -// throw new Exception("Unknown class $class"); +// throw new PHPExcel_Writer_Exception("Unknown class $class"); // } return $ptgRef . $ext_ref. $row . $col; @@ -812,11 +812,11 @@ class PHPExcel_Writer_Excel5_Parser $sheet1 = $this->_getSheetIndex($sheet_name1); if ($sheet1 == -1) { - throw new Exception("Unknown sheet name $sheet_name1 in formula"); + throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name1 in formula"); } $sheet2 = $this->_getSheetIndex($sheet_name2); if ($sheet2 == -1) { - throw new Exception("Unknown sheet name $sheet_name2 in formula"); + throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name2 in formula"); } // Reverse max and min sheet numbers if necessary @@ -826,7 +826,7 @@ class PHPExcel_Writer_Excel5_Parser } else { // Single sheet name only. $sheet1 = $this->_getSheetIndex($ext_ref); if ($sheet1 == -1) { - throw new Exception("Unknown sheet name $ext_ref in formula"); + throw new PHPExcel_Writer_Exception("Unknown sheet name $ext_ref in formula"); } $sheet2 = $sheet1; } @@ -858,11 +858,11 @@ class PHPExcel_Writer_Excel5_Parser $sheet1 = $this->_getSheetIndex($sheet_name1); if ($sheet1 == -1) { - throw new Exception("Unknown sheet name $sheet_name1 in formula"); + throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name1 in formula"); } $sheet2 = $this->_getSheetIndex($sheet_name2); if ($sheet2 == -1) { - throw new Exception("Unknown sheet name $sheet_name2 in formula"); + throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name2 in formula"); } // Reverse max and min sheet numbers if necessary @@ -872,7 +872,7 @@ class PHPExcel_Writer_Excel5_Parser } else { // Single sheet name only. $sheet1 = $this->_getSheetIndex($ext_ref); if ($sheet1 == -1) { - throw new Exception("Unknown sheet name $ext_ref in formula"); + throw new PHPExcel_Writer_Exception("Unknown sheet name $ext_ref in formula"); } $sheet2 = $sheet1; } @@ -942,11 +942,10 @@ class PHPExcel_Writer_Excel5_Parser $cell = strtoupper($cell); list($row, $col, $row_rel, $col_rel) = $this->_cellToRowcol($cell); if ($col >= 256) { - throw new Exception("Column in: $cell greater than 255"); + throw new PHPExcel_Writer_Exception("Column in: $cell greater than 255"); } - // FIXME: change for BIFF8 - if ($row >= 16384) { - throw new Exception("Row in: $cell greater than 16384 "); + if ($row >= 65536) { + throw new PHPExcel_Writer_Exception("Row in: $cell greater than 65536 "); } // Set the high bits to indicate if row or col are relative. @@ -980,11 +979,11 @@ class PHPExcel_Writer_Excel5_Parser --$row2; // Trick poor inocent Excel $col1 = 0; - $col2 = 16383; // FIXME: maximum possible value for Excel 5 (change this!!!) + $col2 = 65535; // FIXME: maximum possible value for Excel 5 (change this!!!) // FIXME: this changes for BIFF8 - if (($row1 >= 16384) or ($row2 >= 16384)) { - throw new Exception("Row in: $range greater than 16384 "); + if (($row1 >= 65536) or ($row2 >= 65536)) { + throw new PHPExcel_Writer_Exception("Row in: $range greater than 65536 "); } // Set the high bits to indicate if rows are relative. @@ -1373,7 +1372,7 @@ class PHPExcel_Writer_Excel5_Parser $this->_advance(); // eat the "(" $result = $this->_parenthesizedExpression(); if ($this->_current_token != ")") { - throw new Exception("')' token expected."); + throw new PHPExcel_Writer_Exception("')' token expected."); } $this->_advance(); // eat the ")" return $result; @@ -1443,7 +1442,7 @@ class PHPExcel_Writer_Excel5_Parser $result = $this->_func(); return $result; } - throw new Exception("Syntax error: ".$this->_current_token. + throw new PHPExcel_Writer_Exception("Syntax error: ".$this->_current_token. ", lookahead: ".$this->_lookahead. ", current char: ".$this->_current_char); } @@ -1470,7 +1469,7 @@ class PHPExcel_Writer_Excel5_Parser { $this->_advance(); // eat the "," or ";" } else { - throw new Exception("Syntax error: comma expected in ". + throw new PHPExcel_Writer_Exception("Syntax error: comma expected in ". "function $function, arg #{$num_args}"); } $result2 = $this->_condition(); @@ -1482,12 +1481,12 @@ class PHPExcel_Writer_Excel5_Parser ++$num_args; } if (!isset($this->_functions[$function])) { - throw new Exception("Function $function() doesn't exist"); + throw new PHPExcel_Writer_Exception("Function $function() doesn't exist"); } $args = $this->_functions[$function][1]; // If fixed number of args eg. TIME($i,$j,$k). Check that the number of args is valid. if (($args >= 0) and ($args != $num_args)) { - throw new Exception("Incorrect number of arguments in function $function() "); + throw new PHPExcel_Writer_Exception("Incorrect number of arguments in function $function() "); } $result = $this->_createTree($function, $result, $num_args); diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Workbook.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Workbook.php index 2e177ceff90..e14bcba4d37 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Workbook.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Workbook.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ // Original file header of PEAR::Spreadsheet_Excel_Writer_Workbook (used as the base for this class): @@ -66,7 +66,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter { @@ -317,6 +317,7 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter } return $fontIndex; } + /** * Alter color palette adding a custom color * @@ -629,7 +630,7 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter $rowmax = $repeat[1] - 1; } else { $rowmin = 0; - $rowmax = 16383; + $rowmax = 65535; } $this->_writeNameShort( @@ -687,7 +688,7 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter } $chunk .= $this->writeData($this->_writeDefinedNameBiff8($namedRange->getName(), $formulaData, $scope, false)); - } catch(Exception $e) { + } catch(PHPExcel_Exception $e) { // do nothing } } @@ -835,10 +836,10 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter /** * Write a short NAME record * - * @param string $name - * @param string $sheetIndex 1-based sheet index the defined name applies to. 0 = global - * @param int[][] $range rangeboundaries - * @param bool $isHidden + * @param string $name + * @param string $sheetIndex 1-based sheet index the defined name applies to. 0 = global + * @param integer[][] $rangeBounds range boundaries + * @param boolean $isHidden * @return string Complete binary record data * */ private function _writeShortNameBiff8($name, $sheetIndex = 0, $rangeBounds, $isHidden = false){ @@ -1446,5 +1447,4 @@ class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter { $this->_escher = $pValue; } - } diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Worksheet.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Worksheet.php index 9aa5083d915..55da26f3282 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Worksheet.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Worksheet.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ // Original file header of PEAR::Spreadsheet_Excel_Writer_Worksheet (used as the base for this class): @@ -66,7 +66,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter { @@ -424,7 +424,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter if ($cVal instanceof PHPExcel_RichText) { // $this->_writeString($row, $column, $cVal->getPlainText(), $xfIndex); $arrcRun = array(); - $str_len = strlen($cVal->getPlainText()); + $str_len = PHPExcel_Shared_String::CountCharacters($cVal->getPlainText(), 'UTF-8'); $str_pos = 0; $elements = $cVal->getRichTextElements(); foreach ($elements as $element) { @@ -437,7 +437,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter } $arrcRun[] = array('strlen' => $str_pos, 'fontidx' => $str_fontidx); // Position FROM - $str_pos += strlen($element->getText()); + $str_pos += PHPExcel_Shared_String::CountCharacters($element->getText(), 'UTF-8'); } $this->_writeRichTextString($row, $column, $cVal->getPlainText(), $xfIndex, $arrcRun); } else { @@ -476,12 +476,22 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter // Append $this->_writeMsoDrawing(); + // Write WINDOW2 record $this->_writeWindow2(); + + // Write PLV record + $this->_writePageLayoutView(); + + // Write ZOOM record $this->_writeZoom(); if ($_phpSheet->getFreezePane()) { $this->_writePanes(); } + + // Write SELECTION record $this->_writeSelection(); + + // Write MergedCellsTable Record $this->_writeMergedCells(); // Hyperlinks @@ -508,9 +518,32 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $this->_writeDataValidity(); $this->_writeSheetLayout(); + + // Write SHEETPROTECTION record $this->_writeSheetProtection(); $this->_writeRangeProtection(); + $arrConditionalStyles = $_phpSheet->getConditionalStylesCollection(); + if(!empty($arrConditionalStyles)){ + $arrConditional = array(); + // @todo CFRule & CFHeader + // Write CFHEADER record + $this->_writeCFHeader(); + // Write ConditionalFormattingTable records + foreach ($arrConditionalStyles as $cellCoordinate => $conditionalStyles) { + foreach ($conditionalStyles as $conditional) { + if($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_EXPRESSION + || $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS){ + if(!in_array($conditional->getHashCode(), $arrConditional)){ + $arrConditional[] = $conditional->getHashCode(); + // Write CFRULE record + $this->_writeCFRule($conditional); + } + } + } + } + } + $this->_storeEof(); } @@ -642,6 +675,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter { $this->_writeLabelSst($row, $col, $str, $xfIndex); } + /** * Write a LABELSST record or a LABEL record. Which one depends on BIFF version * It differs from _writeString by the writing of rich text strings. @@ -654,7 +688,6 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter private function _writeRichTextString($row, $col, $str, $xfIndex, $arrcRun){ $record = 0x00FD; // Record identifier $length = 0x000A; // Bytes to follow - $str = PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($str, $arrcRun); /* check if string is already present */ @@ -901,7 +934,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter return 0; - } catch (Exception $e) { + } catch (PHPExcel_Exception $e) { // do nothing } @@ -1276,26 +1309,29 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter // no support in PHPExcel for selected sheet, therefore sheet is only selected if it is the active sheet $fSelected = ($this->_phpSheet === $this->_phpSheet->getParent()->getActiveSheet()) ? 1 : 0; $fPaged = 1; // 2 + $fPageBreakPreview = $this->_phpSheet->getSheetView()->getView() === PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_BREAK_PREVIEW; $grbit = $fDspFmla; $grbit |= $fDspGrid << 1; - $grbit |= $fDspRwCol << 2; - $grbit |= $fFrozen << 3; - $grbit |= $fDspZeros << 4; - $grbit |= $fDefaultHdr << 5; - $grbit |= $fArabic << 6; + $grbit |= $fDspRwCol << 2; + $grbit |= $fFrozen << 3; + $grbit |= $fDspZeros << 4; + $grbit |= $fDefaultHdr << 5; + $grbit |= $fArabic << 6; $grbit |= $fDspGuts << 7; $grbit |= $fFrozenNoSplit << 8; - $grbit |= $fSelected << 9; - $grbit |= $fPaged << 10; + $grbit |= $fSelected << 9; + $grbit |= $fPaged << 10; + $grbit |= $fPageBreakPreview << 11; $header = pack("vv", $record, $length); $data = pack("vvv", $grbit, $rwTop, $colLeft); // FIXME !!! $rgbHdr = 0x0040; // Row/column heading and gridline color index - $zoom_factor_page_break = 0x0000; - $zoom_factor_normal = 0x0000; + $zoom_factor_page_break = ($fPageBreakPreview? $this->_phpSheet->getSheetView()->getZoomScale() : 0x0000); + $zoom_factor_normal = $this->_phpSheet->getSheetView()->getZoomScaleNormal(); + $data .= pack("vvvvV", $rgbHdr, 0x0000, $zoom_factor_page_break, $zoom_factor_normal, 0x00000000); $this->_append($header.$data); @@ -2238,10 +2274,10 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $record = 0x0012; // Record identifier $length = 0x0002; // Bytes to follow - $fLock = 1; // Worksheet is protected + $fLock = 1; // Worksheet is protected $header = pack("vv", $record, $length); - $data = pack("v", $fLock); + $data = pack("v", $fLock); $this->_append($header.$data); } @@ -2579,7 +2615,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter // Open file. $bmp_fd = @fopen($bitmap,"rb"); if (!$bmp_fd) { - throw new Exception("Couldn't import $bitmap"); + throw new PHPExcel_Writer_Exception("Couldn't import $bitmap"); } // Slurp the file into a string. @@ -2587,13 +2623,13 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter // Check that the file is big enough to be a bitmap. if (strlen($data) <= 0x36) { - throw new Exception("$bitmap doesn't contain enough data.\n"); + throw new PHPExcel_Writer_Exception("$bitmap doesn't contain enough data.\n"); } // The first 2 bytes are used to identify the bitmap. $identity = unpack("A2ident", $data); if ($identity['ident'] != "BM") { - throw new Exception("$bitmap doesn't appear to be a valid bitmap image.\n"); + throw new PHPExcel_Writer_Exception("$bitmap doesn't appear to be a valid bitmap image.\n"); } // Remove bitmap data: ID. @@ -2617,20 +2653,20 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $height = $width_and_height[2]; $data = substr($data, 8); if ($width > 0xFFFF) { - throw new Exception("$bitmap: largest image width supported is 65k.\n"); + throw new PHPExcel_Writer_Exception("$bitmap: largest image width supported is 65k.\n"); } if ($height > 0xFFFF) { - throw new Exception("$bitmap: largest image height supported is 65k.\n"); + throw new PHPExcel_Writer_Exception("$bitmap: largest image height supported is 65k.\n"); } // Read and remove the bitmap planes and bpp data. Verify them. $planes_and_bitcount = unpack("v2", substr($data, 0, 4)); $data = substr($data, 4); if ($planes_and_bitcount[2] != 24) { // Bitcount - throw new Exception("$bitmap isn't a 24bit true color bitmap.\n"); + throw new PHPExcel_Writer_Exception("$bitmap isn't a 24bit true color bitmap.\n"); } if ($planes_and_bitcount[1] != 1) { - throw new Exception("$bitmap: only 1 plane supported in bitmap image.\n"); + throw new PHPExcel_Writer_Exception("$bitmap: only 1 plane supported in bitmap image.\n"); } // Read and remove the bitmap compression. Verify compression. @@ -2639,7 +2675,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter //$compression = 0; if ($compression['comp'] != 0) { - throw new Exception("$bitmap: compression not supported in bitmap image.\n"); + throw new PHPExcel_Writer_Exception("$bitmap: compression not supported in bitmap image.\n"); } // Remove bitmap data: data size, hres, vres, colours, imp. colours. @@ -2895,7 +2931,7 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter $formula1 = $this->_parser->toReversePolish(); $sz1 = strlen($formula1); - } catch(Exception $e) { + } catch(PHPExcel_Exception $e) { $sz1 = 0; $formula1 = ''; } @@ -2906,13 +2942,13 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter try { $formula2 = $dataValidation->getFormula2(); if ($formula2 === '') { - throw new Exception('No formula2'); + throw new PHPExcel_Writer_Exception('No formula2'); } $this->_parser->parse($formula2); $formula2 = $this->_parser->toReversePolish(); $sz2 = strlen($formula2); - } catch(Exception $e) { + } catch(PHPExcel_Exception $e) { $sz2 = 0; $formula2 = ''; } @@ -2951,4 +2987,695 @@ class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter return 0; } + /** + * Write PLV Record + */ + private function _writePageLayoutView(){ + $record = 0x088B; // Record identifier + $length = 0x0010; // Bytes to follow + + $rt = 0x088B; // 2 + $grbitFrt = 0x0000; // 2 + $reserved = 0x0000000000000000; // 8 + $wScalvePLV = $this->_phpSheet->getSheetView()->getZoomScale(); // 2 + + // The options flags that comprise $grbit + if($this->_phpSheet->getSheetView()->getView() == PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_LAYOUT){ + $fPageLayoutView = 1; + } else { + $fPageLayoutView = 0; + } + $fRulerVisible = 0; + $fWhitespaceHidden = 0; + + $grbit = $fPageLayoutView; // 2 + $grbit |= $fRulerVisible << 1; + $grbit |= $fWhitespaceHidden << 3; + + $header = pack("vv", $record, $length); + $data = pack("vvVVvv", $rt, $grbitFrt, 0x00000000, 0x00000000, $wScalvePLV, $grbit); + $this->_append($header . $data); + } + + /** + * Write CFRule Record + * @param PHPExcel_Style_Conditional $conditional + */ + private function _writeCFRule(PHPExcel_Style_Conditional $conditional){ + $record = 0x01B1; // Record identifier + + // $type : Type of the CF + // $operatorType : Comparison operator + if($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_EXPRESSION){ + $type = 0x02; + $operatorType = 0x00; + } else if($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS){ + $type = 0x01; + + switch ($conditional->getOperatorType()){ + case PHPExcel_Style_Conditional::OPERATOR_NONE: + $operatorType = 0x00; + break; + case PHPExcel_Style_Conditional::OPERATOR_EQUAL: + $operatorType = 0x03; + break; + case PHPExcel_Style_Conditional::OPERATOR_GREATERTHAN: + $operatorType = 0x05; + break; + case PHPExcel_Style_Conditional::OPERATOR_GREATERTHANOREQUAL: + $operatorType = 0x07; + break; + case PHPExcel_Style_Conditional::OPERATOR_LESSTHAN: + $operatorType = 0x06; + break; + case PHPExcel_Style_Conditional::OPERATOR_LESSTHANOREQUAL: + $operatorType = 0x08; + break; + case PHPExcel_Style_Conditional::OPERATOR_NOTEQUAL: + $operatorType = 0x04; + break; + case PHPExcel_Style_Conditional::OPERATOR_BETWEEN: + $operatorType = 0x01; + break; + // not OPERATOR_NOTBETWEEN 0x02 + } + } + + // $szValue1 : size of the formula data for first value or formula + // $szValue2 : size of the formula data for second value or formula + $arrConditions = $conditional->getConditions(); + $numConditions = sizeof($arrConditions); + if($numConditions == 1){ + $szValue1 = ($arrConditions[0] <= 65535 ? 3 : 0x0000); + $szValue2 = 0x0000; + $operand1 = pack('Cv', 0x1E, $arrConditions[0]); + $operand2 = null; + } else if($numConditions == 2 && ($conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_BETWEEN)){ + $szValue1 = ($arrConditions[0] <= 65535 ? 3 : 0x0000); + $szValue2 = ($arrConditions[1] <= 65535 ? 3 : 0x0000); + $operand1 = pack('Cv', 0x1E, $arrConditions[0]); + $operand2 = pack('Cv', 0x1E, $arrConditions[1]); + } else { + $szValue1 = 0x0000; + $szValue2 = 0x0000; + $operand1 = null; + $operand2 = null; + } + + // $flags : Option flags + // Alignment + $bAlignHz = ($conditional->getStyle()->getAlignment()->getHorizontal() == null ? 1 : 0); + $bAlignVt = ($conditional->getStyle()->getAlignment()->getVertical() == null ? 1 : 0); + $bAlignWrapTx = ($conditional->getStyle()->getAlignment()->getWrapText() == false ? 1 : 0); + $bTxRotation = ($conditional->getStyle()->getAlignment()->getTextRotation() == null ? 1 : 0); + $bIndent = ($conditional->getStyle()->getAlignment()->getIndent() == 0 ? 1 : 0); + $bShrinkToFit = ($conditional->getStyle()->getAlignment()->getShrinkToFit() == false ? 1 : 0); + if($bAlignHz == 0 || $bAlignVt == 0 || $bAlignWrapTx == 0 || $bTxRotation == 0 || $bIndent == 0 || $bShrinkToFit == 0){ + $bFormatAlign = 1; + } else { + $bFormatAlign = 0; + } + // Protection + $bProtLocked = ($conditional->getStyle()->getProtection()->getLocked() == null ? 1 : 0); + $bProtHidden = ($conditional->getStyle()->getProtection()->getHidden() == null ? 1 : 0); + if($bProtLocked == 0 || $bProtHidden == 0){ + $bFormatProt = 1; + } else { + $bFormatProt = 0; + } + // Border + $bBorderLeft = ($conditional->getStyle()->getBorders()->getLeft()->getColor()->getARGB() == PHPExcel_Style_Color::COLOR_BLACK + && $conditional->getStyle()->getBorders()->getLeft()->getBorderStyle() == PHPExcel_Style_Border::BORDER_NONE ? 1 : 0); + $bBorderRight = ($conditional->getStyle()->getBorders()->getRight()->getColor()->getARGB() == PHPExcel_Style_Color::COLOR_BLACK + && $conditional->getStyle()->getBorders()->getRight()->getBorderStyle() == PHPExcel_Style_Border::BORDER_NONE ? 1 : 0); + $bBorderTop = ($conditional->getStyle()->getBorders()->getTop()->getColor()->getARGB() == PHPExcel_Style_Color::COLOR_BLACK + && $conditional->getStyle()->getBorders()->getTop()->getBorderStyle() == PHPExcel_Style_Border::BORDER_NONE ? 1 : 0); + $bBorderBottom = ($conditional->getStyle()->getBorders()->getBottom()->getColor()->getARGB() == PHPExcel_Style_Color::COLOR_BLACK + && $conditional->getStyle()->getBorders()->getBottom()->getBorderStyle() == PHPExcel_Style_Border::BORDER_NONE ? 1 : 0); + if($bBorderLeft == 0 || $bBorderRight == 0 || $bBorderTop == 0 || $bBorderBottom == 0){ + $bFormatBorder = 1; + } else { + $bFormatBorder = 0; + } + // Pattern + $bFillStyle = ($conditional->getStyle()->getFill()->getFillType() == null ? 0 : 1); + $bFillColor = ($conditional->getStyle()->getFill()->getStartColor()->getARGB() == null ? 0 : 1); + $bFillColorBg = ($conditional->getStyle()->getFill()->getEndColor()->getARGB() == null ? 0 : 1); + if($bFillStyle == 0 || $bFillColor == 0 || $bFillColorBg == 0){ + $bFormatFill = 1; + } else { + $bFormatFill = 0; + } + // Font + if($conditional->getStyle()->getFont()->getName() != null + || $conditional->getStyle()->getFont()->getSize() != null + || $conditional->getStyle()->getFont()->getBold() != null + || $conditional->getStyle()->getFont()->getItalic() != null + || $conditional->getStyle()->getFont()->getSuperScript() != null + || $conditional->getStyle()->getFont()->getSubScript() != null + || $conditional->getStyle()->getFont()->getUnderline() != null + || $conditional->getStyle()->getFont()->getStrikethrough() != null + || $conditional->getStyle()->getFont()->getColor()->getARGB() != null){ + $bFormatFont = 1; + } else { + $bFormatFont = 0; + } + // Alignment + $flags = 0; + $flags |= (1 == $bAlignHz ? 0x00000001 : 0); + $flags |= (1 == $bAlignVt ? 0x00000002 : 0); + $flags |= (1 == $bAlignWrapTx ? 0x00000004 : 0); + $flags |= (1 == $bTxRotation ? 0x00000008 : 0); + // Justify last line flag + $flags |= (1 == 1 ? 0x00000010 : 0); + $flags |= (1 == $bIndent ? 0x00000020 : 0); + $flags |= (1 == $bShrinkToFit ? 0x00000040 : 0); + // Default + $flags |= (1 == 1 ? 0x00000080 : 0); + // Protection + $flags |= (1 == $bProtLocked ? 0x00000100 : 0); + $flags |= (1 == $bProtHidden ? 0x00000200 : 0); + // Border + $flags |= (1 == $bBorderLeft ? 0x00000400 : 0); + $flags |= (1 == $bBorderRight ? 0x00000800 : 0); + $flags |= (1 == $bBorderTop ? 0x00001000 : 0); + $flags |= (1 == $bBorderBottom ? 0x00002000 : 0); + $flags |= (1 == 1 ? 0x00004000 : 0); // Top left to Bottom right border + $flags |= (1 == 1 ? 0x00008000 : 0); // Bottom left to Top right border + // Pattern + $flags |= (1 == $bFillStyle ? 0x00010000 : 0); + $flags |= (1 == $bFillColor ? 0x00020000 : 0); + $flags |= (1 == $bFillColorBg ? 0x00040000 : 0); + $flags |= (1 == 1 ? 0x00380000 : 0); + // Font + $flags |= (1 == $bFormatFont ? 0x04000000 : 0); + // Alignment : + $flags |= (1 == $bFormatAlign ? 0x08000000 : 0); + // Border + $flags |= (1 == $bFormatBorder ? 0x10000000 : 0); + // Pattern + $flags |= (1 == $bFormatFill ? 0x20000000 : 0); + // Protection + $flags |= (1 == $bFormatProt ? 0x40000000 : 0); + // Text direction + $flags |= (1 == 0 ? 0x80000000 : 0); + + // Data Blocks + if($bFormatFont == 1){ + // Font Name + if($conditional->getStyle()->getFont()->getName() == null){ + $dataBlockFont = pack('VVVVVVVV', 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000); + $dataBlockFont .= pack('VVVVVVVV', 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000); + } else { + $dataBlockFont = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($conditional->getStyle()->getFont()->getName()); + } + // Font Size + if($conditional->getStyle()->getFont()->getSize() == null){ + $dataBlockFont .= pack('V', 20 * 11); + } else { + $dataBlockFont .= pack('V', 20 * $conditional->getStyle()->getFont()->getSize()); + } + // Font Options + $dataBlockFont .= pack('V', 0); + // Font weight + if($conditional->getStyle()->getFont()->getBold() == true){ + $dataBlockFont .= pack('v', 0x02BC); + } else { + $dataBlockFont .= pack('v', 0x0190); + } + // Escapement type + if($conditional->getStyle()->getFont()->getSubScript() == true){ + $dataBlockFont .= pack('v', 0x02); + $fontEscapement = 0; + } else if($conditional->getStyle()->getFont()->getSuperScript() == true){ + $dataBlockFont .= pack('v', 0x01); + $fontEscapement = 0; + } else { + $dataBlockFont .= pack('v', 0x00); + $fontEscapement = 1; + } + // Underline type + switch ($conditional->getStyle()->getFont()->getUnderline()){ + case PHPExcel_Style_Font::UNDERLINE_NONE : $dataBlockFont .= pack('C', 0x00); $fontUnderline = 0; break; + case PHPExcel_Style_Font::UNDERLINE_DOUBLE : $dataBlockFont .= pack('C', 0x02); $fontUnderline = 0; break; + case PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING : $dataBlockFont .= pack('C', 0x22); $fontUnderline = 0; break; + case PHPExcel_Style_Font::UNDERLINE_SINGLE : $dataBlockFont .= pack('C', 0x01); $fontUnderline = 0; break; + case PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING : $dataBlockFont .= pack('C', 0x21); $fontUnderline = 0; break; + default : $dataBlockFont .= pack('C', 0x00); $fontUnderline = 1; break; + } + // Not used (3) + $dataBlockFont .= pack('vC', 0x0000, 0x00); + // Font color index + switch ($conditional->getStyle()->getFont()->getColor()->getRGB()) { + case '000000': $colorIdx = 0x08; break; + case 'FFFFFF': $colorIdx = 0x09; break; + case 'FF0000': $colorIdx = 0x0A; break; + case '00FF00': $colorIdx = 0x0B; break; + case '0000FF': $colorIdx = 0x0C; break; + case 'FFFF00': $colorIdx = 0x0D; break; + case 'FF00FF': $colorIdx = 0x0E; break; + case '00FFFF': $colorIdx = 0x0F; break; + case '800000': $colorIdx = 0x10; break; + case '008000': $colorIdx = 0x11; break; + case '000080': $colorIdx = 0x12; break; + case '808000': $colorIdx = 0x13; break; + case '800080': $colorIdx = 0x14; break; + case '008080': $colorIdx = 0x15; break; + case 'C0C0C0': $colorIdx = 0x16; break; + case '808080': $colorIdx = 0x17; break; + case '9999FF': $colorIdx = 0x18; break; + case '993366': $colorIdx = 0x19; break; + case 'FFFFCC': $colorIdx = 0x1A; break; + case 'CCFFFF': $colorIdx = 0x1B; break; + case '660066': $colorIdx = 0x1C; break; + case 'FF8080': $colorIdx = 0x1D; break; + case '0066CC': $colorIdx = 0x1E; break; + case 'CCCCFF': $colorIdx = 0x1F; break; + case '000080': $colorIdx = 0x20; break; + case 'FF00FF': $colorIdx = 0x21; break; + case 'FFFF00': $colorIdx = 0x22; break; + case '00FFFF': $colorIdx = 0x23; break; + case '800080': $colorIdx = 0x24; break; + case '800000': $colorIdx = 0x25; break; + case '008080': $colorIdx = 0x26; break; + case '0000FF': $colorIdx = 0x27; break; + case '00CCFF': $colorIdx = 0x28; break; + case 'CCFFFF': $colorIdx = 0x29; break; + case 'CCFFCC': $colorIdx = 0x2A; break; + case 'FFFF99': $colorIdx = 0x2B; break; + case '99CCFF': $colorIdx = 0x2C; break; + case 'FF99CC': $colorIdx = 0x2D; break; + case 'CC99FF': $colorIdx = 0x2E; break; + case 'FFCC99': $colorIdx = 0x2F; break; + case '3366FF': $colorIdx = 0x30; break; + case '33CCCC': $colorIdx = 0x31; break; + case '99CC00': $colorIdx = 0x32; break; + case 'FFCC00': $colorIdx = 0x33; break; + case 'FF9900': $colorIdx = 0x34; break; + case 'FF6600': $colorIdx = 0x35; break; + case '666699': $colorIdx = 0x36; break; + case '969696': $colorIdx = 0x37; break; + case '003366': $colorIdx = 0x38; break; + case '339966': $colorIdx = 0x39; break; + case '003300': $colorIdx = 0x3A; break; + case '333300': $colorIdx = 0x3B; break; + case '993300': $colorIdx = 0x3C; break; + case '993366': $colorIdx = 0x3D; break; + case '333399': $colorIdx = 0x3E; break; + case '333333': $colorIdx = 0x3F; break; + default: $colorIdx = 0x00; break; + } + $dataBlockFont .= pack('V', $colorIdx); + // Not used (4) + $dataBlockFont .= pack('V', 0x00000000); + // Options flags for modified font attributes + $optionsFlags = 0; + $optionsFlagsBold = ($conditional->getStyle()->getFont()->getBold() == null ? 1 : 0); + $optionsFlags |= (1 == $optionsFlagsBold ? 0x00000002 : 0); + $optionsFlags |= (1 == 1 ? 0x00000008 : 0); + $optionsFlags |= (1 == 1 ? 0x00000010 : 0); + $optionsFlags |= (1 == 0 ? 0x00000020 : 0); + $optionsFlags |= (1 == 1 ? 0x00000080 : 0); + $dataBlockFont .= pack('V', $optionsFlags); + // Escapement type + $dataBlockFont .= pack('V', $fontEscapement); + // Underline type + $dataBlockFont .= pack('V', $fontUnderline); + // Always + $dataBlockFont .= pack('V', 0x00000000); + // Always + $dataBlockFont .= pack('V', 0x00000000); + // Not used (8) + $dataBlockFont .= pack('VV', 0x00000000, 0x00000000); + // Always + $dataBlockFont .= pack('v', 0x0001); + } + if($bFormatAlign == 1){ + $blockAlign = 0; + // Alignment and text break + switch ($conditional->getStyle()->getAlignment()->getHorizontal()){ + case PHPExcel_Style_Alignment::HORIZONTAL_GENERAL : $blockAlign = 0; break; + case PHPExcel_Style_Alignment::HORIZONTAL_LEFT : $blockAlign = 1; break; + case PHPExcel_Style_Alignment::HORIZONTAL_RIGHT : $blockAlign = 3; break; + case PHPExcel_Style_Alignment::HORIZONTAL_CENTER : $blockAlign = 2; break; + case PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS : $blockAlign = 6; break; + case PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY : $blockAlign = 5; break; + } + if($conditional->getStyle()->getAlignment()->getWrapText() == true){ + $blockAlign |= 1 << 3; + } else { + $blockAlign |= 0 << 3; + } + switch ($conditional->getStyle()->getAlignment()->getVertical()){ + case PHPExcel_Style_Alignment::VERTICAL_BOTTOM : $blockAlign = 2 << 4; break; + case PHPExcel_Style_Alignment::VERTICAL_TOP : $blockAlign = 0 << 4; break; + case PHPExcel_Style_Alignment::VERTICAL_CENTER : $blockAlign = 1 << 4; break; + case PHPExcel_Style_Alignment::VERTICAL_JUSTIFY : $blockAlign = 3 << 4; break; + } + $blockAlign |= 0 << 7; + + // Text rotation angle + $blockRotation = $conditional->getStyle()->getAlignment()->getTextRotation(); + + // Indentation + $blockIndent = $conditional->getStyle()->getAlignment()->getIndent(); + if($conditional->getStyle()->getAlignment()->getShrinkToFit() == true){ + $blockIndent |= 1 << 4; + } else { + $blockIndent |= 0 << 4; + } + $blockIndent |= 0 << 6; + + // Relative indentation + $blockIndentRelative = 255; + + $dataBlockAlign = pack('CCvvv', $blockAlign, $blockRotation, $blockIndent, $blockIndentRelative, 0x0000); + } + if($bFormatBorder == 1){ + $blockLineStyle = 0; + switch ($conditional->getStyle()->getBorders()->getLeft()->getBorderStyle()){ + case PHPExcel_Style_Border::BORDER_NONE : $blockLineStyle |= 0x00; break; + case PHPExcel_Style_Border::BORDER_THIN : $blockLineStyle |= 0x01; break; + case PHPExcel_Style_Border::BORDER_MEDIUM : $blockLineStyle |= 0x02; break; + case PHPExcel_Style_Border::BORDER_DASHED : $blockLineStyle |= 0x03; break; + case PHPExcel_Style_Border::BORDER_DOTTED : $blockLineStyle |= 0x04; break; + case PHPExcel_Style_Border::BORDER_THICK : $blockLineStyle |= 0x05; break; + case PHPExcel_Style_Border::BORDER_DOUBLE : $blockLineStyle |= 0x06; break; + case PHPExcel_Style_Border::BORDER_HAIR : $blockLineStyle |= 0x07; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHED : $blockLineStyle |= 0x08; break; + case PHPExcel_Style_Border::BORDER_DASHDOT : $blockLineStyle |= 0x09; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT : $blockLineStyle |= 0x0A; break; + case PHPExcel_Style_Border::BORDER_DASHDOTDOT : $blockLineStyle |= 0x0B; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT : $blockLineStyle |= 0x0C; break; + case PHPExcel_Style_Border::BORDER_SLANTDASHDOT : $blockLineStyle |= 0x0D; break; + } + switch ($conditional->getStyle()->getBorders()->getRight()->getBorderStyle()){ + case PHPExcel_Style_Border::BORDER_NONE : $blockLineStyle |= 0x00 << 4; break; + case PHPExcel_Style_Border::BORDER_THIN : $blockLineStyle |= 0x01 << 4; break; + case PHPExcel_Style_Border::BORDER_MEDIUM : $blockLineStyle |= 0x02 << 4; break; + case PHPExcel_Style_Border::BORDER_DASHED : $blockLineStyle |= 0x03 << 4; break; + case PHPExcel_Style_Border::BORDER_DOTTED : $blockLineStyle |= 0x04 << 4; break; + case PHPExcel_Style_Border::BORDER_THICK : $blockLineStyle |= 0x05 << 4; break; + case PHPExcel_Style_Border::BORDER_DOUBLE : $blockLineStyle |= 0x06 << 4; break; + case PHPExcel_Style_Border::BORDER_HAIR : $blockLineStyle |= 0x07 << 4; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHED : $blockLineStyle |= 0x08 << 4; break; + case PHPExcel_Style_Border::BORDER_DASHDOT : $blockLineStyle |= 0x09 << 4; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT : $blockLineStyle |= 0x0A << 4; break; + case PHPExcel_Style_Border::BORDER_DASHDOTDOT : $blockLineStyle |= 0x0B << 4; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT : $blockLineStyle |= 0x0C << 4; break; + case PHPExcel_Style_Border::BORDER_SLANTDASHDOT : $blockLineStyle |= 0x0D << 4; break; + } + switch ($conditional->getStyle()->getBorders()->getTop()->getBorderStyle()){ + case PHPExcel_Style_Border::BORDER_NONE : $blockLineStyle |= 0x00 << 8; break; + case PHPExcel_Style_Border::BORDER_THIN : $blockLineStyle |= 0x01 << 8; break; + case PHPExcel_Style_Border::BORDER_MEDIUM : $blockLineStyle |= 0x02 << 8; break; + case PHPExcel_Style_Border::BORDER_DASHED : $blockLineStyle |= 0x03 << 8; break; + case PHPExcel_Style_Border::BORDER_DOTTED : $blockLineStyle |= 0x04 << 8; break; + case PHPExcel_Style_Border::BORDER_THICK : $blockLineStyle |= 0x05 << 8; break; + case PHPExcel_Style_Border::BORDER_DOUBLE : $blockLineStyle |= 0x06 << 8; break; + case PHPExcel_Style_Border::BORDER_HAIR : $blockLineStyle |= 0x07 << 8; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHED : $blockLineStyle |= 0x08 << 8; break; + case PHPExcel_Style_Border::BORDER_DASHDOT : $blockLineStyle |= 0x09 << 8; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT : $blockLineStyle |= 0x0A << 8; break; + case PHPExcel_Style_Border::BORDER_DASHDOTDOT : $blockLineStyle |= 0x0B << 8; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT : $blockLineStyle |= 0x0C << 8; break; + case PHPExcel_Style_Border::BORDER_SLANTDASHDOT : $blockLineStyle |= 0x0D << 8; break; + } + switch ($conditional->getStyle()->getBorders()->getBottom()->getBorderStyle()){ + case PHPExcel_Style_Border::BORDER_NONE : $blockLineStyle |= 0x00 << 12; break; + case PHPExcel_Style_Border::BORDER_THIN : $blockLineStyle |= 0x01 << 12; break; + case PHPExcel_Style_Border::BORDER_MEDIUM : $blockLineStyle |= 0x02 << 12; break; + case PHPExcel_Style_Border::BORDER_DASHED : $blockLineStyle |= 0x03 << 12; break; + case PHPExcel_Style_Border::BORDER_DOTTED : $blockLineStyle |= 0x04 << 12; break; + case PHPExcel_Style_Border::BORDER_THICK : $blockLineStyle |= 0x05 << 12; break; + case PHPExcel_Style_Border::BORDER_DOUBLE : $blockLineStyle |= 0x06 << 12; break; + case PHPExcel_Style_Border::BORDER_HAIR : $blockLineStyle |= 0x07 << 12; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHED : $blockLineStyle |= 0x08 << 12; break; + case PHPExcel_Style_Border::BORDER_DASHDOT : $blockLineStyle |= 0x09 << 12; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT : $blockLineStyle |= 0x0A << 12; break; + case PHPExcel_Style_Border::BORDER_DASHDOTDOT : $blockLineStyle |= 0x0B << 12; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT : $blockLineStyle |= 0x0C << 12; break; + case PHPExcel_Style_Border::BORDER_SLANTDASHDOT : $blockLineStyle |= 0x0D << 12; break; + } + //@todo _writeCFRule() => $blockLineStyle => Index Color for left line + //@todo _writeCFRule() => $blockLineStyle => Index Color for right line + //@todo _writeCFRule() => $blockLineStyle => Top-left to bottom-right on/off + //@todo _writeCFRule() => $blockLineStyle => Bottom-left to top-right on/off + $blockColor = 0; + //@todo _writeCFRule() => $blockColor => Index Color for top line + //@todo _writeCFRule() => $blockColor => Index Color for bottom line + //@todo _writeCFRule() => $blockColor => Index Color for diagonal line + switch ($conditional->getStyle()->getBorders()->getDiagonal()->getBorderStyle()){ + case PHPExcel_Style_Border::BORDER_NONE : $blockColor |= 0x00 << 21; break; + case PHPExcel_Style_Border::BORDER_THIN : $blockColor |= 0x01 << 21; break; + case PHPExcel_Style_Border::BORDER_MEDIUM : $blockColor |= 0x02 << 21; break; + case PHPExcel_Style_Border::BORDER_DASHED : $blockColor |= 0x03 << 21; break; + case PHPExcel_Style_Border::BORDER_DOTTED : $blockColor |= 0x04 << 21; break; + case PHPExcel_Style_Border::BORDER_THICK : $blockColor |= 0x05 << 21; break; + case PHPExcel_Style_Border::BORDER_DOUBLE : $blockColor |= 0x06 << 21; break; + case PHPExcel_Style_Border::BORDER_HAIR : $blockColor |= 0x07 << 21; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHED : $blockColor |= 0x08 << 21; break; + case PHPExcel_Style_Border::BORDER_DASHDOT : $blockColor |= 0x09 << 21; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT : $blockColor |= 0x0A << 21; break; + case PHPExcel_Style_Border::BORDER_DASHDOTDOT : $blockColor |= 0x0B << 21; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT : $blockColor |= 0x0C << 21; break; + case PHPExcel_Style_Border::BORDER_SLANTDASHDOT : $blockColor |= 0x0D << 21; break; + } + $dataBlockBorder = pack('vv', $blockLineStyle, $blockColor); + } + if($bFormatFill == 1){ + // Fill Patern Style + $blockFillPatternStyle = 0; + switch ($conditional->getStyle()->getFill()->getFillType()){ + case PHPExcel_Style_Fill::FILL_NONE : $blockFillPatternStyle = 0x00; break; + case PHPExcel_Style_Fill::FILL_SOLID : $blockFillPatternStyle = 0x01; break; + case PHPExcel_Style_Fill::FILL_PATTERN_MEDIUMGRAY : $blockFillPatternStyle = 0x02; break; + case PHPExcel_Style_Fill::FILL_PATTERN_DARKGRAY : $blockFillPatternStyle = 0x03; break; + case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRAY : $blockFillPatternStyle = 0x04; break; + case PHPExcel_Style_Fill::FILL_PATTERN_DARKHORIZONTAL : $blockFillPatternStyle = 0x05; break; + case PHPExcel_Style_Fill::FILL_PATTERN_DARKVERTICAL : $blockFillPatternStyle = 0x06; break; + case PHPExcel_Style_Fill::FILL_PATTERN_DARKDOWN : $blockFillPatternStyle = 0x07; break; + case PHPExcel_Style_Fill::FILL_PATTERN_DARKUP : $blockFillPatternStyle = 0x08; break; + case PHPExcel_Style_Fill::FILL_PATTERN_DARKGRID : $blockFillPatternStyle = 0x09; break; + case PHPExcel_Style_Fill::FILL_PATTERN_DARKTRELLIS : $blockFillPatternStyle = 0x0A; break; + case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTHORIZONTAL : $blockFillPatternStyle = 0x0B; break; + case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTVERTICAL : $blockFillPatternStyle = 0x0C; break; + case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTDOWN : $blockFillPatternStyle = 0x0D; break; + case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTUP : $blockFillPatternStyle = 0x0E; break; + case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRID : $blockFillPatternStyle = 0x0F; break; + case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTTRELLIS : $blockFillPatternStyle = 0x10; break; + case PHPExcel_Style_Fill::FILL_PATTERN_GRAY125 : $blockFillPatternStyle = 0x11; break; + case PHPExcel_Style_Fill::FILL_PATTERN_GRAY0625 : $blockFillPatternStyle = 0x12; break; + case PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR : $blockFillPatternStyle = 0x00; break; // does not exist in BIFF8 + case PHPExcel_Style_Fill::FILL_GRADIENT_PATH : $blockFillPatternStyle = 0x00; break; // does not exist in BIFF8 + default : $blockFillPatternStyle = 0x00; break; + } + // Color + switch ($conditional->getStyle()->getFill()->getStartColor()->getRGB()) { + case '000000': $colorIdxBg = 0x08; break; + case 'FFFFFF': $colorIdxBg = 0x09; break; + case 'FF0000': $colorIdxBg = 0x0A; break; + case '00FF00': $colorIdxBg = 0x0B; break; + case '0000FF': $colorIdxBg = 0x0C; break; + case 'FFFF00': $colorIdxBg = 0x0D; break; + case 'FF00FF': $colorIdxBg = 0x0E; break; + case '00FFFF': $colorIdxBg = 0x0F; break; + case '800000': $colorIdxBg = 0x10; break; + case '008000': $colorIdxBg = 0x11; break; + case '000080': $colorIdxBg = 0x12; break; + case '808000': $colorIdxBg = 0x13; break; + case '800080': $colorIdxBg = 0x14; break; + case '008080': $colorIdxBg = 0x15; break; + case 'C0C0C0': $colorIdxBg = 0x16; break; + case '808080': $colorIdxBg = 0x17; break; + case '9999FF': $colorIdxBg = 0x18; break; + case '993366': $colorIdxBg = 0x19; break; + case 'FFFFCC': $colorIdxBg = 0x1A; break; + case 'CCFFFF': $colorIdxBg = 0x1B; break; + case '660066': $colorIdxBg = 0x1C; break; + case 'FF8080': $colorIdxBg = 0x1D; break; + case '0066CC': $colorIdxBg = 0x1E; break; + case 'CCCCFF': $colorIdxBg = 0x1F; break; + case '000080': $colorIdxBg = 0x20; break; + case 'FF00FF': $colorIdxBg = 0x21; break; + case 'FFFF00': $colorIdxBg = 0x22; break; + case '00FFFF': $colorIdxBg = 0x23; break; + case '800080': $colorIdxBg = 0x24; break; + case '800000': $colorIdxBg = 0x25; break; + case '008080': $colorIdxBg = 0x26; break; + case '0000FF': $colorIdxBg = 0x27; break; + case '00CCFF': $colorIdxBg = 0x28; break; + case 'CCFFFF': $colorIdxBg = 0x29; break; + case 'CCFFCC': $colorIdxBg = 0x2A; break; + case 'FFFF99': $colorIdxBg = 0x2B; break; + case '99CCFF': $colorIdxBg = 0x2C; break; + case 'FF99CC': $colorIdxBg = 0x2D; break; + case 'CC99FF': $colorIdxBg = 0x2E; break; + case 'FFCC99': $colorIdxBg = 0x2F; break; + case '3366FF': $colorIdxBg = 0x30; break; + case '33CCCC': $colorIdxBg = 0x31; break; + case '99CC00': $colorIdxBg = 0x32; break; + case 'FFCC00': $colorIdxBg = 0x33; break; + case 'FF9900': $colorIdxBg = 0x34; break; + case 'FF6600': $colorIdxBg = 0x35; break; + case '666699': $colorIdxBg = 0x36; break; + case '969696': $colorIdxBg = 0x37; break; + case '003366': $colorIdxBg = 0x38; break; + case '339966': $colorIdxBg = 0x39; break; + case '003300': $colorIdxBg = 0x3A; break; + case '333300': $colorIdxBg = 0x3B; break; + case '993300': $colorIdxBg = 0x3C; break; + case '993366': $colorIdxBg = 0x3D; break; + case '333399': $colorIdxBg = 0x3E; break; + case '333333': $colorIdxBg = 0x3F; break; + default: $colorIdxBg = 0x41; break; + } + // Fg Color + switch ($conditional->getStyle()->getFill()->getEndColor()->getRGB()) { + case '000000': $colorIdxFg = 0x08; break; + case 'FFFFFF': $colorIdxFg = 0x09; break; + case 'FF0000': $colorIdxFg = 0x0A; break; + case '00FF00': $colorIdxFg = 0x0B; break; + case '0000FF': $colorIdxFg = 0x0C; break; + case 'FFFF00': $colorIdxFg = 0x0D; break; + case 'FF00FF': $colorIdxFg = 0x0E; break; + case '00FFFF': $colorIdxFg = 0x0F; break; + case '800000': $colorIdxFg = 0x10; break; + case '008000': $colorIdxFg = 0x11; break; + case '000080': $colorIdxFg = 0x12; break; + case '808000': $colorIdxFg = 0x13; break; + case '800080': $colorIdxFg = 0x14; break; + case '008080': $colorIdxFg = 0x15; break; + case 'C0C0C0': $colorIdxFg = 0x16; break; + case '808080': $colorIdxFg = 0x17; break; + case '9999FF': $colorIdxFg = 0x18; break; + case '993366': $colorIdxFg = 0x19; break; + case 'FFFFCC': $colorIdxFg = 0x1A; break; + case 'CCFFFF': $colorIdxFg = 0x1B; break; + case '660066': $colorIdxFg = 0x1C; break; + case 'FF8080': $colorIdxFg = 0x1D; break; + case '0066CC': $colorIdxFg = 0x1E; break; + case 'CCCCFF': $colorIdxFg = 0x1F; break; + case '000080': $colorIdxFg = 0x20; break; + case 'FF00FF': $colorIdxFg = 0x21; break; + case 'FFFF00': $colorIdxFg = 0x22; break; + case '00FFFF': $colorIdxFg = 0x23; break; + case '800080': $colorIdxFg = 0x24; break; + case '800000': $colorIdxFg = 0x25; break; + case '008080': $colorIdxFg = 0x26; break; + case '0000FF': $colorIdxFg = 0x27; break; + case '00CCFF': $colorIdxFg = 0x28; break; + case 'CCFFFF': $colorIdxFg = 0x29; break; + case 'CCFFCC': $colorIdxFg = 0x2A; break; + case 'FFFF99': $colorIdxFg = 0x2B; break; + case '99CCFF': $colorIdxFg = 0x2C; break; + case 'FF99CC': $colorIdxFg = 0x2D; break; + case 'CC99FF': $colorIdxFg = 0x2E; break; + case 'FFCC99': $colorIdxFg = 0x2F; break; + case '3366FF': $colorIdxFg = 0x30; break; + case '33CCCC': $colorIdxFg = 0x31; break; + case '99CC00': $colorIdxFg = 0x32; break; + case 'FFCC00': $colorIdxFg = 0x33; break; + case 'FF9900': $colorIdxFg = 0x34; break; + case 'FF6600': $colorIdxFg = 0x35; break; + case '666699': $colorIdxFg = 0x36; break; + case '969696': $colorIdxFg = 0x37; break; + case '003366': $colorIdxFg = 0x38; break; + case '339966': $colorIdxFg = 0x39; break; + case '003300': $colorIdxFg = 0x3A; break; + case '333300': $colorIdxFg = 0x3B; break; + case '993300': $colorIdxFg = 0x3C; break; + case '993366': $colorIdxFg = 0x3D; break; + case '333399': $colorIdxFg = 0x3E; break; + case '333333': $colorIdxFg = 0x3F; break; + default: $colorIdxFg = 0x40; break; + } + $dataBlockFill = pack('v', $blockFillPatternStyle); + $dataBlockFill .= pack('v', $colorIdxFg | ($colorIdxBg << 7)); + } + if($bFormatProt == 1){ + $dataBlockProtection = 0; + if($conditional->getStyle()->getProtection()->getLocked() == PHPExcel_Style_Protection::PROTECTION_PROTECTED){ + $dataBlockProtection = 1; + } + if($conditional->getStyle()->getProtection()->getHidden() == PHPExcel_Style_Protection::PROTECTION_PROTECTED){ + $dataBlockProtection = 1 << 1; + } + } + + $data = pack('CCvvVv', $type, $operatorType, $szValue1, $szValue2, $flags, 0x0000); + if($bFormatFont == 1){ // Block Formatting : OK + $data .= $dataBlockFont; + } + if($bFormatAlign == 1){ + $data .= $dataBlockAlign; + } + if($bFormatBorder == 1){ + $data .= $dataBlockBorder; + } + if($bFormatFill == 1){ // Block Formatting : OK + $data .= $dataBlockFill; + } + if($bFormatProt == 1){ + $data .= $dataBlockProtection; + } + if(!is_null($operand1)){ + $data .= $operand1; + } + if(!is_null($operand2)){ + $data .= $operand2; + } + $header = pack('vv', $record, strlen($data)); + $this->_append($header . $data); + } + + /** + * Write CFHeader record + */ + private function _writeCFHeader(){ + $record = 0x01B0; // Record identifier + $length = 0x0016; // Bytes to follow + + $numColumnMin = null; + $numColumnMax = null; + $numRowMin = null; + $numRowMax = null; + $arrConditional = array(); + foreach ($this->_phpSheet->getConditionalStylesCollection() as $cellCoordinate => $conditionalStyles) { + foreach ($conditionalStyles as $conditional) { + if($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_EXPRESSION + || $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS){ + if(!in_array($conditional->getHashCode(), $arrConditional)){ + $arrConditional[] = $conditional->getHashCode(); + } + // Cells + $arrCoord = PHPExcel_Cell::coordinateFromString($cellCoordinate); + if(!is_numeric($arrCoord[0])){ + $arrCoord[0] = PHPExcel_Cell::columnIndexFromString($arrCoord[0]); + } + if(is_null($numColumnMin) || ($numColumnMin > $arrCoord[0])){ + $numColumnMin = $arrCoord[0]; + } + if(is_null($numColumnMax) || ($numColumnMax < $arrCoord[0])){ + $numColumnMax = $arrCoord[0]; + } + if(is_null($numRowMin) || ($numRowMin > $arrCoord[1])){ + $numRowMin = $arrCoord[1]; + } + if(is_null($numRowMax) || ($numRowMax < $arrCoord[1])){ + $numRowMax = $arrCoord[1]; + } + } + } + } + $needRedraw = 1; + $cellRange = pack('vvvv', $numRowMin-1, $numRowMax-1, $numColumnMin-1, $numColumnMax-1); + + $header = pack('vv', $record, $length); + $data = pack('vv', count($arrConditional), $needRedraw); + $data .= $cellRange; + $data .= pack('v', 0x0001); + $data .= $cellRange; + $this->_append($header . $data); + } } \ No newline at end of file diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Xf.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Xf.php index 06fb1d9d8cf..f803f68346b 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Xf.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Excel5/Xf.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +20,9 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ // Original file header of PEAR::Spreadsheet_Excel_Writer_Format (used as the base for this class): @@ -66,7 +66,7 @@ * * @category PHPExcel * @package PHPExcel_Writer_Excel5 - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ class PHPExcel_Writer_Excel5_Xf { @@ -179,7 +179,7 @@ class PHPExcel_Writer_Excel5_Xf // Flags to indicate if attributes have been set. $atr_num = ($this->_numberFormatIndex != 0)?1:0; $atr_fnt = ($this->_fontIndex != 0)?1:0; - $atr_alc = ((int) $this->_style->getAlignment()->getWrapText())?1:0; + $atr_alc = ((int) $this->_style->getAlignment()->getWrapText()) ? 1 : 0; $atr_bdr = (self::_mapBorderStyle($this->_style->getBorders()->getBottom()->getBorderStyle()) || self::_mapBorderStyle($this->_style->getBorders()->getTop()->getBorderStyle()) || self::_mapBorderStyle($this->_style->getBorders()->getLeft()->getBorderStyle()) || @@ -457,6 +457,7 @@ class PHPExcel_Writer_Excel5_Xf PHPExcel_Style_Alignment::HORIZONTAL_LEFT => 1, PHPExcel_Style_Alignment::HORIZONTAL_CENTER => 2, PHPExcel_Style_Alignment::HORIZONTAL_RIGHT => 3, + PHPExcel_Style_Alignment::HORIZONTAL_FILL => 4, PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY => 5, PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS => 6, ); diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/Exception.php b/htdocs/includes/phpexcel/PHPExcel/Writer/Exception.php new file mode 100644 index 00000000000..e8fe9be783d --- /dev/null +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/Exception.php @@ -0,0 +1,52 @@ +line = $line; + $e->file = $file; + throw $e; + } +} diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/HTML.php b/htdocs/includes/phpexcel/PHPExcel/Writer/HTML.php index f0aafafed34..0f2cc089f6b 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/HTML.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/HTML.php @@ -2,7 +2,7 @@ /** * PHPExcel * - * Copyright (c) 2006 - 2012 PHPExcel + * Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,10 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * @category PHPExcel - * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @package PHPExcel_Writer_HTML + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL - * @version 1.7.8, 2012-10-12 + * @version 1.8.0, 2014-03-02 */ @@ -30,10 +30,10 @@ * PHPExcel_Writer_HTML * * @category PHPExcel - * @package PHPExcel_Writer - * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) + * @package PHPExcel_Writer_HTML + * @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) */ -class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { +class PHPExcel_Writer_HTML extends PHPExcel_Writer_Abstract implements PHPExcel_Writer_IWriter { /** * PHPExcel object * @@ -48,13 +48,6 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { */ private $_sheetIndex = 0; - /** - * Pre-calculate formulas - * - * @var boolean - */ - private $_preCalculateFormulas = true; - /** * Images root * @@ -62,6 +55,13 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { */ private $_imagesRoot = '.'; + /** + * embed images, or link to images + * + * @var boolean + */ + private $_embedImages = FALSE; + /** * Use inline CSS? * @@ -146,14 +146,14 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { * Save PHPExcel to file * * @param string $pFilename - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function save($pFilename = null) { // garbage collect $this->_phpExcel->garbageCollect(); - $saveDebugLog = PHPExcel_Calculation::getInstance()->writeDebugLog; - PHPExcel_Calculation::getInstance()->writeDebugLog = false; + $saveDebugLog = PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->getWriteDebugLog(); + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog(FALSE); $saveArrayReturnType = PHPExcel_Calculation::getArrayReturnType(); PHPExcel_Calculation::setArrayReturnType(PHPExcel_Calculation::RETURN_ARRAY_AS_VALUE); @@ -163,7 +163,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // Open file $fileHandle = fopen($pFilename, 'wb+'); if ($fileHandle === false) { - throw new Exception("Could not open file $pFilename for writing."); + throw new PHPExcel_Writer_Exception("Could not open file $pFilename for writing."); } // Write headers @@ -184,7 +184,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { fclose($fileHandle); PHPExcel_Calculation::setArrayReturnType($saveArrayReturnType); - PHPExcel_Calculation::getInstance()->writeDebugLog = $saveDebugLog; + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog($saveDebugLog); } /** @@ -300,12 +300,12 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { * * @param boolean $pIncludeStyles Include styles? * @return string - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function generateHTMLHeader($pIncludeStyles = false) { // PHPExcel object known? if (is_null($this->_phpExcel)) { - throw new Exception('Internal PHPExcel object not set to an instance of an object.'); + throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); } // Construct HTML @@ -351,12 +351,12 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { * Generate sheet data * * @return string - * @throws Exception + * @throws PHPExcel_Writer_Exception */ public function generateSheetData() { // PHPExcel object known? if (is_null($this->_phpExcel)) { - throw new Exception('Internal PHPExcel object not set to an instance of an object.'); + throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); } // Ensure that Spans have been calculated? @@ -394,7 +394,6 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // calculate start of

'; + $html .= $this->_writeImageInCell($pSheet, $col.$row); + if ($this->_includeCharts) { + $html .= $this->_writeChartInCell($pSheet, $col.$row); + } + $html .= '
' . PHP_EOL; } else { $style = isset($this->_cssStyles['table']) ? $this->_assembleCSS($this->_cssStyles['table']) : ''; - if ($this->_isPdf && $pSheet->getShowGridLines()) { - $html .= '
' . PHP_EOL; + if ($this->_isPdf && $pSheet->getShowGridlines()) { + $html .= '
' . PHP_EOL; } else { - $html .= '
' . PHP_EOL; + $html .= '
' . PHP_EOL; } } @@ -938,7 +1057,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { /** * Generate table footer * - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _generateTableFooter() { // Construct HTML @@ -956,7 +1075,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { * @param array $pValues Array containing cells in a row * @param int $pRow Row number (0-based) * @return string - * @throws Exception + * @throws PHPExcel_Writer_Exception */ private function _generateRow(PHPExcel_Worksheet $pSheet, $pValues = null, $pRow = 0) { if (is_array($pValues)) { @@ -995,9 +1114,9 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // Write cells $colNum = 0; - foreach ($pValues as $cell) { + foreach ($pValues as $cellAddress) { + $cell = ($cellAddress > '') ? $pSheet->getCell($cellAddress) : ''; $coordinate = PHPExcel_Cell::stringFromColumnIndex($colNum) . ($pRow + 1); - if (!$this->_useInlineCss) { $cssClass = ''; $cssClass = 'column' . $colNum; @@ -1011,10 +1130,11 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { $rowSpan = 1; // initialize - $cellData = ''; + $cellData = ' '; // PHPExcel_Cell if ($cell instanceof PHPExcel_Cell) { + $cellData = ''; if (is_null($cell->getParent())) { $cell->attach($pSheet); } @@ -1112,6 +1232,13 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { $spans = $this->_isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum]; $rowSpan = $spans['rowspan']; $colSpan = $spans['colspan']; + + // Also apply style from last cell in merge to fix borders - + // relies on !important for non-none border declarations in _createCSSStyleBorder + $endCellCoord = PHPExcel_Cell::stringFromColumnIndex($colNum + $colSpan - 1) . ($pRow + $rowSpan); + if (!$this->_useInlineCss) { + $cssClass .= ' style' . $pSheet->getCell($endCellCoord)->getXfIndex(); + } } // Write @@ -1153,7 +1280,12 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { $html .= '>'; // Image? - $html .= $this->_writeImageTagInCell($pSheet, $coordinate); + $html .= $this->_writeImageInCell($pSheet, $coordinate); + + // Chart? + if ($this->_includeCharts) { + $html .= $this->_writeChartInCell($pSheet, $coordinate); + } // Cell data $html .= $cellData; @@ -1172,7 +1304,7 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { // Return return $html; } else { - throw new Exception("Invalid parameters passed."); + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); } } @@ -1193,26 +1325,6 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { return $string; } - /** - * Get Pre-Calculate Formulas - * - * @return boolean - */ - public function getPreCalculateFormulas() { - return $this->_preCalculateFormulas; - } - - /** - * Set Pre-Calculate Formulas - * - * @param boolean $pValue Pre-Calculate Formulas? - * @return PHPExcel_Writer_HTML - */ - public function setPreCalculateFormulas($pValue = true) { - $this->_preCalculateFormulas = $pValue; - return $this; - } - /** * Get images root * @@ -1233,6 +1345,26 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { return $this; } + /** + * Get embed images + * + * @return boolean + */ + public function getEmbedImages() { + return $this->_embedImages; + } + + /** + * Set embed images + * + * @param boolean $pValue + * @return PHPExcel_Writer_HTML + */ + public function setEmbedImages($pValue = '.') { + $this->_embedImages = $pValue; + return $this; + } + /** * Get use inline CSS? * @@ -1374,4 +1506,27 @@ class PHPExcel_Writer_HTML implements PHPExcel_Writer_IWriter { $this->_spansAreCalculated = true; } + private function _setMargins(PHPExcel_Worksheet $pSheet) { + $htmlPage = '@page { '; + $htmlBody = 'body { '; + + $left = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getLeft()) . 'in; '; + $htmlPage .= 'left-margin: ' . $left; + $htmlBody .= 'left-margin: ' . $left; + $right = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getRight()) . 'in; '; + $htmlPage .= 'right-margin: ' . $right; + $htmlBody .= 'right-margin: ' . $right; + $top = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getTop()) . 'in; '; + $htmlPage .= 'top-margin: ' . $top; + $htmlBody .= 'top-margin: ' . $top; + $bottom = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getBottom()) . 'in; '; + $htmlPage .= 'bottom-margin: ' . $bottom; + $htmlBody .= 'bottom-margin: ' . $bottom; + + $htmlPage .= "}\n"; + $htmlBody .= "}\n"; + + return "\n"; + } + } diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/IWriter.php b/htdocs/includes/phpexcel/PHPExcel/Writer/IWriter.php index af97f0778ce..6974c93c875 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/IWriter.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/IWriter.php @@ -1,45 +1,46 @@ _renderer = new $rendererName($phpExcel); - } + $rendererName = 'PHPExcel_Writer_PDF_' . $pdfLibraryName; + $this->_renderer = new $rendererName($phpExcel); + } + /** + * Magic method to handle direct calls to the configured PDF renderer wrapper class. + * + * @param string $name Renderer library method name + * @param mixed[] $arguments Array of arguments to pass to the renderer method + * @return mixed Returned data from the PDF renderer wrapper method + */ public function __call($name, $arguments) { if ($this->_renderer === NULL) { - throw new Exception("PDF Renderer has not been defined."); + throw new PHPExcel_Writer_Exception("PDF Rendering library has not been defined."); } - return call_user_func_array(array($this->_renderer,$name),$arguments); + return call_user_func_array(array($this->_renderer, $name), $arguments); } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/PDF/Core.php b/htdocs/includes/phpexcel/PHPExcel/Writer/PDF/Core.php index b9154ac6bee..3b281f4e582 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/PDF/Core.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/PDF/Core.php @@ -1,239 +1,364 @@ 'LETTER', // (8.5 in. by 11 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER_SMALL => 'LETTER', // (8.5 in. by 11 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_TABLOID => array(792.00,1224.00), // (11 in. by 17 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_LEDGER => array(1224.00,792.00), // (17 in. by 11 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_LEGAL => 'LEGAL', // (8.5 in. by 14 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_STATEMENT => array(396.00,612.00), // (5.5 in. by 8.5 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_EXECUTIVE => 'EXECUTIVE', // (7.25 in. by 10.5 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_A3 => 'A3', // (297 mm by 420 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4 => 'A4', // (210 mm by 297 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4_SMALL => 'A4', // (210 mm by 297 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_A5 => 'A5', // (148 mm by 210 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_B4 => 'B4', // (250 mm by 353 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_B5 => 'B5', // (176 mm by 250 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_FOLIO => 'FOLIO', // (8.5 in. by 13 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_QUARTO => array(609.45,779.53), // (215 mm by 275 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_STANDARD_1 => array(720.00,1008.00), // (10 in. by 14 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_STANDARD_2 => array(792.00,1224.00), // (11 in. by 17 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_NOTE => 'LETTER', // (8.5 in. by 11 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_NO9_ENVELOPE => array(279.00,639.00), // (3.875 in. by 8.875 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_NO10_ENVELOPE => array(297.00,684.00), // (4.125 in. by 9.5 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_NO11_ENVELOPE => array(324.00,747.00), // (4.5 in. by 10.375 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_NO12_ENVELOPE => array(342.00,792.00), // (4.75 in. by 11 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_NO14_ENVELOPE => array(360.00,828.00), // (5 in. by 11.5 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_C => array(1224.00,1584.00), // (17 in. by 22 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_D => array(1584.00,2448.00), // (22 in. by 34 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_E => array(2448.00,3168.00), // (34 in. by 44 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_DL_ENVELOPE => array(311.81,623.62), // (110 mm by 220 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_C5_ENVELOPE => 'C5', // (162 mm by 229 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_C3_ENVELOPE => 'C3', // (324 mm by 458 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_C4_ENVELOPE => 'C4', // (229 mm by 324 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_C6_ENVELOPE => 'C6', // (114 mm by 162 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_C65_ENVELOPE => array(323.15,649.13), // (114 mm by 229 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_B4_ENVELOPE => 'B4', // (250 mm by 353 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_B5_ENVELOPE => 'B5', // (176 mm by 250 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_B6_ENVELOPE => array(498.90,354.33), // (176 mm by 125 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_ITALY_ENVELOPE => array(311.81,651.97), // (110 mm by 230 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_MONARCH_ENVELOPE => array(279.00,540.00), // (3.875 in. by 7.5 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_6_3_4_ENVELOPE => array(261.00,468.00), // (3.625 in. by 6.5 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_US_STANDARD_FANFOLD => array(1071.00,792.00), // (14.875 in. by 11 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_GERMAN_STANDARD_FANFOLD => array(612.00,864.00), // (8.5 in. by 12 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_GERMAN_LEGAL_FANFOLD => 'FOLIO', // (8.5 in. by 13 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_ISO_B4 => 'B4', // (250 mm by 353 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_JAPANESE_DOUBLE_POSTCARD => array(566.93,419.53), // (200 mm by 148 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_STANDARD_PAPER_1 => array(648.00,792.00), // (9 in. by 11 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_STANDARD_PAPER_2 => array(720.00,792.00), // (10 in. by 11 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_STANDARD_PAPER_3 => array(1080.00,792.00), // (15 in. by 11 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_INVITE_ENVELOPE => array(623.62,623.62), // (220 mm by 220 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER_EXTRA_PAPER => array(667.80,864.00), // (9.275 in. by 12 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_LEGAL_EXTRA_PAPER => array(667.80,1080.00), // (9.275 in. by 15 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_TABLOID_EXTRA_PAPER => array(841.68,1296.00), // (11.69 in. by 18 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4_EXTRA_PAPER => array(668.98,912.76), // (236 mm by 322 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER_TRANSVERSE_PAPER => array(595.80,792.00), // (8.275 in. by 11 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4_TRANSVERSE_PAPER => 'A4', // (210 mm by 297 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER_EXTRA_TRANSVERSE_PAPER => array(667.80,864.00), // (9.275 in. by 12 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_SUPERA_SUPERA_A4_PAPER => array(643.46,1009.13), // (227 mm by 356 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_SUPERB_SUPERB_A3_PAPER => array(864.57,1380.47), // (305 mm by 487 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER_PLUS_PAPER => array(612.00,913.68), // (8.5 in. by 12.69 in.) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4_PLUS_PAPER => array(595.28,935.43), // (210 mm by 330 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_A5_TRANSVERSE_PAPER => 'A5', // (148 mm by 210 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_JIS_B5_TRANSVERSE_PAPER => array(515.91,728.50), // (182 mm by 257 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_A3_EXTRA_PAPER => array(912.76,1261.42), // (322 mm by 445 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_A5_EXTRA_PAPER => array(493.23,666.14), // (174 mm by 235 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_ISO_B5_EXTRA_PAPER => array(569.76,782.36), // (201 mm by 276 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_A2_PAPER => 'A2', // (420 mm by 594 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_A3_TRANSVERSE_PAPER => 'A3', // (297 mm by 420 mm) - PHPExcel_Worksheet_PageSetup::PAPERSIZE_A3_EXTRA_TRANSVERSE_PAPER => array(912.76,1261.42) // (322 mm by 445 mm) - ); - - /** - * Create a new PHPExcel_Writer_PDF - * - * @param PHPExcel $phpExcel PHPExcel object - */ - public function __construct(PHPExcel $phpExcel) { - parent::__construct($phpExcel); - $this->setUseInlineCss(true); - $this->_tempDir = PHPExcel_Shared_File::sys_get_temp_dir(); - } +abstract class PHPExcel_Writer_PDF_Core extends PHPExcel_Writer_HTML +{ + /** + * Temporary storage directory + * + * @var string + */ + protected $_tempDir = ''; /** - * Get Font + * Font * - * @return string + * @var string */ - public function getFont() { - return $this->_font; - } - - /** - * Set font. Examples: - * 'arialunicid0-chinese-simplified' - * 'arialunicid0-chinese-traditional' - * 'arialunicid0-korean' - * 'arialunicid0-japanese' - * - * @param string $fontName - */ - public function setFont($fontName) { - $this->_font = $fontName; - return $this; - } + protected $_font = 'freesans'; /** - * Get Paper Size + * Orientation (Over-ride) * - * @return int + * @var string */ - public function getPaperSize() { - return $this->_paperSize; + protected $_orientation = NULL; + + /** + * Paper size (Over-ride) + * + * @var int + */ + protected $_paperSize = NULL; + + + /** + * Temporary storage for Save Array Return type + * + * @var string + */ + private $_saveArrayReturnType; + + /** + * Paper Sizes xRef List + * + * @var array + */ + protected static $_paperSizes = array( + PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER + => 'LETTER', // (8.5 in. by 11 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER_SMALL + => 'LETTER', // (8.5 in. by 11 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_TABLOID + => array(792.00, 1224.00), // (11 in. by 17 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_LEDGER + => array(1224.00, 792.00), // (17 in. by 11 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_LEGAL + => 'LEGAL', // (8.5 in. by 14 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_STATEMENT + => array(396.00, 612.00), // (5.5 in. by 8.5 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_EXECUTIVE + => 'EXECUTIVE', // (7.25 in. by 10.5 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A3 + => 'A3', // (297 mm by 420 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4 + => 'A4', // (210 mm by 297 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4_SMALL + => 'A4', // (210 mm by 297 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A5 + => 'A5', // (148 mm by 210 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_B4 + => 'B4', // (250 mm by 353 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_B5 + => 'B5', // (176 mm by 250 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_FOLIO + => 'FOLIO', // (8.5 in. by 13 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_QUARTO + => array(609.45, 779.53), // (215 mm by 275 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_STANDARD_1 + => array(720.00, 1008.00), // (10 in. by 14 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_STANDARD_2 + => array(792.00, 1224.00), // (11 in. by 17 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_NOTE + => 'LETTER', // (8.5 in. by 11 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_NO9_ENVELOPE + => array(279.00, 639.00), // (3.875 in. by 8.875 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_NO10_ENVELOPE + => array(297.00, 684.00), // (4.125 in. by 9.5 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_NO11_ENVELOPE + => array(324.00, 747.00), // (4.5 in. by 10.375 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_NO12_ENVELOPE + => array(342.00, 792.00), // (4.75 in. by 11 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_NO14_ENVELOPE + => array(360.00, 828.00), // (5 in. by 11.5 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_C + => array(1224.00, 1584.00), // (17 in. by 22 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_D + => array(1584.00, 2448.00), // (22 in. by 34 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_E + => array(2448.00, 3168.00), // (34 in. by 44 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_DL_ENVELOPE + => array(311.81, 623.62), // (110 mm by 220 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_C5_ENVELOPE + => 'C5', // (162 mm by 229 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_C3_ENVELOPE + => 'C3', // (324 mm by 458 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_C4_ENVELOPE + => 'C4', // (229 mm by 324 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_C6_ENVELOPE + => 'C6', // (114 mm by 162 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_C65_ENVELOPE + => array(323.15, 649.13), // (114 mm by 229 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_B4_ENVELOPE + => 'B4', // (250 mm by 353 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_B5_ENVELOPE + => 'B5', // (176 mm by 250 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_B6_ENVELOPE + => array(498.90, 354.33), // (176 mm by 125 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_ITALY_ENVELOPE + => array(311.81, 651.97), // (110 mm by 230 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_MONARCH_ENVELOPE + => array(279.00, 540.00), // (3.875 in. by 7.5 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_6_3_4_ENVELOPE + => array(261.00, 468.00), // (3.625 in. by 6.5 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_US_STANDARD_FANFOLD + => array(1071.00, 792.00), // (14.875 in. by 11 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_GERMAN_STANDARD_FANFOLD + => array(612.00, 864.00), // (8.5 in. by 12 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_GERMAN_LEGAL_FANFOLD + => 'FOLIO', // (8.5 in. by 13 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_ISO_B4 + => 'B4', // (250 mm by 353 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_JAPANESE_DOUBLE_POSTCARD + => array(566.93, 419.53), // (200 mm by 148 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_STANDARD_PAPER_1 + => array(648.00, 792.00), // (9 in. by 11 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_STANDARD_PAPER_2 + => array(720.00, 792.00), // (10 in. by 11 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_STANDARD_PAPER_3 + => array(1080.00, 792.00), // (15 in. by 11 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_INVITE_ENVELOPE + => array(623.62, 623.62), // (220 mm by 220 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER_EXTRA_PAPER + => array(667.80, 864.00), // (9.275 in. by 12 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_LEGAL_EXTRA_PAPER + => array(667.80, 1080.00), // (9.275 in. by 15 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_TABLOID_EXTRA_PAPER + => array(841.68, 1296.00), // (11.69 in. by 18 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4_EXTRA_PAPER + => array(668.98, 912.76), // (236 mm by 322 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER_TRANSVERSE_PAPER + => array(595.80, 792.00), // (8.275 in. by 11 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4_TRANSVERSE_PAPER + => 'A4', // (210 mm by 297 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER_EXTRA_TRANSVERSE_PAPER + => array(667.80, 864.00), // (9.275 in. by 12 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_SUPERA_SUPERA_A4_PAPER + => array(643.46, 1009.13), // (227 mm by 356 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_SUPERB_SUPERB_A3_PAPER + => array(864.57, 1380.47), // (305 mm by 487 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER_PLUS_PAPER + => array(612.00, 913.68), // (8.5 in. by 12.69 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4_PLUS_PAPER + => array(595.28, 935.43), // (210 mm by 330 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A5_TRANSVERSE_PAPER + => 'A5', // (148 mm by 210 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_JIS_B5_TRANSVERSE_PAPER + => array(515.91, 728.50), // (182 mm by 257 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A3_EXTRA_PAPER + => array(912.76, 1261.42), // (322 mm by 445 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A5_EXTRA_PAPER + => array(493.23, 666.14), // (174 mm by 235 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_ISO_B5_EXTRA_PAPER + => array(569.76, 782.36), // (201 mm by 276 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A2_PAPER + => 'A2', // (420 mm by 594 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A3_TRANSVERSE_PAPER + => 'A3', // (297 mm by 420 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A3_EXTRA_TRANSVERSE_PAPER + => array(912.76, 1261.42) // (322 mm by 445 mm) + ); + + /** + * Create a new PHPExcel_Writer_PDF + * + * @param PHPExcel $phpExcel PHPExcel object + */ + public function __construct(PHPExcel $phpExcel) + { + parent::__construct($phpExcel); + $this->setUseInlineCss(TRUE); + $this->_tempDir = PHPExcel_Shared_File::sys_get_temp_dir(); } /** - * Set Paper Size + * Get Font * - * @param int $pValue - * @return PHPExcel_Writer_PDF + * @return string */ - public function setPaperSize($pValue = PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER) { - $this->_paperSize = $pValue; - return $this; + public function getFont() + { + return $this->_font; } /** - * Get Orientation + * Set font. Examples: + * 'arialunicid0-chinese-simplified' + * 'arialunicid0-chinese-traditional' + * 'arialunicid0-korean' + * 'arialunicid0-japanese' * - * @return string + * @param string $fontName */ - public function getOrientation() { - return $this->_orientation; + public function setFont($fontName) + { + $this->_font = $fontName; + return $this; } /** - * Set Orientation + * Get Paper Size * - * @param string $pValue - * @return PHPExcel_Writer_PDF + * @return int */ - public function setOrientation($pValue = PHPExcel_Worksheet_PageSetup::ORIENTATION_DEFAULT) { - $this->_orientation = $pValue; - return $this; + public function getPaperSize() + { + return $this->_paperSize; } - /** - * Get temporary storage directory - * - * @return string - */ - public function getTempDir() { - return $this->_tempDir; - } + /** + * Set Paper Size + * + * @param string $pValue Paper size + * @return PHPExcel_Writer_PDF + */ + public function setPaperSize($pValue = PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER) + { + $this->_paperSize = $pValue; + return $this; + } + + /** + * Get Orientation + * + * @return string + */ + public function getOrientation() + { + return $this->_orientation; + } + + /** + * Set Orientation + * + * @param string $pValue Page orientation + * @return PHPExcel_Writer_PDF + */ + public function setOrientation($pValue = PHPExcel_Worksheet_PageSetup::ORIENTATION_DEFAULT) + { + $this->_orientation = $pValue; + return $this; + } + + /** + * Get temporary storage directory + * + * @return string + */ + public function getTempDir() + { + return $this->_tempDir; + } + + /** + * Set temporary storage directory + * + * @param string $pValue Temporary storage directory + * @throws PHPExcel_Writer_Exception when directory does not exist + * @return PHPExcel_Writer_PDF + */ + public function setTempDir($pValue = '') + { + if (is_dir($pValue)) { + $this->_tempDir = $pValue; + } else { + throw new PHPExcel_Writer_Exception("Directory does not exist: $pValue"); + } + return $this; + } + + /** + * Save PHPExcel to PDF file, pre-save + * + * @param string $pFilename Name of the file to save as + * @throws PHPExcel_Writer_Exception + */ + protected function prepareForSave($pFilename = NULL) + { + // garbage collect + $this->_phpExcel->garbageCollect(); + + $this->_saveArrayReturnType = PHPExcel_Calculation::getArrayReturnType(); + PHPExcel_Calculation::setArrayReturnType(PHPExcel_Calculation::RETURN_ARRAY_AS_VALUE); + + // Open file + $fileHandle = fopen($pFilename, 'w'); + if ($fileHandle === FALSE) { + throw new PHPExcel_Writer_Exception("Could not open file $pFilename for writing."); + } + + // Set PDF + $this->_isPdf = TRUE; + // Build CSS + $this->buildCSS(TRUE); + + return $fileHandle; + } + + /** + * Save PHPExcel to PDF file, post-save + * + * @param resource $fileHandle + * @throws PHPExcel_Writer_Exception + */ + protected function restoreStateAfterSave($fileHandle) + { + // Close file + fclose($fileHandle); + + PHPExcel_Calculation::setArrayReturnType($this->_saveArrayReturnType); + } - /** - * Set temporary storage directory - * - * @param string $pValue Temporary storage directory - * @throws Exception Exception when directory does not exist - * @return PHPExcel_Writer_PDF - */ - public function setTempDir($pValue = '') { - if (is_dir($pValue)) { - $this->_tempDir = $pValue; - } else { - throw new Exception("Directory does not exist: $pValue"); - } - return $this; - } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/PDF/DomPDF.php b/htdocs/includes/phpexcel/PHPExcel/Writer/PDF/DomPDF.php index a8ab4efd945..111dd36078c 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/PDF/DomPDF.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/PDF/DomPDF.php @@ -1,128 +1,120 @@ _phpExcel->garbageCollect(); + /** + * Save PHPExcel to file + * + * @param string $pFilename Name of the file to save as + * @throws PHPExcel_Writer_Exception + */ + public function save($pFilename = NULL) + { + $fileHandle = parent::prepareForSave($pFilename); - $saveArrayReturnType = PHPExcel_Calculation::getArrayReturnType(); - PHPExcel_Calculation::setArrayReturnType(PHPExcel_Calculation::RETURN_ARRAY_AS_VALUE); + // Default PDF paper size + $paperSize = 'LETTER'; // Letter (8.5 in. by 11 in.) - // Open file - $fileHandle = fopen($pFilename, 'w'); - if ($fileHandle === false) { - throw new Exception("Could not open file $pFilename for writing."); - } + // Check for paper size and page orientation + if (is_null($this->getSheetIndex())) { + $orientation = ($this->_phpExcel->getSheet(0)->getPageSetup()->getOrientation() + == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) + ? 'L' + : 'P'; + $printPaperSize = $this->_phpExcel->getSheet(0)->getPageSetup()->getPaperSize(); + $printMargins = $this->_phpExcel->getSheet(0)->getPageMargins(); + } else { + $orientation = ($this->_phpExcel->getSheet($this->getSheetIndex())->getPageSetup()->getOrientation() + == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) + ? 'L' + : 'P'; + $printPaperSize = $this->_phpExcel->getSheet($this->getSheetIndex())->getPageSetup()->getPaperSize(); + $printMargins = $this->_phpExcel->getSheet($this->getSheetIndex())->getPageMargins(); + } - // Set PDF - $this->_isPdf = true; - // Build CSS - $this->buildCSS(true); + // Override Page Orientation + if (!is_null($this->getOrientation())) { + $orientation = ($this->getOrientation() == PHPExcel_Worksheet_PageSetup::ORIENTATION_DEFAULT) + ? PHPExcel_Worksheet_PageSetup::ORIENTATION_PORTRAIT + : $this->getOrientation(); + } + // Override Paper Size + if (!is_null($this->getPaperSize())) { + $printPaperSize = $this->getPaperSize(); + } - // Default PDF paper size - $paperSize = 'LETTER'; // Letter (8.5 in. by 11 in.) + if (isset(self::$_paperSizes[$printPaperSize])) { + $paperSize = self::$_paperSizes[$printPaperSize]; + } - // Check for paper size and page orientation - if (is_null($this->getSheetIndex())) { - $orientation = ($this->_phpExcel->getSheet(0)->getPageSetup()->getOrientation() == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) ? 'L' : 'P'; - $printPaperSize = $this->_phpExcel->getSheet(0)->getPageSetup()->getPaperSize(); - $printMargins = $this->_phpExcel->getSheet(0)->getPageMargins(); - } else { - $orientation = ($this->_phpExcel->getSheet($this->getSheetIndex())->getPageSetup()->getOrientation() == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) ? 'L' : 'P'; - $printPaperSize = $this->_phpExcel->getSheet($this->getSheetIndex())->getPageSetup()->getPaperSize(); - $printMargins = $this->_phpExcel->getSheet($this->getSheetIndex())->getPageMargins(); - } + $orientation = ($orientation == 'L') ? 'landscape' : 'portrait'; - // Override Page Orientation - if (!is_null($this->getOrientation())) { - $orientation = ($this->getOrientation() == PHPExcel_Worksheet_PageSetup::ORIENTATION_DEFAULT) ? - PHPExcel_Worksheet_PageSetup::ORIENTATION_PORTRAIT : $this->getOrientation(); - } - // Override Paper Size - if (!is_null($this->getPaperSize())) { - $printPaperSize = $this->getPaperSize(); - } + // Create PDF + $pdf = new DOMPDF(); + $pdf->set_paper(strtolower($paperSize), $orientation); - if (isset(self::$_paperSizes[$printPaperSize])) { - $paperSize = self::$_paperSizes[$printPaperSize]; - } + $pdf->load_html( + $this->generateHTMLHeader(FALSE) . + $this->generateSheetData() . + $this->generateHTMLFooter() + ); + $pdf->render(); - $orientation = ($orientation == 'L') ? 'landscape' : 'portrait'; + // Write to file + fwrite($fileHandle, $pdf->output()); - // Create PDF - $pdf = new DOMPDF(); - $pdf->set_paper(strtolower($paperSize), $orientation); - - $pdf->load_html( - $this->generateHTMLHeader(false) . - $this->generateSheetData() . - $this->generateHTMLFooter() - ); - $pdf->render(); - - // Write to file - fwrite($fileHandle, $pdf->output()); - - // Close file - fclose($fileHandle); - - PHPExcel_Calculation::setArrayReturnType($saveArrayReturnType); - } + parent::restoreStateAfterSave($fileHandle); + } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/PDF/mPDF.php b/htdocs/includes/phpexcel/PHPExcel/Writer/PDF/mPDF.php index 5f9f2a350fc..8e274f4ce79 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/PDF/mPDF.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/PDF/mPDF.php @@ -1,135 +1,130 @@ _phpExcel->garbageCollect(); + /** + * Save PHPExcel to file + * + * @param string $pFilename Name of the file to save as + * @throws PHPExcel_Writer_Exception + */ + public function save($pFilename = NULL) + { + $fileHandle = parent::prepareForSave($pFilename); - $saveArrayReturnType = PHPExcel_Calculation::getArrayReturnType(); - PHPExcel_Calculation::setArrayReturnType(PHPExcel_Calculation::RETURN_ARRAY_AS_VALUE); + // Default PDF paper size + $paperSize = 'LETTER'; // Letter (8.5 in. by 11 in.) - // Open file - $fileHandle = fopen($pFilename, 'w'); - if ($fileHandle === false) { - throw new Exception("Could not open file $pFilename for writing."); - } + // Check for paper size and page orientation + if (is_null($this->getSheetIndex())) { + $orientation = ($this->_phpExcel->getSheet(0)->getPageSetup()->getOrientation() + == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) + ? 'L' + : 'P'; + $printPaperSize = $this->_phpExcel->getSheet(0)->getPageSetup()->getPaperSize(); + $printMargins = $this->_phpExcel->getSheet(0)->getPageMargins(); + } else { + $orientation = ($this->_phpExcel->getSheet($this->getSheetIndex())->getPageSetup()->getOrientation() + == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) + ? 'L' + : 'P'; + $printPaperSize = $this->_phpExcel->getSheet($this->getSheetIndex())->getPageSetup()->getPaperSize(); + $printMargins = $this->_phpExcel->getSheet($this->getSheetIndex())->getPageMargins(); + } + $this->setOrientation($orientation); - // Set PDF - $this->_isPdf = true; - // Build CSS - $this->buildCSS(true); + // Override Page Orientation + if (!is_null($this->getOrientation())) { + $orientation = ($this->getOrientation() == PHPExcel_Worksheet_PageSetup::ORIENTATION_DEFAULT) + ? PHPExcel_Worksheet_PageSetup::ORIENTATION_PORTRAIT + : $this->getOrientation(); + } + $orientation = strtoupper($orientation); - // Default PDF paper size - $paperSize = 'LETTER'; // Letter (8.5 in. by 11 in.) + // Override Paper Size + if (!is_null($this->getPaperSize())) { + $printPaperSize = $this->getPaperSize(); + } - // Check for paper size and page orientation - if (is_null($this->getSheetIndex())) { - $orientation = ($this->_phpExcel->getSheet(0)->getPageSetup()->getOrientation() == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) ? 'L' : 'P'; - $printPaperSize = $this->_phpExcel->getSheet(0)->getPageSetup()->getPaperSize(); - $printMargins = $this->_phpExcel->getSheet(0)->getPageMargins(); - } else { - $orientation = ($this->_phpExcel->getSheet($this->getSheetIndex())->getPageSetup()->getOrientation() == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) ? 'L' : 'P'; - $printPaperSize = $this->_phpExcel->getSheet($this->getSheetIndex())->getPageSetup()->getPaperSize(); - $printMargins = $this->_phpExcel->getSheet($this->getSheetIndex())->getPageMargins(); - } - $this->setOrientation($orientation); + if (isset(self::$_paperSizes[$printPaperSize])) { + $paperSize = self::$_paperSizes[$printPaperSize]; + } - // Override Page Orientation - if (!is_null($this->getOrientation())) { - $orientation = ($this->getOrientation() == PHPExcel_Worksheet_PageSetup::ORIENTATION_DEFAULT) ? - PHPExcel_Worksheet_PageSetup::ORIENTATION_PORTRAIT : $this->getOrientation(); - } - $orientation = strtoupper($orientation); - - // Override Paper Size - if (!is_null($this->getPaperSize())) { - $printPaperSize = $this->getPaperSize(); - } - - if (isset(self::$_paperSizes[$printPaperSize])) { - $paperSize = self::$_paperSizes[$printPaperSize]; - } - - // Create PDF - $pdf = new mpdf(); - $pdf->_setPageSize(strtoupper($paperSize), $orientation); + // Create PDF + $pdf = new mpdf(); + $ortmp = $orientation; + $pdf->_setPageSize(strtoupper($paperSize), $ortmp); $pdf->DefOrientation = $orientation; - // Document info - $pdf->SetTitle($this->_phpExcel->getProperties()->getTitle()); - $pdf->SetAuthor($this->_phpExcel->getProperties()->getCreator()); - $pdf->SetSubject($this->_phpExcel->getProperties()->getSubject()); - $pdf->SetKeywords($this->_phpExcel->getProperties()->getKeywords()); - $pdf->SetCreator($this->_phpExcel->getProperties()->getCreator()); + $pdf->AddPage($orientation); - $pdf->WriteHTML( - $this->generateHTMLHeader(false) . - $this->generateSheetData() . - $this->generateHTMLFooter() - ); + // Document info + $pdf->SetTitle($this->_phpExcel->getProperties()->getTitle()); + $pdf->SetAuthor($this->_phpExcel->getProperties()->getCreator()); + $pdf->SetSubject($this->_phpExcel->getProperties()->getSubject()); + $pdf->SetKeywords($this->_phpExcel->getProperties()->getKeywords()); + $pdf->SetCreator($this->_phpExcel->getProperties()->getCreator()); - // Write to file - fwrite($fileHandle, $pdf->Output('','S')); + $pdf->WriteHTML( + $this->generateHTMLHeader(FALSE) . + $this->generateSheetData() . + $this->generateHTMLFooter() + ); - // Close file - fclose($fileHandle); + // Write to file + fwrite($fileHandle, $pdf->Output('', 'S')); - PHPExcel_Calculation::setArrayReturnType($saveArrayReturnType); - } + parent::restoreStateAfterSave($fileHandle); + } } diff --git a/htdocs/includes/phpexcel/PHPExcel/Writer/PDF/tcPDF.php b/htdocs/includes/phpexcel/PHPExcel/Writer/PDF/tcPDF.php index d77ab91a9fc..c3809ec750c 100644 --- a/htdocs/includes/phpexcel/PHPExcel/Writer/PDF/tcPDF.php +++ b/htdocs/includes/phpexcel/PHPExcel/Writer/PDF/tcPDF.php @@ -1,147 +1,136 @@ _phpExcel->garbageCollect(); + /** + * Save PHPExcel to file + * + * @param string $pFilename Name of the file to save as + * @throws PHPExcel_Writer_Exception + */ + public function save($pFilename = NULL) + { + $fileHandle = parent::prepareForSave($pFilename); - $saveArrayReturnType = PHPExcel_Calculation::getArrayReturnType(); - PHPExcel_Calculation::setArrayReturnType(PHPExcel_Calculation::RETURN_ARRAY_AS_VALUE); + // Default PDF paper size + $paperSize = 'LETTER'; // Letter (8.5 in. by 11 in.) - // Open file - $fileHandle = fopen($pFilename, 'w'); - if ($fileHandle === false) { - throw new Exception("Could not open file $pFilename for writing."); - } + // Check for paper size and page orientation + if (is_null($this->getSheetIndex())) { + $orientation = ($this->_phpExcel->getSheet(0)->getPageSetup()->getOrientation() + == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) + ? 'L' + : 'P'; + $printPaperSize = $this->_phpExcel->getSheet(0)->getPageSetup()->getPaperSize(); + $printMargins = $this->_phpExcel->getSheet(0)->getPageMargins(); + } else { + $orientation = ($this->_phpExcel->getSheet($this->getSheetIndex())->getPageSetup()->getOrientation() + == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) + ? 'L' + : 'P'; + $printPaperSize = $this->_phpExcel->getSheet($this->getSheetIndex())->getPageSetup()->getPaperSize(); + $printMargins = $this->_phpExcel->getSheet($this->getSheetIndex())->getPageMargins(); + } - // Set PDF - $this->_isPdf = true; - // Build CSS - $this->buildCSS(true); + // Override Page Orientation + if (!is_null($this->getOrientation())) { + $orientation = ($this->getOrientation() == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) + ? 'L' + : 'P'; + } + // Override Paper Size + if (!is_null($this->getPaperSize())) { + $printPaperSize = $this->getPaperSize(); + } - // Default PDF paper size - $paperSize = 'LETTER'; // Letter (8.5 in. by 11 in.) - - // Check for paper size and page orientation - if (is_null($this->getSheetIndex())) { - $orientation = ($this->_phpExcel->getSheet(0)->getPageSetup()->getOrientation() == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) ? 'L' : 'P'; - $printPaperSize = $this->_phpExcel->getSheet(0)->getPageSetup()->getPaperSize(); - $printMargins = $this->_phpExcel->getSheet(0)->getPageMargins(); - } else { - $orientation = ($this->_phpExcel->getSheet($this->getSheetIndex())->getPageSetup()->getOrientation() == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) ? 'L' : 'P'; - $printPaperSize = $this->_phpExcel->getSheet($this->getSheetIndex())->getPageSetup()->getPaperSize(); - $printMargins = $this->_phpExcel->getSheet($this->getSheetIndex())->getPageMargins(); - } - - // Override Page Orientation - if (!is_null($this->getOrientation())) { - $orientation = ($this->getOrientation() == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) ? - 'L' : 'P'; - } - // Override Paper Size - if (!is_null($this->getPaperSize())) { - $printPaperSize = $this->getPaperSize(); - } + if (isset(self::$_paperSizes[$printPaperSize])) { + $paperSize = self::$_paperSizes[$printPaperSize]; + } - if (isset(self::$_paperSizes[$printPaperSize])) { - $paperSize = self::$_paperSizes[$printPaperSize]; - } + // Create PDF + $pdf = new TCPDF($orientation, 'pt', $paperSize); + $pdf->setFontSubsetting(FALSE); + // Set margins, converting inches to points (using 72 dpi) + $pdf->SetMargins($printMargins->getLeft() * 72, $printMargins->getTop() * 72, $printMargins->getRight() * 72); + $pdf->SetAutoPageBreak(TRUE, $printMargins->getBottom() * 72); + $pdf->setPrintHeader(FALSE); + $pdf->setPrintFooter(FALSE); - // Create PDF - $pdf = new TCPDF($orientation, 'pt', $paperSize); - $pdf->setFontSubsetting(false); - // Set margins, converting inches to points (using 72 dpi) - $pdf->SetMargins($printMargins->getLeft() * 72,$printMargins->getTop() * 72,$printMargins->getRight() * 72); - $pdf->SetAutoPageBreak(true,$printMargins->getBottom() * 72); -// $pdf->setHeaderMargin($printMargins->getHeader() * 72); -// $pdf->setFooterMargin($printMargins->getFooter() * 72); + $pdf->AddPage(); - $pdf->setPrintHeader(false); - $pdf->setPrintFooter(false); + // Set the appropriate font + $pdf->SetFont($this->getFont()); + $pdf->writeHTML( + $this->generateHTMLHeader(FALSE) . + $this->generateSheetData() . + $this->generateHTMLFooter() + ); - $pdf->AddPage(); + // Document info + $pdf->SetTitle($this->_phpExcel->getProperties()->getTitle()); + $pdf->SetAuthor($this->_phpExcel->getProperties()->getCreator()); + $pdf->SetSubject($this->_phpExcel->getProperties()->getSubject()); + $pdf->SetKeywords($this->_phpExcel->getProperties()->getKeywords()); + $pdf->SetCreator($this->_phpExcel->getProperties()->getCreator()); - // Set the appropriate font - $pdf->SetFont($this->getFont()); - $pdf->writeHTML( - $this->generateHTMLHeader(false) . - $this->generateSheetData() . - $this->generateHTMLFooter() - ); + // Write to file + fwrite($fileHandle, $pdf->output($pFilename, 'S')); - // Document info - $pdf->SetTitle($this->_phpExcel->getProperties()->getTitle()); - $pdf->SetAuthor($this->_phpExcel->getProperties()->getCreator()); - $pdf->SetSubject($this->_phpExcel->getProperties()->getSubject()); - $pdf->SetKeywords($this->_phpExcel->getProperties()->getKeywords()); - $pdf->SetCreator($this->_phpExcel->getProperties()->getCreator()); - - // Write to file - fwrite($fileHandle, $pdf->output($pFilename, 'S')); - - // Close file - fclose($fileHandle); - - PHPExcel_Calculation::setArrayReturnType($saveArrayReturnType); - } + parent::restoreStateAfterSave($fileHandle); + } } diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/bg/config b/htdocs/includes/phpexcel/PHPExcel/locale/bg/config new file mode 100644 index 00000000000..d7ecb2b2ab1 --- /dev/null +++ b/htdocs/includes/phpexcel/PHPExcel/locale/bg/config @@ -0,0 +1,49 @@ +## +## PHPExcel +## + +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Settings +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.8.0, 2014-03-02 +## +## + + +ArgumentSeparator = ; + + +## +## (For future use) +## +currencySymbol = лв + + +## +## Excel Error Codes (For future use) + +## +NULL = #ПРАЗНО! +DIV0 = #ДЕЛ/0! +VALUE = #СТОЙНОСТ! +REF = #РЕФ! +NAME = #ИМЕ? +NUM = #ЧИСЛО! +NA = #Н/Д diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/cs/config b/htdocs/includes/phpexcel/PHPExcel/locale/cs/config index 38a44128e27..af4589b0955 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/cs/config +++ b/htdocs/includes/phpexcel/PHPExcel/locale/cs/config @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Settings -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/cs/functions b/htdocs/includes/phpexcel/PHPExcel/locale/cs/functions index 992dc37535e..f324759d247 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/cs/functions +++ b/htdocs/includes/phpexcel/PHPExcel/locale/cs/functions @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Calculation -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/da/config b/htdocs/includes/phpexcel/PHPExcel/locale/da/config index 49292f1cf67..1ddecb936f4 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/da/config +++ b/htdocs/includes/phpexcel/PHPExcel/locale/da/config @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Settings -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/da/functions b/htdocs/includes/phpexcel/PHPExcel/locale/da/functions index affc19a1ac2..102d57843e7 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/da/functions +++ b/htdocs/includes/phpexcel/PHPExcel/locale/da/functions @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Calculation -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/de/config b/htdocs/includes/phpexcel/PHPExcel/locale/de/config index 95193498fe6..c9972751661 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/de/config +++ b/htdocs/includes/phpexcel/PHPExcel/locale/de/config @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Settings -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/de/functions b/htdocs/includes/phpexcel/PHPExcel/locale/de/functions index 1c19c5b22ce..8ce08de4d5d 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/de/functions +++ b/htdocs/includes/phpexcel/PHPExcel/locale/de/functions @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Calculation -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/en/uk/config b/htdocs/includes/phpexcel/PHPExcel/locale/en/uk/config index 1bcfcb2b79c..dfcc63b0e8f 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/en/uk/config +++ b/htdocs/includes/phpexcel/PHPExcel/locale/en/uk/config @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Settings -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/es/config b/htdocs/includes/phpexcel/PHPExcel/locale/es/config index 039f5b8c877..0b11eb7af07 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/es/config +++ b/htdocs/includes/phpexcel/PHPExcel/locale/es/config @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Settings -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/es/functions b/htdocs/includes/phpexcel/PHPExcel/locale/es/functions index 9d47f0e491a..f6e6fd2b6b3 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/es/functions +++ b/htdocs/includes/phpexcel/PHPExcel/locale/es/functions @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Calculation -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/fi/config b/htdocs/includes/phpexcel/PHPExcel/locale/fi/config index ba274e1d5c2..380f39793d7 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/fi/config +++ b/htdocs/includes/phpexcel/PHPExcel/locale/fi/config @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Settings -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/fi/functions b/htdocs/includes/phpexcel/PHPExcel/locale/fi/functions index 25e08eacd35..bf60bec0012 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/fi/functions +++ b/htdocs/includes/phpexcel/PHPExcel/locale/fi/functions @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Calculation -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/fr/config b/htdocs/includes/phpexcel/PHPExcel/locale/fr/config index 8ae183a698a..368b3c3cc3d 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/fr/config +++ b/htdocs/includes/phpexcel/PHPExcel/locale/fr/config @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Settings -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/fr/functions b/htdocs/includes/phpexcel/PHPExcel/locale/fr/functions index ebb8339b6ac..e85dba5b89a 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/fr/functions +++ b/htdocs/includes/phpexcel/PHPExcel/locale/fr/functions @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Calculation -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/hu/config b/htdocs/includes/phpexcel/PHPExcel/locale/hu/config index 725b5698f2a..e04151cb8a7 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/hu/config +++ b/htdocs/includes/phpexcel/PHPExcel/locale/hu/config @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Settings -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/hu/functions b/htdocs/includes/phpexcel/PHPExcel/locale/hu/functions index a3855c066e5..77cae928e60 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/hu/functions +++ b/htdocs/includes/phpexcel/PHPExcel/locale/hu/functions @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Calculation -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/it/config b/htdocs/includes/phpexcel/PHPExcel/locale/it/config index 5baad5378d6..94499fe2767 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/it/config +++ b/htdocs/includes/phpexcel/PHPExcel/locale/it/config @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Settings -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/it/functions b/htdocs/includes/phpexcel/PHPExcel/locale/it/functions index 3d092048130..033b9696420 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/it/functions +++ b/htdocs/includes/phpexcel/PHPExcel/locale/it/functions @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Calculation -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/nl/config b/htdocs/includes/phpexcel/PHPExcel/locale/nl/config index d56b38fdbf7..00c1b0ff592 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/nl/config +++ b/htdocs/includes/phpexcel/PHPExcel/locale/nl/config @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Settings -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/nl/functions b/htdocs/includes/phpexcel/PHPExcel/locale/nl/functions index 6e941216d13..63800086167 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/nl/functions +++ b/htdocs/includes/phpexcel/PHPExcel/locale/nl/functions @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Calculation -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/no/config b/htdocs/includes/phpexcel/PHPExcel/locale/no/config index 482e4bc4464..5bf96a1b18a 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/no/config +++ b/htdocs/includes/phpexcel/PHPExcel/locale/no/config @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Settings -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/no/functions b/htdocs/includes/phpexcel/PHPExcel/locale/no/functions index eb5ae02dd27..917c7f7d79a 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/no/functions +++ b/htdocs/includes/phpexcel/PHPExcel/locale/no/functions @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Calculation -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/pl/config b/htdocs/includes/phpexcel/PHPExcel/locale/pl/config index 6823761e012..5061311c85d 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/pl/config +++ b/htdocs/includes/phpexcel/PHPExcel/locale/pl/config @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Settings -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/pl/functions b/htdocs/includes/phpexcel/PHPExcel/locale/pl/functions index 14858433784..14499c05926 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/pl/functions +++ b/htdocs/includes/phpexcel/PHPExcel/locale/pl/functions @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Calculation -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/pt/br/config b/htdocs/includes/phpexcel/PHPExcel/locale/pt/br/config index b8e696454aa..b4bf7041d22 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/pt/br/config +++ b/htdocs/includes/phpexcel/PHPExcel/locale/pt/br/config @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Settings -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/pt/br/functions b/htdocs/includes/phpexcel/PHPExcel/locale/pt/br/functions index 11d45f1fd77..a062a7fad51 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/pt/br/functions +++ b/htdocs/includes/phpexcel/PHPExcel/locale/pt/br/functions @@ -1,4 +1,4 @@ -## +## ## Add-in and Automation functions Funções Suplemento e Automação ## GETPIVOTDATA = INFODADOSTABELADINÂMICA ## Retorna os dados armazenados em um relatório de tabela dinâmica diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/pt/config b/htdocs/includes/phpexcel/PHPExcel/locale/pt/config index 595ee96835b..60b422bd4c7 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/pt/config +++ b/htdocs/includes/phpexcel/PHPExcel/locale/pt/config @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Settings -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/pt/functions b/htdocs/includes/phpexcel/PHPExcel/locale/pt/functions index 05e8bcaea7d..ba4eb471bad 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/pt/functions +++ b/htdocs/includes/phpexcel/PHPExcel/locale/pt/functions @@ -1,4 +1,4 @@ -## +## ## Add-in and Automation functions Funções de Suplemento e Automatização ## GETPIVOTDATA = OBTERDADOSDIN ## Devolve dados armazenados num relatório de Tabela Dinâmica diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/ru/config b/htdocs/includes/phpexcel/PHPExcel/locale/ru/config index aa7e685787b..6f6ace23116 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/ru/config +++ b/htdocs/includes/phpexcel/PHPExcel/locale/ru/config @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Settings -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/ru/functions b/htdocs/includes/phpexcel/PHPExcel/locale/ru/functions index f37afc2491c..bd636861950 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/ru/functions +++ b/htdocs/includes/phpexcel/PHPExcel/locale/ru/functions @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Calculation -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## Data in this file derived from information provided by web-junior (http://www.web-junior.net/) ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/sv/config b/htdocs/includes/phpexcel/PHPExcel/locale/sv/config index 6a597781650..5d1a9a9fbde 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/sv/config +++ b/htdocs/includes/phpexcel/PHPExcel/locale/sv/config @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Settings -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/sv/functions b/htdocs/includes/phpexcel/PHPExcel/locale/sv/functions index 27f61e7f834..73b2deb5eb2 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/sv/functions +++ b/htdocs/includes/phpexcel/PHPExcel/locale/sv/functions @@ -1,4 +1,4 @@ -## +## ## Add-in and Automation functions Tilläggs- och automatiseringsfunktioner ## GETPIVOTDATA = HÄMTA.PIVOTDATA ## Returnerar data som lagrats i en pivottabellrapport diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/tr/config b/htdocs/includes/phpexcel/PHPExcel/locale/tr/config index bd75af628ee..de69cf5872c 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/tr/config +++ b/htdocs/includes/phpexcel/PHPExcel/locale/tr/config @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Settings -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## diff --git a/htdocs/includes/phpexcel/PHPExcel/locale/tr/functions b/htdocs/includes/phpexcel/PHPExcel/locale/tr/functions index f8cd30fbd2e..c327bca4265 100644 --- a/htdocs/includes/phpexcel/PHPExcel/locale/tr/functions +++ b/htdocs/includes/phpexcel/PHPExcel/locale/tr/functions @@ -1,7 +1,7 @@ -## +## ## PHPExcel ## -## Copyright (c) 2006 - 2011 PHPExcel +## Copyright (c) 2006 - 2013 PHPExcel ## ## This library is free software; you can redistribute it and/or ## modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,9 @@ ## ## @category PHPExcel ## @package PHPExcel_Calculation -## @copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel) +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) ## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -## @version 1.7.8, 2012-10-12 +## @version 1.8.0, 2014-03-02 ## ## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ ## diff --git a/htdocs/includes/phpexcel/changelog.txt b/htdocs/includes/phpexcel/changelog.txt index 3040d3438ca..a87065ab886 100644 --- a/htdocs/includes/phpexcel/changelog.txt +++ b/htdocs/includes/phpexcel/changelog.txt @@ -1,7 +1,7 @@ ************************************************************************************** * PHPExcel * -* Copyright (c) 2006 - 2012 PHPExcel +* Copyright (c) 2006 - 2014 PHPExcel * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,61 +17,98 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * -* @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) +* @copyright Copyright (c) 2006 - 2014 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -* @version 1.7.8, 2012-10-12 +* @version 1.8.0, 2014-03-02 ************************************************************************************** --------------------------------------------------------------------------------- -BREAKING CHANGE! As part of the planned changes for handling array formulae in -workbooks, there are some changes that will affect the PHPExcel_Cell object -methods. - -The following methods are now deprecated, and will be removed in version 1.7.9: - getCalculatedValue() The getValue() method will return calculated - values for cells containing formulae instead. - setCalculatedValue() The cell value will always contain the result of a - any formula calculation. - setFormulaAttributes() Will now be determined by the arguments to the - setFormula() method. - getFormulaAttributes() This will be replaced by the getArrayFormulaRange() - method. - -The following methods will be added in version 1.7.9 - getFormula() Use to retrieve a cell formula, will return the cell - value if the cell doesn't contain a formula, or - is not part of an array formula range. - setFormula() Use to set a cell formula. It will still be possible - to set formulae using the setValue() and - setValueExplicit() methods. - calculate() Use to execute a formula calculation to update the - cell value. - isFormula() Use to determine if a cell contains a formula, or is - part of an array formula range or not. - isArrayFormula() Use to determine if a cell contains an array formula, - or is part of an array formula range or not. - getArrayFormulaRange() Use to retrieve an array formula range. - -The following methods will be changed in version 1.7.9 - setValue() The logic behind this will be modified to store - formula values in the new cell property structure, - but it will still perform the same function. - setValueExplicit() The logic behind this will be modified to store - formula values in the new cell property structure, - but it will still perform the same function. - getValue() Will no longer return a formula if the cell contains - a formula, but will return the calculated value - instead. For cells that don't contain a formula, - it will still return the stored value. - getDataType() Will return the datatype of the calculated value for - cells that contain formulae. - setDataType() Error handling will be added to prevent setting a - cell datatype to an inappropriate value. --------------------------------------------------------------------------------- +2014-03-02 (v1.8.0): +- Bugfix: (MBaker) Work item CP19830 - Undefined variable: fileHandle in CSV Reader +- Bugfix: (MBaker) Work item CP19968 - Out of memory in style/supervisor.php +- Bugfix: (MBaker) - Style error with merged cells in PDF Writer +- Bugfix: (MBaker) - Problem with cloning worksheets +- Bugfix: (tavoarcila) Work Item GH-259 - Bug fix reading Open Office files +- Bugfix: (MBaker) Work item CP20397 - Serious bug in absolute cell reference used in shared formula + Would also have affected insert/delete column/row +- Bugfix: (RomanSyroeshko) Work Item GH-267 - CHOOSE() returns "#VALUE!" if the 1st entry is chosen +- Bugfix: (Gemorroj) Work Item GH-268 - When duplicating styles, styles shifted by one column to the right + Fix also applied to duplicating conditional styles +- Bugfix: (IndrekHaav) Work Item GH-212 - Fix for formulae that reference a sheet whose name begins with a digit: + these were erroneously identified as numeric values, causing the parser to throw an undefined variable error. +- Bugfix: (IndrekHaav) Work Item CP16208 - Fixed undefined variable error due to $styleArray being used before it's initialised +- Bugfix: (PowerKiKi) Work Item GH-273 - ISTEXT() return wrong result if referencing an empty but formatted cell +- Bugfix: (PowerKiKi) Work Item GH-270/GH-31 - Binary comparison of strings are case insensitive +- Bugfix: (MBaker) Work Item GH-275 - Insert New Row/Column Before is not correctly updating formula references +- Bugfix: (MBaker) Work Item GH-257 - Passing an array of cells to _generateRow() in the HTML/PDF Writer causes caching problems with last cell in the range +- Bugfix: (MBaker) Work Item GH-193 - Fix to empty worksheet garbage collection when using cell caching +- Bugfix: (Jazzo) Work Item GH-248 - Excel2007 does not correctly mark rows as hidden +- Bugfix: (Roy Shahbazian) Work Item GH-299 - Fixed typo in Chart/Layout set/getYMode() +- Bugfix: (EliuFlorez) Work item GH-279 - Fatal error: Call to a member function cellExists() line: 3327 in calculation.php if referenced worksheet doesn't exist +- Bugfix: (MBaker) Work Item GH-290 - AdvancedValueBinder "Division by zero"-error +- Bugfix: (MBaker) Work Item CP20604 - Adding Sheet to Workbook Bug +- Bugfix: (MBaker) Work item CP20703 - Calculation engine incorrectly evaluates empty cells as #VALUE +- Bugfix: (MBaker) Work item CP20760 - Formula references to cell on another sheet in ODS files +- Bugfix: (MBaker) Work item GH321,GH158,CP17824 - LibreOffice created XLSX files results in an empty file. +- Feature: (amerov) - Implementation of the Excel HLOOKUP() function +- Feature: (MBaker) - Added "Quote Prefix" to style settings (Excel2007 Reader and Writer only) +- Feature: (MBaker) - Added Horizontal FILL alignment for Excel5 and Excel2007 Readers/Writers, and Horizontal DISTRIBUTED alignment for Excel2007 Reader/Writer +- Feature: (trvrnrth) Work Item GH-261 - Add support for reading protected (RC4 encrypted) .xls files +- Feature: (LWol) Work Item GH-252 - Adding support for macros, Ribbon in Excel 2007 +- General: (cdhutch) Work item CP20055 - Remove array_shift in ReferenceHelper::insertNewBefore improves column or row delete speed +- General: (MBaker) - Improve stock chart handling and rendering, with help from Swashata Ghosh +- General: (MBaker) - Fix to calculation properties for Excel2007 so that the opening application will only recalculate on load if it's actually required +- General: (MBaker) - Modified Excel2007 Writer to default preCalculateFormulas to false + Note that autosize columns will still recalculate affected formulae internally +- General: (dresenhista) Work Item GH-242 - Functionality to getHighestRow() for a specified column, and getHighestColumn() for a specified row +- General: (adamriyadi) Work Item GH-247 - Modify PHPExcel_Reader_Excel2007 to use zipClass from PHPExcel_Settings::getZipClass() + This allows the use of PCLZip when reading for people that don't have access to ZipArchive +- General: (infojunkie) Work Item GH-276 - Convert properties to string in OOCalc reader +- Security: (maartenba) Work Item GH-322 - Disable libxml external entity loading by default. + This is to prevent XML External Entity Processing (XXE) injection attacks (see http://websec.io/2012/08/27/Preventing-XEE-in-PHP.html for an explanation of XXE injection). + Reference CVE-2014-2054 -Fixed in develop branch: +2013-06-02 (v1.7.9): +- Feature: (MBaker) Include charts option for HTML Writer +- Feature: (MBaker) Added composer file +- Feature: (MBaker) Added getStyle() method to Cell object +- Bugfix: (Asker) Work item 18777 - Error in PHPEXCEL/Calculation.php script on line 2976 (stack pop check) +- Bugfix: (MBaker) Work item 18794 - CSV files without a file extension being identified as HTML +- Bugfix: (AndreKR) Work item GH-66 - Wrong check for maximum number of rows in Excel5 Writer +- Bugfix: (MBaker) Work item GH-67 - Cache directory for DiscISAM cache storage cannot be set +- Bugfix: (MBaker) Work item 17976 - Fix to Excel2007 Reader for hyperlinks with an anchor fragment (following a #), otherwise they were treated as sheet references +- Bugfix: (MBaker) Work item 18963 - getSheetNames() fails on numeric (floating point style) names with trailing zeroes +- Bugfix: (MBaker) Work item GH-130 - Single cell print area +- General: (kea) Work item GH-69 - Improved AdvancedValueBinder for currency +- General: (MBaker) Work items 17936 and 17840 - Fix for environments where there is no access to /tmp but to upload_tmp_dir + Provided an option to set the sys_get_temp_dir() call to use the upload_tmp_dir; though by default the standard temp directory will still be used +- General: (amironov ) Work item GH-84 - Search style by identity in PHPExcel_Worksheet::duplicateStyle() +- General: (karak) Work item GH-85 - Fill SheetView IO in Excel5 +- General: (cfhay) Work item 18958 - Memory and Speed improvements in PHPExcel_Reader_Excel5 +- General: (MBaker) Work item GH-78 - Modify listWorksheetNames() and listWorksheetInfo to use XMLReader with streamed XML rather than SimpleXML +- General: (dbonsch) Restructuring of PHPExcel Exceptions +- General: (MBaker) Work items 16926 and 15145 - Refactor Calculation Engine from singleton to a Multiton + Ensures that calculation cache is maintained independently for different workbooks +- General: (MBaker) Modify cell's getCalculatedValue() method to return the content of RichText objects rather than the RichText object itself +- Bugfix: (techhead) Work item GH-70 - Fixed formula/formatting bug when removing rows +- Bugfix: (alexgann) Work item GH-63 - Fix to cellExists for non-existent namedRanges +- Bugfix: (MBaker) Work item 18844 - cache_in_memory_gzip "eats" last worksheet line, cache_in_memory doesn't +- Feature: (Progi1984) Work item GH-22 - Sheet View in Excel5 Writer +- Bugfix: (amironov) Work item GH-82 - PHPExcel_Worksheet::getCellCollection() may not return last cached cell +- Bugfix: (teso) Work item 18551 - Rich Text containing UTF-8 characters creating unreadable content with Excel5 Writer +- Bugfix: (MBaker) Work item GH-104 - echo statements in HTML.php +- Feature: (Progi1984) Work item GH-8/CP11704 : Conditional formatting in Excel 5 Writer +- Bugfix: (MBaker) Work item GH-113 - canRead() Error for GoogleDocs ODS files: in ODS files from Google Docs there is no mimetype file +- Bugfix: (MBaker) Work item GH-80 - "Sheet index is out of bounds." Exception +- Bugfix: (ccorliss) Work item GH-105 - Fixed number format fatal error +- Bugfix: (MBaker) - Add DROP TABLE in destructor for SQLite and SQLite3 cache controllers +- Bugfix: (alexgann) Work item GH-154 - Fix merged-cell borders on HTML/PDF output +- Bugfix: (Shanto) Work item GH-161 - Fix: Hyperlinks break when removing rows +- Bugfix: (neclimdul) Work item GH-166 - Fix Extra Table Row From Images and Charts + + +2012-10-12 (v1.7.8): - Special: (kkamkou) Phar builder script to add phar file as a distribution option - Feature: (MBaker) Refactor PDF Writer to allow use with a choice of PDF Rendering library rather than restricting to tcPDF @@ -140,7 +177,7 @@ Fixed in develop branch: - General: (MBaker) Reduce cell caching overhead using dirty flag to ensure that cells are only rewritten to the cache if they have actually been changed - General: (MBaker) Improved memory usage in CSV Writer - General: (MBaker) Improved speed and memory usage in Excel5 Writer -- General: (MBaker) Experimental - +- General: (MBaker) Experimental - Added getHighestDataColumn(), getHighestDataRow(), getHighestRowAndColumn() and calculateWorksheetDataDimension() methods for the worksheet that return the highest row and column that have cell records - General: (MBaker) Change iterators to implement Iterator rather than extend CachingIterator, as a fix for PHP 5.4. changes in SPL - Bugfix: (MBaker) Work item 15459 - Invalid cell coordinate in Autofilter for Excel2007 Writer diff --git a/htdocs/includes/phpexcel/install.txt b/htdocs/includes/phpexcel/install.txt index e52bcda8ef3..3fa420222f5 100644 --- a/htdocs/includes/phpexcel/install.txt +++ b/htdocs/includes/phpexcel/install.txt @@ -7,19 +7,19 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. -* +* * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. -* +* * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * -* @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel) +* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL -* @version 1.7.8, 2012-10-12 +* @version 1.8.0, 2014-03-02 ************************************************************************************** Requirements @@ -59,16 +59,16 @@ Getting started --------------- A good way to get started is to run some of the tests included in the download. -Copy the "Tests" folder next to your "Classes" folder from above so you end up with: +Copy the "Examples" folder next to your "Classes" folder from above so you end up with: -/var/www/Tests/01simple.php -/var/www/Tests/02types.php +/var/www/Examples/01simple.php +/var/www/Examples/02types.php ... Start running the test by pointing your browser to the test scripts: -http://example.com/Tests/01simple.php -http://example.com/Tests/02types.php +http://example.com/Examples/01simple.php +http://example.com/Examples/02types.php ... Note: It may be necessary to modify the include/require statements at the beginning of From dec277f30fed206763dce16dbac5e689e1595000 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 20 Feb 2015 15:53:19 +0100 Subject: [PATCH 163/173] Accept h tags --- htdocs/theme/amarok/ckeditor/config.js | 18 ++++++++++-------- htdocs/theme/auguria/ckeditor/config.js | 14 ++++++++------ htdocs/theme/bureau2crea/ckeditor/config.js | 14 ++++++++------ htdocs/theme/cameleo/ckeditor/config.js | 15 +++++++++------ htdocs/theme/eldy/ckeditor/config.js | 6 +++--- 5 files changed, 38 insertions(+), 29 deletions(-) diff --git a/htdocs/theme/amarok/ckeditor/config.js b/htdocs/theme/amarok/ckeditor/config.js index 4243ac6e57e..97f1c0a0b62 100755 --- a/htdocs/theme/amarok/ckeditor/config.js +++ b/htdocs/theme/amarok/ckeditor/config.js @@ -24,8 +24,8 @@ CKEDITOR.editorConfig = function( config ) config.fullPage = false; // Not a full html page string, just part of it config.dialog_backgroundCoverColor = 'rgb(255, 254, 253)'; //config.contentsCss = '/css/mysitestyles.css'; - config.image_previewText=' '; - + config.image_previewText=' '; // Must no be empty + config.toolbar_Full = [ ['Source','-','Save','NewPage','Preview','-','Templates'], @@ -45,30 +45,33 @@ CKEDITOR.editorConfig = function( config ) ['Maximize', 'ShowBlocks','-','About'] ]; + // Used for mailing fields config.toolbar_dolibarr_mailings = [ ['Source','Maximize'], ['Cut','Copy','Paste','-','SpellChecker'], ['Undo','Redo','-','Find','Replace'], - ['Font','FontSize'], + ['Format','Font','FontSize'], ['Bold','Italic','Underline','Strike','Subscript','Superscript','-','TextColor','RemoveFormat'], - ['NumberedList','BulletedList','Outdent','Indent'], + ['NumberedList','BulletedList','Outdent','Indent','CreateDiv'], ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'], ['Link','Unlink','Anchor','Image','Table','HorizontalRule','SpecialChar'] ]; + // Used for notes fields config.toolbar_dolibarr_notes = [ - ['Source'], + ['Source','Maximize'], ['Cut','Copy','Paste','-','SpellChecker'], ['Undo','Redo','-','Find','Replace'], - ['Font','FontSize'], + ['Format','Font','FontSize'], ['Bold','Italic','Underline','Strike','Subscript','Superscript','-','TextColor','RemoveFormat'], ['NumberedList','BulletedList','Outdent','Indent'], ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'], ['Link','Unlink','Image','Table','HorizontalRule','SpecialChar'] ]; + // Used for details lines config.toolbar_dolibarr_details = [ ['Source','Maximize'], @@ -77,7 +80,7 @@ CKEDITOR.editorConfig = function( config ) ['Bold','Italic','Underline','Strike','Subscript','Superscript','-','TextColor','RemoveFormat'], ['NumberedList','BulletedList','Outdent','Indent'], ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'], - ['SpecialChar'] + ['Link','Unlink','SpecialChar'] ]; // Used for mailing fields @@ -86,5 +89,4 @@ CKEDITOR.editorConfig = function( config ) ['Source','Maximize'], ['Find'] ]; - }; diff --git a/htdocs/theme/auguria/ckeditor/config.js b/htdocs/theme/auguria/ckeditor/config.js index fd4a34b0453..97f1c0a0b62 100644 --- a/htdocs/theme/auguria/ckeditor/config.js +++ b/htdocs/theme/auguria/ckeditor/config.js @@ -24,8 +24,8 @@ CKEDITOR.editorConfig = function( config ) config.fullPage = false; // Not a full html page string, just part of it config.dialog_backgroundCoverColor = 'rgb(255, 254, 253)'; //config.contentsCss = '/css/mysitestyles.css'; - config.image_previewText=' '; - + config.image_previewText=' '; // Must no be empty + config.toolbar_Full = [ ['Source','-','Save','NewPage','Preview','-','Templates'], @@ -45,30 +45,33 @@ CKEDITOR.editorConfig = function( config ) ['Maximize', 'ShowBlocks','-','About'] ]; + // Used for mailing fields config.toolbar_dolibarr_mailings = [ ['Source','Maximize'], ['Cut','Copy','Paste','-','SpellChecker'], ['Undo','Redo','-','Find','Replace'], - ['Font','FontSize'], + ['Format','Font','FontSize'], ['Bold','Italic','Underline','Strike','Subscript','Superscript','-','TextColor','RemoveFormat'], ['NumberedList','BulletedList','Outdent','Indent','CreateDiv'], ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'], ['Link','Unlink','Anchor','Image','Table','HorizontalRule','SpecialChar'] ]; + // Used for notes fields config.toolbar_dolibarr_notes = [ - ['Source'], + ['Source','Maximize'], ['Cut','Copy','Paste','-','SpellChecker'], ['Undo','Redo','-','Find','Replace'], - ['Font','FontSize'], + ['Format','Font','FontSize'], ['Bold','Italic','Underline','Strike','Subscript','Superscript','-','TextColor','RemoveFormat'], ['NumberedList','BulletedList','Outdent','Indent'], ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'], ['Link','Unlink','Image','Table','HorizontalRule','SpecialChar'] ]; + // Used for details lines config.toolbar_dolibarr_details = [ ['Source','Maximize'], @@ -86,5 +89,4 @@ CKEDITOR.editorConfig = function( config ) ['Source','Maximize'], ['Find'] ]; - }; diff --git a/htdocs/theme/bureau2crea/ckeditor/config.js b/htdocs/theme/bureau2crea/ckeditor/config.js index fd4a34b0453..97f1c0a0b62 100644 --- a/htdocs/theme/bureau2crea/ckeditor/config.js +++ b/htdocs/theme/bureau2crea/ckeditor/config.js @@ -24,8 +24,8 @@ CKEDITOR.editorConfig = function( config ) config.fullPage = false; // Not a full html page string, just part of it config.dialog_backgroundCoverColor = 'rgb(255, 254, 253)'; //config.contentsCss = '/css/mysitestyles.css'; - config.image_previewText=' '; - + config.image_previewText=' '; // Must no be empty + config.toolbar_Full = [ ['Source','-','Save','NewPage','Preview','-','Templates'], @@ -45,30 +45,33 @@ CKEDITOR.editorConfig = function( config ) ['Maximize', 'ShowBlocks','-','About'] ]; + // Used for mailing fields config.toolbar_dolibarr_mailings = [ ['Source','Maximize'], ['Cut','Copy','Paste','-','SpellChecker'], ['Undo','Redo','-','Find','Replace'], - ['Font','FontSize'], + ['Format','Font','FontSize'], ['Bold','Italic','Underline','Strike','Subscript','Superscript','-','TextColor','RemoveFormat'], ['NumberedList','BulletedList','Outdent','Indent','CreateDiv'], ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'], ['Link','Unlink','Anchor','Image','Table','HorizontalRule','SpecialChar'] ]; + // Used for notes fields config.toolbar_dolibarr_notes = [ - ['Source'], + ['Source','Maximize'], ['Cut','Copy','Paste','-','SpellChecker'], ['Undo','Redo','-','Find','Replace'], - ['Font','FontSize'], + ['Format','Font','FontSize'], ['Bold','Italic','Underline','Strike','Subscript','Superscript','-','TextColor','RemoveFormat'], ['NumberedList','BulletedList','Outdent','Indent'], ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'], ['Link','Unlink','Image','Table','HorizontalRule','SpecialChar'] ]; + // Used for details lines config.toolbar_dolibarr_details = [ ['Source','Maximize'], @@ -86,5 +89,4 @@ CKEDITOR.editorConfig = function( config ) ['Source','Maximize'], ['Find'] ]; - }; diff --git a/htdocs/theme/cameleo/ckeditor/config.js b/htdocs/theme/cameleo/ckeditor/config.js index 99d5d33fc5d..97f1c0a0b62 100644 --- a/htdocs/theme/cameleo/ckeditor/config.js +++ b/htdocs/theme/cameleo/ckeditor/config.js @@ -25,7 +25,7 @@ CKEDITOR.editorConfig = function( config ) config.dialog_backgroundCoverColor = 'rgb(255, 254, 253)'; //config.contentsCss = '/css/mysitestyles.css'; config.image_previewText=' '; // Must no be empty - + config.toolbar_Full = [ ['Source','-','Save','NewPage','Preview','-','Templates'], @@ -45,30 +45,33 @@ CKEDITOR.editorConfig = function( config ) ['Maximize', 'ShowBlocks','-','About'] ]; + // Used for mailing fields config.toolbar_dolibarr_mailings = [ ['Source','Maximize'], ['Cut','Copy','Paste','-','SpellChecker'], ['Undo','Redo','-','Find','Replace'], - ['Font','FontSize'], + ['Format','Font','FontSize'], ['Bold','Italic','Underline','Strike','Subscript','Superscript','-','TextColor','RemoveFormat'], ['NumberedList','BulletedList','Outdent','Indent','CreateDiv'], ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'], - ['Link','Unlink','Anchor','Image','Table','SpecialChar'] + ['Link','Unlink','Anchor','Image','Table','HorizontalRule','SpecialChar'] ]; + // Used for notes fields config.toolbar_dolibarr_notes = [ - ['Source'], + ['Source','Maximize'], ['Cut','Copy','Paste','-','SpellChecker'], ['Undo','Redo','-','Find','Replace'], - ['Font','FontSize'], + ['Format','Font','FontSize'], ['Bold','Italic','Underline','Strike','Subscript','Superscript','-','TextColor','RemoveFormat'], ['NumberedList','BulletedList','Outdent','Indent'], ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'], - ['Link','Unlink','Image','Table','SpecialChar'] + ['Link','Unlink','Image','Table','HorizontalRule','SpecialChar'] ]; + // Used for details lines config.toolbar_dolibarr_details = [ ['Source','Maximize'], diff --git a/htdocs/theme/eldy/ckeditor/config.js b/htdocs/theme/eldy/ckeditor/config.js index 150b75dbd54..97f1c0a0b62 100644 --- a/htdocs/theme/eldy/ckeditor/config.js +++ b/htdocs/theme/eldy/ckeditor/config.js @@ -25,7 +25,7 @@ CKEDITOR.editorConfig = function( config ) config.dialog_backgroundCoverColor = 'rgb(255, 254, 253)'; //config.contentsCss = '/css/mysitestyles.css'; config.image_previewText=' '; // Must no be empty - + config.toolbar_Full = [ ['Source','-','Save','NewPage','Preview','-','Templates'], @@ -51,7 +51,7 @@ CKEDITOR.editorConfig = function( config ) ['Source','Maximize'], ['Cut','Copy','Paste','-','SpellChecker'], ['Undo','Redo','-','Find','Replace'], - ['Font','FontSize'], + ['Format','Font','FontSize'], ['Bold','Italic','Underline','Strike','Subscript','Superscript','-','TextColor','RemoveFormat'], ['NumberedList','BulletedList','Outdent','Indent','CreateDiv'], ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'], @@ -64,7 +64,7 @@ CKEDITOR.editorConfig = function( config ) ['Source','Maximize'], ['Cut','Copy','Paste','-','SpellChecker'], ['Undo','Redo','-','Find','Replace'], - ['Font','FontSize'], + ['Format','Font','FontSize'], ['Bold','Italic','Underline','Strike','Subscript','Superscript','-','TextColor','RemoveFormat'], ['NumberedList','BulletedList','Outdent','Indent'], ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'], From 49cb36461c3792756c32160384a89bc357cac422 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 20 Feb 2015 15:54:16 +0100 Subject: [PATCH 164/173] Typo --- htdocs/compta/prelevement/class/bonprelevement.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/prelevement/class/bonprelevement.class.php b/htdocs/compta/prelevement/class/bonprelevement.class.php index b543cac104a..aa1ba197d74 100644 --- a/htdocs/compta/prelevement/class/bonprelevement.class.php +++ b/htdocs/compta/prelevement/class/bonprelevement.class.php @@ -1629,7 +1629,7 @@ class BonPrelevement extends CommonObject * @param int $nombre 0 or 1 * @param float $total Total * @param string $CrLf End of line character - * @return string String with SEAP Sender + * @return string String with SEPA Sender */ function EnregEmetteurSEPA($configuration, $ladate, $nombre, $total, $CrLf='\n') { // SEPA INITIALISATION From ba80bbb29179d3d4c397687fe3b77607085a6a9c Mon Sep 17 00:00:00 2001 From: Sof Date: Fri, 20 Feb 2015 17:33:58 +0100 Subject: [PATCH 165/173] FIX; Unknown field 'sc.fk_soc' in field list --- htdocs/comm/prospect/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/comm/prospect/list.php b/htdocs/comm/prospect/list.php index 896168baa80..999c212a80d 100644 --- a/htdocs/comm/prospect/list.php +++ b/htdocs/comm/prospect/list.php @@ -197,7 +197,7 @@ $form=new Form($db); $sql = "SELECT s.rowid, s.nom as name, s.zip, s.town, s.datec, s.status as status, s.code_client, s.client,"; $sql.= " st.libelle as stcomm, s.prefix_comm, s.fk_stcomm, s.fk_prospectlevel,"; $sql.= " d.nom as departement"; -if ((!$user->rights->societe->client->voir && !$socid) || $search_sale) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) +if ((!$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) $sql .= " FROM ".MAIN_DB_PREFIX."c_stcomm as st"; $sql.= ", ".MAIN_DB_PREFIX."societe as s"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as d on (d.rowid = s.fk_departement)"; From d2da098336e9193f45561e9f301bcc9651266e74 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 21 Feb 2015 10:00:31 +0100 Subject: [PATCH 166/173] Fixed example --- htdocs/conf/conf.php.example | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/conf/conf.php.example b/htdocs/conf/conf.php.example index 681cecf1261..b94893a741a 100644 --- a/htdocs/conf/conf.php.example +++ b/htdocs/conf/conf.php.example @@ -204,7 +204,7 @@ $dolibarr_main_authentication='dolibarr'; //################## // dolibarr_main_force_https -// This parameter allows to force the HTTPS mode. +// This parameter allows to force the HTTPS mode. // 0 = No forced redirect // 1 = Force redirect to https, until SCRIPT_URI start with https into response // 2 = Force redirect to https, until SERVER["HTTPS"] is 'on' into response @@ -212,9 +212,9 @@ $dolibarr_main_authentication='dolibarr'; // Warning: If you enable this parameter, your web server must be configured to // respond URL with https protocol. // According to your web server setup, some values may works and other not. Try -// different values (1,2 or 'http://my.domain.com') if you experience problems. +// different values (1,2 or 'https://my.domain.com') if you experience problems. // Default value: 0 -// Possible values: 0, 1, 2 or 'http://my.domain.com' +// Possible values: 0, 1, 2 or 'https://my.domain.com' // Examples: // $dolibarr_main_force_https='0'; // From 070accd1e0f9001f6fec4f5aa77b53ab95cc8b6b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 21 Feb 2015 12:57:17 +0100 Subject: [PATCH 167/173] Work on new module expense report --- htdocs/core/class/commonobject.class.php | 7 +- htdocs/core/class/html.form.class.php | 2 +- htdocs/core/class/html.formfile.class.php | 5 +- htdocs/core/class/html.formprojet.class.php | 5 +- ...lacement.php => modules_expensereport.php} | 0 .../tpl/document_actions_post_headers.tpl.php | 3 +- htdocs/expensereport/card.php | 339 +++++++------ .../class/expensereport.class.php | 468 ++++++++---------- htdocs/expensereport/document.php | 8 +- .../mysql/tables/llx_expensereport.sql | 1 + .../mysql/tables/llx_expensereport_det.sql | 2 +- htdocs/langs/en_US/suppliers.lang | 2 +- htdocs/langs/en_US/trips.lang | 86 ++-- htdocs/langs/fr_FR/expensereport.lang | 137 ----- htdocs/projet/card.php | 2 +- htdocs/projet/class/project.class.php | 21 +- htdocs/theme/eldy/style.css.php | 9 + 17 files changed, 450 insertions(+), 647 deletions(-) rename htdocs/core/modules/expensereport/{modules_deplacement.php => modules_expensereport.php} (100%) delete mode 100755 htdocs/langs/fr_FR/expensereport.lang diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index aed2aa3b224..20f7859469d 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -2121,7 +2121,7 @@ abstract class CommonObject * * @param int $status Status to set * @param int $elementId Id of element to force (use this->id by default) - * @param string $elementType Type of element to force (use ->this->element by default) + * @param string $elementType Type of element to force (use this->table_element by default) * @return int <0 if KO, >0 if OK */ function setStatut($status,$elementId='',$elementType='') @@ -2135,9 +2135,12 @@ abstract class CommonObject $fieldstatus="fk_statut"; if ($elementTable == 'user') $fieldstatus="statut"; - + if ($elementTable == 'expensereport') $fieldstatus="fk_c_expensereport_statuts"; + $sql = "UPDATE ".MAIN_DB_PREFIX.$elementTable; $sql.= " SET ".$fieldstatus." = ".$status; + // If status = 1 = validated, update also fk_user_valid + if ($status == 1 && $elementTable == 'expensereport') $sql.=", fk_user_valid = ".$user->id; $sql.= " WHERE rowid=".$elementId; dol_syslog(get_class($this)."::setStatut", LOG_DEBUG); diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 53d04b8ab6a..6e6f39837d5 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -3042,7 +3042,7 @@ class Form if (! empty($more)) { $formconfirm.= '
'.$more.'
'; } - $formconfirm.= img_help('','').' '.$question; + $formconfirm.= ($question ? img_help('','').' '.$question : ''); $formconfirm.= ''."\n"; $formconfirm.= "\n\n"; diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index 274fa19a417..241c44cf5f8 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -273,7 +273,7 @@ class FormFile } $printer=0; - if (in_array($modulepart,array('facture','propal','proposal','order','commande','expedition'))) // This feature is implemented only for such elements + if (in_array($modulepart,array('facture','propal','proposal','order','commande','expedition'))) // The direct print feature is implemented only for such elements { $printer = (!empty($user->rights->printing->read) && !empty($conf->printing->enabled))?true:false; } @@ -440,7 +440,6 @@ class FormFile } else if ($modulepart != 'agenda') { - // For normalized standard modules $file=dol_buildpath('/core/modules/'.$modulepart.'/modules_'.$modulepart.'.php',0); if (file_exists($file)) @@ -449,7 +448,7 @@ class FormFile } // For normalized external modules else - { + { $file=dol_buildpath('/'.$modulepart.'/core/modules/'.$modulepart.'/modules_'.$modulepart.'.php',0); $res=include_once $file; } diff --git a/htdocs/core/class/html.formprojet.class.php b/htdocs/core/class/html.formprojet.class.php index e1487818438..86d46f3b9b5 100644 --- a/htdocs/core/class/html.formprojet.class.php +++ b/htdocs/core/class/html.formprojet.class.php @@ -86,6 +86,8 @@ class FormProjets $resql=$this->db->query($sql); if ($resql) { + $minmax=''; + // Use select2 selector $nodatarole=''; if (! empty($conf->use_javascript_ajax)) @@ -94,10 +96,11 @@ class FormProjets $comboenhancement = ajax_combobox($htmlname, '', 0, $forcefocus); $out.=$comboenhancement; $nodatarole=($comboenhancement?' data-role="none"':''); + $minmax='minwidth100 maxwidth300'; } if (empty($option_only)) { - $out.= ''; } if (!empty($show_empty)) { $out.= ''; diff --git a/htdocs/core/modules/expensereport/modules_deplacement.php b/htdocs/core/modules/expensereport/modules_expensereport.php similarity index 100% rename from htdocs/core/modules/expensereport/modules_deplacement.php rename to htdocs/core/modules/expensereport/modules_expensereport.php diff --git a/htdocs/core/tpl/document_actions_post_headers.tpl.php b/htdocs/core/tpl/document_actions_post_headers.tpl.php index d1a1cedca61..abd42296cde 100644 --- a/htdocs/core/tpl/document_actions_post_headers.tpl.php +++ b/htdocs/core/tpl/document_actions_post_headers.tpl.php @@ -20,6 +20,7 @@ $langs->load("link"); if (empty($relativepathwithnofile)) $relativepathwithnofile=''; + /* * Confirm form to delete */ @@ -46,7 +47,7 @@ $savingdocmask=''; if (empty($conf->global->MAIN_DISABLE_SUGGEST_REF_AS_PREFIX)) { //var_dump($modulepart); - if (in_array($modulepart,array('facture_fournisseur','commande_fournisseur','facture','commande','propal','ficheinter','contract','project','project_task'))) + if (in_array($modulepart,array('facture_fournisseur','commande_fournisseur','facture','commande','propal','ficheinter','contract','project','project_task','expensereport'))) { $savingdocmask=$object->ref.'___file__'; } diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index b555746c05b..871cbe22990 100755 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -32,6 +32,7 @@ require_once(DOL_DOCUMENT_ROOT."/core/class/html.formprojet.class.php"); require_once(DOL_DOCUMENT_ROOT."/projet/class/project.class.php"); require_once(DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'); require_once(DOL_DOCUMENT_ROOT."/core/lib/expensereport.lib.php"); +require_once(DOL_DOCUMENT_ROOT."/core/lib/price.lib.php"); dol_include_once('/expensereport/core/modules/expensereport/modules_expensereport.php'); dol_include_once("/expensereport/class/expensereport.class.php"); @@ -99,9 +100,9 @@ if ($action == 'add' && $user->rights->expensereport->creer) $object->date_debut = $date_start; $object->date_fin = $date_end; - $object->fk_user_validator = GETPOST('fk_user_validator','int'); $object->fk_c_expensereport_statuts = 1; $object->fk_c_paiement = GETPOST('fk_c_paiement','int'); + $object->fk_user_validator = GETPOST('fk_user_validator','int'); $object->note = GETPOST('note'); if ($object->periode_existe($user,dol_print_date($object->date_debut, 'dayrfc'),dol_print_date($object->date_fin, 'dayrfc'))) @@ -164,7 +165,7 @@ if ($action == "confirm_save" && GETPOST("confirm") == "yes" && $id > 0 && $user { $object = new ExpenseReport($db); $object->fetch($id); - $result = $object->set_save($user); + $result = $object->setValidate($user); if ($result > 0) { // Send mail @@ -234,7 +235,7 @@ if ($action == "confirm_save" && GETPOST("confirm") == "yes" && $id > 0 && $user } } -if ($action == "confirm_save_from_refuse" && $_GET["confirm"] == "yes" && $id > 0 && $user->rights->expensereport->creer) +if ($action == "confirm_save_from_refuse" && GETPOST("confirm") == "yes" && $id > 0 && $user->rights->expensereport->creer) { $object = new ExpenseReport($db); $object->fetch($id); @@ -315,7 +316,7 @@ if ($action == "confirm_validate" && GETPOST("confirm") == "yes" && $id > 0 && $ $object = new ExpenseReport($db); $object->fetch($id); - $result = $object->set_valide($user); + $result = $object->setApproved($user); if ($result > 0) { if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) @@ -393,12 +394,12 @@ if ($action == "confirm_validate" && GETPOST("confirm") == "yes" && $id > 0 && $ } } -if ($action == "confirm_refuse" && $_POST['confirm']=="yes" && !empty($_POST['detail_refuse']) && $id > 0 && $user->rights->expensereport->to_validate) +if ($action == "confirm_refuse" && GETPOST('confirm')=="yes" && $id > 0 && $user->rights->expensereport->to_validate) { $object = new ExpenseReport($db); $object->fetch($id); - - $result = $object->set_refuse($user,$_POST['detail_refuse']); + + $result = $object->set_refuse($user,GETPOST('detail_refuse')); if ($result > 0) { if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) @@ -454,35 +455,35 @@ if ($action == "confirm_refuse" && $_POST['confirm']=="yes" && !empty($_POST['de } } -if ($action == "confirm_cancel" && GETPOST('confirm')=="yes" && !empty($_POST['detail_cancel']) && $id > 0 && $user->rights->expensereport->to_validate) +//var_dump($user->id == $object->fk_user_validator);exit; +if ($action == "confirm_cancel" && GETPOST('confirm')=="yes" && !empty($_POST['detail_cancel']) && $id > 0 && $user->rights->expensereport->creer) { $object = new ExpenseReport($db); $object->fetch($id); - - if($user->id == $object->fk_user_validator) + + if ($user->id == $object->fk_user_valid || $user->id == $object->fk_user_author) { $result = $object->set_cancel($user,$_POST['detail_cancel']); - + if ($result > 0) { if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) { - // Send mail - + // TO $destinataire = new User($db); $destinataire->fetch($object->fk_user_author); $emailTo = $destinataire->email; - + // FROM $expediteur = new User($db); $expediteur->fetch($object->fk_user_cancel); $emailFrom = $expediteur->email; - + // SUBJECT $subject = "' ERP - Note de frais annulée"; - + // CONTENT $message = "Bonjour {$destinataire->firstname},\n\n"; $message.= "Votre note de frais \"{$object->ref}\" vient d'être annulée.\n"; @@ -490,10 +491,10 @@ if ($action == "confirm_cancel" && GETPOST('confirm')=="yes" && !empty($_POST['d $message.= "- Motif d'annulation : {$_POST['detail_cancel']}\n"; $message.= "- Lien : {$dolibarr_main_url_root}/expensereport/card.php?id={$object->id}\n\n"; $message.= "Bien cordialement,\n' SI"; - + // PREPARE SEND $mailfile = new CMailFile($subject,$emailTo,$emailFrom,$message); - + if(!$mailfile->error) { // SEND @@ -520,10 +521,6 @@ if ($action == "confirm_cancel" && GETPOST('confirm')=="yes" && !empty($_POST['d setEventMessages($object->error, $object->errors, 'errors'); } } - else - { - setEventMessages($langs->transnoentitiesnoconv("NOT_VALIDATOR"), '', 'errors'); - } } if ($action == "confirm_paid" && $_GET['confirm']=="yes" && $id > 0 && $user->rights->expensereport->to_paid) @@ -531,7 +528,7 @@ if ($action == "confirm_paid" && $_GET['confirm']=="yes" && $id > 0 && $user->ri $object = new ExpenseReport($db); $object->fetch($id,$user); - $result = $object->set_paid($user); + $result = $object->setPaid($user); if ($result > 0) { if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) @@ -622,13 +619,13 @@ if ($action == "confirm_paid" && $_GET['confirm']=="yes" && $id > 0 && $user->ri } } -if ($action == "confirm_brouillonner" && $_GET['confirm']=="yes" && $id > 0 && $user->rights->expensereport->creer) +if ($action == "confirm_brouillonner" && GETPOST('confirm')=="yes" && $id > 0 && $user->rights->expensereport->creer) { $object = new ExpenseReport($db); $object->fetch($id); - if($user->id == $object->fk_user_author OR $user->id == $object->fk_user_validator) + if ($user->id == $object->fk_user_author || $user->id == $object->fk_user_valid) { - $result = $object->set_draft($user); + $result = $object->setStatut(0); if ($result > 0) { header("Location: ".$_SEVER["PHP_SELF"]."?id=".$id); @@ -654,19 +651,21 @@ if ($action == "addline") $object_ligne = new ExpenseReportLine($db); $object_ligne->comments = GETPOST('comments'); - $object_ligne->qty = empty($_POST['qty'])?1:$_POST['qty']; + $qty = GETPOST('qty','int'); + if (empty($qty)) $qty=1; + $object_ligne->qty = $qty; - $object_ligne->value_unit = price2num(GETPOST('value_unit')); - $object_ligne->value_unit = price2num($object_ligne->value_unit,'MU'); + $up=price2num(GETPOST('value_unit'),'MU'); + $object_ligne->value_unit = $up; $object_ligne->date = $date; $object_ligne->fk_c_type_fees = GETPOST('fk_c_type_fees'); - $tva=GETPOST('vatrate'); - - $object_ligne->fk_c_tva = $tva; - + $vatrate=GETPOST('vatrate'); + $object_ligne->fk_c_tva = $vatrate; + $object_ligne->vatrate = $vatrate; + $object_ligne->fk_projet = $fk_projet; if (! GETPOST('fk_c_type_fees') > 0) @@ -682,7 +681,7 @@ if ($action == "addline") $action=''; } - // Si aucun projet n'est défini + /* Projects are never required. To force them, check module forceproject if ($conf->projet->enabled) { if (empty($object_ligne->fk_projet) || $object_ligne->fk_projet==-1) @@ -690,7 +689,7 @@ if ($action == "addline") $error++; setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("Project")), 'errors'); } - } + }*/ // Si aucune date n'est rentrée if (empty($object_ligne->date) || $object_ligne->date=="--") @@ -698,7 +697,6 @@ if ($action == "addline") $error++; setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("Date")), 'errors'); } - // Si aucun prix n'est rentré if($object_ligne->value_unit==0) { @@ -711,25 +709,19 @@ if ($action == "addline") { $object_ligne->fk_expensereport = $_POST['fk_expensereport']; - // Calculs des totos - $object_ligne->total_ttc = $object_ligne->value_unit * $object_ligne->qty; - $object_ligne->total_ttc = price2num($object_ligne->total_ttc,'MT'); + $type = 0; // TODO What if service + $tmp = calcul_price_total($qty, $up, 0, $vatrate, 0, 0, 0, 'TTC', 0, $type); + $object_ligne->total_ttc = $tmp[2]; $object_ligne->tva_taux = GETPOST('vatrate'); - - $tx_tva = $object_ligne->tva_taux / 100; - $tx_tva = $tx_tva + 1; - - $object_ligne->total_ht = $object_ligne->total_ttc / $tx_tva; - $object_ligne->total_ht = price2num($object_ligne->total_ht,'MT'); - - $object_ligne->total_tva = $object_ligne->total_ttc - $object_ligne->total_ht; + $object_ligne->total_ht = $tmp[0]; + $object_ligne->total_tva = $tmp[1]; $result = $object_ligne->insert(); if ($result > 0) { $db->commit(); - header("Location: ".$_SERVER["PHP_SELF"]."?id=".$_GET['id']); + header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id); exit; } else @@ -910,10 +902,7 @@ if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) } -/* - * Create - */ - +// Create if ($action == 'create') { print print_fiche_titre($langs->trans("NewTrip")); @@ -1002,11 +991,6 @@ else } $head = expensereport_prepare_head($object); - /* - $head[0][0] = $_SERVER['PHP_SELF'].'?id='.$object->id; - $head[0][1] = $langs->trans('Card'); - $head[0][2] = 'card'; - $h++;*/ if ($action == 'edit' && ($object->fk_c_expensereport_statuts < 3 || $object->fk_c_expensereport_statuts==99)) { @@ -1062,10 +1046,10 @@ else if($object->fk_c_expensereport_statuts<3) { print '
'; - print ''; + print ''; // Approbator print ''; print ''; @@ -1146,7 +1130,7 @@ else endif; if ($action == 'cancel'): - $array_input = array(array('type'=>"text",'label'=>"Entrez ci-dessous un motif d'annulation :",'name'=>"detail_cancel",'size'=>"50",'value'=>"")); + $array_input = array(array('type'=>"text",'label'=>$langs->trans("Comment"),'name'=>"detail_cancel",'size'=>"50",'value'=>"")); $ret=$form->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("ConfirmCancelTrip"),"","confirm_cancel",$array_input,"",0); if ($ret == 'html') print '
'; endif; @@ -1157,14 +1141,14 @@ else endif; if ($action == 'refuse'): - $array_input = array(array('type'=>"text",'label'=>"Entrez ci-dessous un motif de refus :",'name'=>"detail_refuse",'size'=>"50",'value'=>"")); - $ret=$form->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("ConfirmRefuseTrip"),"","confirm_refuse",$array_input,"yes",0); + $array_input = array('text'=>$langs->trans("ConfirmRefuseTrip"), array('type'=>"text",'label'=>$langs->trans("Comment"),'name'=>"detail_refuse",'size'=>"50",'value'=>"")); + $ret=$form->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("Deny"),'',"confirm_refuse",$array_input,"yes",1); if ($ret == 'html') print '
'; endif; if ($action == 'delete_line') { - $ret=$form->form_confirm($_SEVER["PHP_SELF"]."?id=".$_GET['id']."&rowid=".$_GET['rowid'],$langs->trans("DeleteLine"),$langs->trans("ConfirmDeleteLine"),"confirm_delete_line"); + $ret=$form->form_confirm($_SEVER["PHP_SELF"]."?id=".$id."&rowid=".$_GET['rowid'],$langs->trans("DeleteLine"),$langs->trans("ConfirmDeleteLine"),"confirm_delete_line",'','yes',1); if ($ret == 'html') print '
'; } @@ -1190,9 +1174,10 @@ else print ''; print ''; } + // Status print ''; print ''; - print ''; + print ''; print ''; print ''; print ''; @@ -1211,58 +1196,7 @@ else print ''; print ''; - if($object->fk_c_expensereport_statuts<3) - { - print ''; - print ''; - print ''; - } - elseif($object->fk_c_expensereport_statuts==4) - { - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - } - else - { - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - } - + // Author print ''; print ''; print ''; print ''; } + + if($object->fk_c_expensereport_statuts<3) + { + print ''; + print ''; + print ''; + } + elseif($object->fk_c_expensereport_statuts==4) + { + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + } + else + { + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + } + if($object->fk_c_expensereport_statuts==99 || !empty($object->detail_refuse)) { print ''; - print ''; - print ''; + print ''; + print ''; print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; + print ''; + print ''; print ''; } print '
'.$langs->trans("VALIDATOR").''.$langs->trans("VALIDATOR").''; $include_users = $object->fetch_users_approver_expensereport(); - $s=$form->select_dolusers($object->fk_user_validator,"fk_user_validator",0,"",0,$include_users); + $s=$form->select_dolusers($object->fk_user_validator,"fk_user_validator",1,"",0,$include_users); print $form->textwithpicto($s, $langs->trans("AnyOtherInThisListCanValidate")); print '
'.$object->libelle_paiement.'
'.$langs->trans("Statut").''.$object->getLibStatut(4).''.$object->getLibStatut(4).'
'.$langs->trans("Note").''.price($object->total_ttc).'
'.$langs->trans("VALIDATOR").''; - if ($object->fk_user_validator > 0) - { - $userfee=new User($db); - $userfee->fetch($object->fk_user_validator); - print $userfee->getNomUrl(1); - } - print '
'.$langs->trans("CANCEL_USER").''; - if ($object->fk_user_cancel > 0) - { - $userfee=new User($db); - $userfee->fetch($object->fk_user_cancel); - print $userfee->getNomUrl(1); - } - print '
'.$langs->trans("MOTIF_CANCEL").''.$object->detail_cancel.'
'.$langs->trans("DATE_CANCEL").''.$object->date_cancel.'
'.$langs->trans("VALIDOR").''; - if ($object->fk_user_valid > 0) - { - $userfee=new User($db); - $userfee->fetch($object->fk_user_valid); - print $userfee->getNomUrl(1); - } - print '
'.$langs->trans("DATE_VALIDE").''.$object->date_valide.'
'.$langs->trans("AUTHOR").''; @@ -1293,31 +1227,82 @@ else print ''.$object->date_paiement.'
'.$langs->trans("VALIDATOR").''; + if ($object->fk_user_validator > 0) + { + $userfee=new User($db); + $userfee->fetch($object->fk_user_validator); + print $userfee->getNomUrl(1); + } + print '
'.$langs->trans("CANCEL_USER").''; + if ($object->fk_user_cancel > 0) + { + $userfee=new User($db); + $userfee->fetch($object->fk_user_cancel); + print $userfee->getNomUrl(1); + } + print '
'.$langs->trans("MOTIF_CANCEL").''.$object->detail_cancel.'
'.$langs->trans("DATE_CANCEL").''.$object->date_cancel.'
'.$langs->trans("VALIDOR").''; + if ($object->fk_user_valid > 0) + { + $userfee=new User($db); + $userfee->fetch($object->fk_user_valid); + print $userfee->getNomUrl(1); + } + print '
'.$langs->trans("DATE_VALIDE").''.$object->date_valide.'
'.$langs->trans("REFUSEUR").''; + print ''.$langs->trans("REFUSEUR").''; $userfee=new User($db); $userfee->fetch($object->fk_user_refuse); print $userfee->getNomUrl(1); - print '
'.$langs->trans("MOTIF_REFUS").''.$object->detail_refuse.'
'.$langs->trans("DATE_REFUS").''.$object->date_refuse.'
'.$langs->trans("DATE_REFUS").''.$object->date_refuse; + if ($object->detail_refuse) print ' - '.$object->detail_refuse; + print '
'; print '
'; - // Fetch Lines of current ndf + // Fetch Lines of current expense report $sql = 'SELECT fde.rowid, fde.fk_expensereport, fde.fk_c_type_fees, fde.fk_projet, fde.date,'; - $sql.= ' fde.fk_c_tva, fde.comments, fde.qty, fde.value_unit, fde.total_ht, fde.total_tva, fde.total_ttc,'; + $sql.= ' fde.fk_c_tva as vatrate, fde.comments, fde.qty, fde.value_unit, fde.total_ht, fde.total_tva, fde.total_ttc,'; $sql.= ' ctf.code as type_fees_code, ctf.label as type_fees_libelle,'; $sql.= ' pjt.rowid as projet_id, pjt.title as projet_title, pjt.ref as projet_ref'; $sql.= ' FROM '.MAIN_DB_PREFIX.'expensereport_det fde'; @@ -1357,7 +1342,7 @@ else print '
'.$langs->trans('AmountTTC').'
'; - print img_picto($langs->trans("Document"), "object_generic"); - print ' '.$piece_comptable.''; + print img_picto($langs->trans("Document"), "object_generic"); + print ' '.$piece_comptable.''.$objp->date.''; - $projecttmp->id=$objp->projet_id; - $projecttmp->ref=$objp->projet_ref; - print $projecttmp->getNomUrl(1); + if ($objp->projet_id > 0) + { + $projecttmp->id=$objp->projet_id; + $projecttmp->ref=$objp->projet_ref; + print $projecttmp->getNomUrl(1); + } print ''.$langs->trans("TF_".strtoupper($objp->type_fees_libelle)).''.$objp->comments.''.vatrate($objp->tva_taux,true).''.vatrate($objp->vatrate,true).''.price($objp->value_unit).''.$objp->qty.''.price($objp->total_ht).''.price($objp->total_ttc).''.price($objp->total_ht).''.price($objp->total_ttc).'
'; + print ''; $form->select_date($objp->date,'date'); print ''; - print select_projet($objp->fk_projet,'','fk_projet'); + // Select project + print ''; + $formproject->select_projects(-1, $objp->fk_projet,'fk_projet', 0, 0, 0, 1); print ''; + // Sélect type + print ''; select_type_fees_id($objp->type_fees_code,'fk_c_type_fees'); print ''; + print ''; print ''; print ''; + print ''; print $form->load_tva('fk_c_tva', (isset($_POST["fk_c_tva"])?$_POST["fk_c_tva"]:$objp->tva_taux), $mysoc, ''); print ''; - print ''; + print ''; + print ''; print ''; - print ''; + print ''; + print ''; print ''; @@ -1450,7 +1443,6 @@ else print ''; print '
'; print '
'; - $formproject->select_projects('', GETPOST('fk_projet'), 'fk_projet', 0, 0, 1, 1); + $formproject->select_projects(-1, GETPOST('fk_projet'), 'fk_projet', 0, 0, 1, 1); print ''; - print ''; + print ''; print '
'.$objp->ref_num.''.dol_print_date($objp->date,'day').''.$author->getNomUrl().''.$objp->comments.''.price($objp->total_ht).''.price($objp->total_ttc).''; + print '
'.$objp->ref_num.''.dol_print_date($objp->date,'day').''.$author->getNomUrl().''.$objp->comments.''.price($objp->total_ht).''.price($objp->total_ttc).''; - switch($objp->fk_c_expensereport_status) { - case 4: - print img_picto($langs->trans('StatusOrderCanceled'),'statut5'); - break; - case 1: - print $langs->trans('Draft').' '.img_picto($langs->trans('Draft'),'statut0'); - break; - case 2: - print $langs->trans('TripForValid').' '.img_picto($langs->trans('TripForValid'),'statut3');; - break; - case 5: - print $langs->trans('TripForPaid').' '.img_picto($langs->trans('TripForPaid'),'statut3'); - break; - case 6: - print $langs->trans('TripPaid').' '.img_picto($langs->trans('TripPaid'),'statut4'); - break; - } - /* - if ($status==4) return img_picto($langs->trans('StatusOrderCanceled'),'statut5'); - if ($status==1) return img_picto($langs->trans('StatusOrderDraft'),'statut0'); - if ($status==2) return img_picto($langs->trans('StatusOrderValidated'),'statut1'); - if ($status==2) return img_picto($langs->trans('StatusOrderOnProcess'),'statut3'); - if ($status==5) return img_picto($langs->trans('StatusOrderToBill'),'statut4'); - if ($status==6) return img_picto($langs->trans('StatusOrderOnProcess'),'statut6'); - */ - print '
'.$langs->trans("Number").': '.$i.''.$langs->trans("TotalHT").' : '.price($total_HT).''.$langs->trans("TotalTTC").' : '.price($total_TTC).' 
'.$langs->trans("Number").': '.$i.''.$langs->trans("TotalHT").' : '.price($total_HT).''.$langs->trans("TotalTTC").' : '.price($total_TTC).' 
'; - $out.= ''; - $out.= ''; - $out.= '
'; - if ($projetid == 0) { - $out.= ''; - } else { - $out.= ''; - } - $out.= ajax_autocompleter(($projetid?$projetid:-1),$htmlname,dol_buildpath('/expensereport/ajax/ajaxprojet.php',1).'?filter='.urlencode($filter), '', $minLength); - $out.= '
'; - } - - } - else - { - dol_print_error($db); - } - - return $out; -} - /** * Return list of types of notes with select value = id * diff --git a/htdocs/expensereport/document.php b/htdocs/expensereport/document.php index b8f3d02c8a6..86ff064db7d 100644 --- a/htdocs/expensereport/document.php +++ b/htdocs/expensereport/document.php @@ -1,6 +1,6 @@ - * Copyright (C) 2004-2010 Laurent Destailleur + * Copyright (C) 2004-2015 Laurent Destailleur * Copyright (C) 2005 Marc Barilley / Ocebo * Copyright (C) 2005-2009 Regis Houssin * Copyright (C) 2005 Simon TOSSER @@ -25,10 +25,12 @@ /** * \file htdocs/expensereport/document.php * \ingroup expensereport - * \brief Page of linked files onto trip and expenses + * \brief Page of linked files onto trip and expens reports */ require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/expensereport.lib.php'; require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php'; @@ -102,7 +104,7 @@ if ($object->id) print ''; - $linkback = ''.$langs->trans("BackToList").''; + $linkback = ''.$langs->trans("BackToList").''; // Ref print ''; - print ''; + print ''; print ''; // Description diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index e1aa84f1f4c..0b80c7b9cd7 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -126,7 +126,7 @@ class Project extends CommonObject $sql.= ", '".$this->db->idate($now)."'"; $sql.= ", " . ($this->date_start != '' ? "'".$this->db->idate($this->date_start)."'" : 'null'); $sql.= ", " . ($this->date_end != '' ? "'".$this->db->idate($this->date_end)."'" : 'null'); - $sql.= ", " . $this->budget_amount; + $sql.= ", " . ($this->budget_amount != ''?price2num($this->budget_amount):'null'); $sql.= ", ".$conf->entity; $sql.= ")"; @@ -152,7 +152,7 @@ class Project extends CommonObject $error++; } - //Update extrafield + // Update extrafield if (!$error) { if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used { @@ -495,6 +495,23 @@ class Project extends CommonObject } } + // Set fk_projet into elements to null + $listoftables=array( + 'facture'=>'fk_projet','propal'=>'fk_projet','commande'=>'fk_projet','facture_fourn'=>'fk_projet','commande_fournisseur'=>'fk_projet', + 'expensereport_det'=>'fk_projet','contrat'=>'fk_projet','fichinter'=>'fk_projet' + ); + foreach($listoftables as $key => $value) + { + $sql = "UPDATE " . MAIN_DB_PREFIX . $key . " SET ".$value." = NULL where ".$value." = ". $this->id; + $resql = $this->db->query($sql); + if (!$resql) + { + $this->errors[] = $this->db->lasterror(); + $error++; + break; + } + } + // Delete tasks if (! $error) { diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index e83964949b6..ccf54a6f9b5 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -393,6 +393,9 @@ th .button { .centpercent { width: 100%; } +textarea.centpercent { + width: 96%; +} .center { text-align: center; } @@ -444,11 +447,17 @@ th .button { .hideobject { display: none; } .minwidth100 { min-width: 100px; } .minwidth200 { min-width: 200px; } +.minwidth300 { min-width: 300px; } +.maxwidth100 { max-width: 100px; } +.maxwidth200 { max-width: 200px; } +.maxwidth300 { max-width: 300px; } .hideonsmartphone { display: none; } .noenlargeonsmartphone { width : 50px !important; display: inline !important; } .maxwidthonsmartphone { max-width: 100px; } +.maxwidth100onsmartphone { max-width: 100px; } .maxwidth200onsmartphone { max-width: 200px; } +.maxwidth300onsmartphone { max-width: 300px; } .linkobject { cursor: pointer; } From 30a5111c683800123df486fee8adab8b4b681569 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 21 Feb 2015 15:18:05 +0100 Subject: [PATCH 168/173] Work on expense report module --- htdocs/compta/deplacement/card.php | 2 +- htdocs/core/class/html.formprojet.class.php | 20 ++-- .../core/modules/modExpenseReport.class.php | 39 +++++-- htdocs/expensereport/card.php | 82 +++++++------- .../class/expensereport.class.php | 103 ++++++++++-------- .../class/expensereportstats.class.php | 20 ++-- htdocs/expensereport/synchro_compta.php | 6 +- .../install/mysql/migration/3.7.0-3.8.0.sql | 24 ++-- .../mysql/tables/llx_expensereport.sql | 21 ++-- htdocs/langs/en_US/trips.lang | 5 + htdocs/projet/class/project.class.php | 4 +- htdocs/projet/element.php | 87 ++++++++++----- 12 files changed, 243 insertions(+), 170 deletions(-) diff --git a/htdocs/compta/deplacement/card.php b/htdocs/compta/deplacement/card.php index bdde060f448..bd4a4555fb7 100644 --- a/htdocs/compta/deplacement/card.php +++ b/htdocs/compta/deplacement/card.php @@ -128,7 +128,7 @@ else if ($action == 'add' && $user->rights->deplacement->creer) setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("Date")), 'errors'); $error++; } - if ($object->type == '-1') // Otherwise it is TF_LUNCH,... + if ($object->type == '-1') { setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("Type")), 'errors'); $error++; diff --git a/htdocs/core/class/html.formprojet.class.php b/htdocs/core/class/html.formprojet.class.php index 86d46f3b9b5..85c9ffbb241 100644 --- a/htdocs/core/class/html.formprojet.class.php +++ b/htdocs/core/class/html.formprojet.class.php @@ -87,7 +87,7 @@ class FormProjets if ($resql) { $minmax=''; - + // Use select2 selector $nodatarole=''; if (! empty($conf->use_javascript_ajax)) @@ -219,6 +219,11 @@ class FormProjets $sql = "SELECT id as rowid, label as ref"; $projectkey="fk_project"; break; + case "expensereport_det": + return ''; + /*$sql = "SELECT rowid, '' as ref"; // table is llx_expensereport_det + $projectkey="fk_projet"; + break;*/ default: $sql = "SELECT rowid, ref"; break; @@ -226,10 +231,8 @@ class FormProjets $sql.= " FROM ".MAIN_DB_PREFIX.$table_element; $sql.= " WHERE ".$projectkey." is null"; - if (!empty($socid)) { - $sql.= " AND fk_soc=".$socid; - } - $sql.= ' AND entity='.getEntity('project'); + if (!empty($socid)) $sql.= " AND fk_soc=".$socid; + if (! in_array($table_element, array('expensereport_det'))) $sql.= ' AND entity='.getEntity('project'); $sql.= " ORDER BY ref DESC"; dol_syslog(get_class($this).'::select_element', LOG_DEBUG); @@ -260,9 +263,12 @@ class FormProjets }*/ $this->db->free($resql); - return $sellist ; - }else { + return $sellist; + } + else + { $this->error=$this->db->lasterror(); + $this->errors[]=$this->db->lasterror(); dol_syslog(get_class($this) . "::select_element " . $this->error, LOG_ERR); return -1; } diff --git a/htdocs/core/modules/modExpenseReport.class.php b/htdocs/core/modules/modExpenseReport.class.php index edee0952b00..b5b45ea23f8 100755 --- a/htdocs/core/modules/modExpenseReport.class.php +++ b/htdocs/core/modules/modExpenseReport.class.php @@ -224,8 +224,8 @@ class modExpenseReport extends DolibarrModules 'url'=>'/expensereport/index.php', 'langs'=>'trips', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. 'position'=>100, - 'enabled'=>'1', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. - 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules + 'enabled'=>'$conf->expensereport->enabled', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. + 'perms'=>'$user->rights->expensereport->lire', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules 'target'=>'', 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both $r++; @@ -234,12 +234,12 @@ class modExpenseReport extends DolibarrModules 'type'=>'left', // This is a Left menu entry 'titre'=>'New', 'mainmenu'=>'accountancy', - 'leftmenu'=>'expensereport_detail', + 'leftmenu'=>'expensereport_detailnew', 'url'=>'/expensereport/card.php?action=create', 'langs'=>'trips', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. 'position'=>100, - 'enabled'=>'1', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. - 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules + 'enabled'=>'$conf->expensereport->enabled', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. + 'perms'=>'$user->rights->expensereport->creer', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules 'target'=>'', 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both $r++; @@ -248,12 +248,26 @@ class modExpenseReport extends DolibarrModules 'type'=>'left', // This is a Left menu entry 'titre'=>'List', 'mainmenu'=>'accountancy', - 'leftmenu'=>'expensereport_detail', + 'leftmenu'=>'expensereport_detaillist', 'url'=>'/expensereport/list.php', 'langs'=>'trips', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. 'position'=>100, - 'enabled'=>'1', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. - 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules + 'enabled'=>'$conf->expensereport->enabled', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. + 'perms'=>'$user->rights->expensereport->lire', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both + $r++; + + $this->menu[$r]=array( 'fk_menu'=>'fk_mainmenu=accountancy,fk_leftmenu=expensereport_detaillist', // Use r=value where r is index key used for the parent menu entry (higher parent must be a top menu entry) + 'type'=>'left', // This is a Left menu entry + 'titre'=>'ListToApprove', + 'mainmenu'=>'accountancy', + 'leftmenu'=>'expensereport_detaillist_approve', + 'url'=>'/expensereport/list.php?search_state=2', + 'langs'=>'trips', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>100, + 'enabled'=>'$conf->expensereport->enabled', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. + 'perms'=>'$user->rights->expensereport->lire', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules 'target'=>'', 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both $r++; @@ -266,13 +280,14 @@ class modExpenseReport extends DolibarrModules 'url'=>'/expensereport/stats/index.php', 'langs'=>'trips', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. 'position'=>100, - 'enabled'=>'1', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. - 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules + 'enabled'=>'$conf->expensereport->enabled', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. + 'perms'=>'$user->rights->expensereport->lire', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules 'target'=>'', 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both $r++; + // Disabled, not yet stable $this->menu[$r]=array( 'fk_menu'=>'fk_mainmenu=accountancy,fk_leftmenu=expensereport', // Use r=value where r is index key used for the parent menu entry (higher parent must be a top menu entry) 'type'=>'left', // This is a Left menu entry 'titre'=>'ExportTripCSV', @@ -282,7 +297,7 @@ class modExpenseReport extends DolibarrModules 'langs'=>'expensereport', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. 'position'=>100, 'enabled'=>'$conf->global->DEPLACEMENT_TO_CLEAN', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. - 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules + 'perms'=>'$user->rights->expensereport->lire', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules 'target'=>'', 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both $r++; @@ -296,7 +311,7 @@ class modExpenseReport extends DolibarrModules 'langs'=>'expensereport', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. 'position'=>100, 'enabled'=>'$conf->global->DEPLACEMENT_TO_CLEAN', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. - 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules + 'perms'=>'$user->rights->expensereport->lire', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules 'target'=>'', 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both $r++; diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index 871cbe22990..cfe3c86058b 100755 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -105,7 +105,7 @@ if ($action == 'add' && $user->rights->expensereport->creer) $object->fk_user_validator = GETPOST('fk_user_validator','int'); $object->note = GETPOST('note'); - if ($object->periode_existe($user,dol_print_date($object->date_debut, 'dayrfc'),dol_print_date($object->date_fin, 'dayrfc'))) + if ($object->periode_existe($user,$object->date_debut,$object->date_fin)) { $error++; setEventMessage($langs->trans("ErrorDoubleDeclaration"),'errors'); @@ -398,8 +398,8 @@ if ($action == "confirm_refuse" && GETPOST('confirm')=="yes" && $id > 0 && $user { $object = new ExpenseReport($db); $object->fetch($id); - - $result = $object->set_refuse($user,GETPOST('detail_refuse')); + + $result = $object->setDeny($user,GETPOST('detail_refuse')); if ($result > 0) { if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) @@ -456,34 +456,34 @@ if ($action == "confirm_refuse" && GETPOST('confirm')=="yes" && $id > 0 && $user } //var_dump($user->id == $object->fk_user_validator);exit; -if ($action == "confirm_cancel" && GETPOST('confirm')=="yes" && !empty($_POST['detail_cancel']) && $id > 0 && $user->rights->expensereport->creer) +if ($action == "confirm_cancel" && GETPOST('confirm')=="yes" && GETPOST('detail_cancel') && $id > 0 && $user->rights->expensereport->creer) { $object = new ExpenseReport($db); $object->fetch($id); - + if ($user->id == $object->fk_user_valid || $user->id == $object->fk_user_author) { - $result = $object->set_cancel($user,$_POST['detail_cancel']); - + $result = $object->set_cancel($user,GETPOST('detail_cancel')); + if ($result > 0) { if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) { // Send mail - + // TO $destinataire = new User($db); $destinataire->fetch($object->fk_user_author); $emailTo = $destinataire->email; - + // FROM $expediteur = new User($db); $expediteur->fetch($object->fk_user_cancel); $emailFrom = $expediteur->email; - + // SUBJECT $subject = "' ERP - Note de frais annulée"; - + // CONTENT $message = "Bonjour {$destinataire->firstname},\n\n"; $message.= "Votre note de frais \"{$object->ref}\" vient d'être annulée.\n"; @@ -491,10 +491,10 @@ if ($action == "confirm_cancel" && GETPOST('confirm')=="yes" && !empty($_POST['d $message.= "- Motif d'annulation : {$_POST['detail_cancel']}\n"; $message.= "- Lien : {$dolibarr_main_url_root}/expensereport/card.php?id={$object->id}\n\n"; $message.= "Bien cordialement,\n' SI"; - + // PREPARE SEND $mailfile = new CMailFile($subject,$emailTo,$emailFrom,$message); - + if(!$mailfile->error) { // SEND @@ -523,10 +523,10 @@ if ($action == "confirm_cancel" && GETPOST('confirm')=="yes" && !empty($_POST['d } } -if ($action == "confirm_paid" && $_GET['confirm']=="yes" && $id > 0 && $user->rights->expensereport->to_paid) +if ($action == "confirm_paid" && GETPOST('confirm')=="yes" && $id > 0 && $user->rights->expensereport->to_paid) { $object = new ExpenseReport($db); - $object->fetch($id,$user); + $object->fetch($id); $result = $object->setPaid($user); if ($result > 0) @@ -665,7 +665,7 @@ if ($action == "addline") $vatrate=GETPOST('vatrate'); $object_ligne->fk_c_tva = $vatrate; $object_ligne->vatrate = $vatrate; - + $object_ligne->fk_projet = $fk_projet; if (! GETPOST('fk_c_type_fees') > 0) @@ -1129,22 +1129,24 @@ else if ($ret == 'html') print '
'; endif; - if ($action == 'cancel'): - $array_input = array(array('type'=>"text",'label'=>$langs->trans("Comment"),'name'=>"detail_cancel",'size'=>"50",'value'=>"")); - $ret=$form->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("ConfirmCancelTrip"),"","confirm_cancel",$array_input,"",0); - if ($ret == 'html') print '
'; - endif; + if ($action == 'cancel') + { + $array_input = array('text'=>$langs->trans("ConfirmCancelTrip"), array('type'=>"text",'label'=>$langs->trans("Comment"),'name'=>"detail_cancel",'size'=>"50",'value'=>"")); + $ret=$form->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("Cancel"),"","confirm_cancel",$array_input,"",1); + if ($ret == 'html') print '
'; + } if ($action == 'brouillonner'): $ret=$form->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("BrouillonnerTrip"),$langs->trans("ConfirmBrouillonnerTrip"),"confirm_brouillonner","","",1); if ($ret == 'html') print '
'; endif; - if ($action == 'refuse'): - $array_input = array('text'=>$langs->trans("ConfirmRefuseTrip"), array('type'=>"text",'label'=>$langs->trans("Comment"),'name'=>"detail_refuse",'size'=>"50",'value'=>"")); - $ret=$form->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("Deny"),'',"confirm_refuse",$array_input,"yes",1); - if ($ret == 'html') print '
'; - endif; + if ($action == 'refuse') // Deny + { + $array_input = array('text'=>$langs->trans("ConfirmRefuseTrip"), array('type'=>"text",'label'=>$langs->trans("Comment"),'name'=>"detail_refuse",'size'=>"50",'value'=>"")); + $ret=$form->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("Deny"),'',"confirm_refuse",$array_input,"yes",1); + if ($ret == 'html') print '
'; + } if ($action == 'delete_line') { @@ -1211,7 +1213,7 @@ else print '
'; print ''; - print ''; + print ''; print ''; if($object->fk_c_expensereport_statuts==6) { @@ -1227,8 +1229,8 @@ else print ''; print ''; } - - if($object->fk_c_expensereport_statuts<3) + + if($object->fk_c_expensereport_statuts<3) // informed { print ''; print ''; @@ -1259,24 +1261,24 @@ else print ''; print ''; print ''; - print ''; + print ''; print ''; } else { print ''; - print ''; + print ''; print ''; print ''; - print ''; - print ''; + print ''; + print ''; print ''; } @@ -1291,7 +1293,7 @@ else print ''; print ''; print ''; - print ''; print ''; @@ -1398,7 +1400,7 @@ else } print ''; } - + if ($action == 'editline' && $objp->rowid == GETPOST('rowid')) { //modif ligne!!!!! @@ -1681,7 +1683,7 @@ if ($action != 'create' && $action != 'edit') { print ''.$langs->trans('Cancel').''; } - + if($user->rights->expensereport->supprimer) { // Supprimer diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php index 76534e94c2a..40be7298a1c 100755 --- a/htdocs/expensereport/class/expensereport.class.php +++ b/htdocs/expensereport/class/expensereport.class.php @@ -54,10 +54,14 @@ class ExpenseReport extends CommonObject var $fk_user_cancel; // Validation - var $date_valide; + var $date_valid; var $fk_user_valid; var $user_valid_infos; + // Approve + var $date_approve; + var $fk_user_approve; + // Paiement var $date_paiement; var $fk_user_paid; @@ -257,9 +261,9 @@ class ExpenseReport extends CommonObject $sql.= " d.detail_refuse, d.detail_cancel, d.fk_user_refuse, d.fk_user_cancel,"; // ACTIONS $sql.= " d.date_refuse, d.date_cancel,"; // ACTIONS $sql.= " d.total_ht, d.total_ttc, d.total_tva,"; // TOTAUX (int) - $sql.= " d.date_debut, d.date_fin, d.date_create, d.date_valide, d.date_paiement,"; // DATES (datetime) + $sql.= " d.date_debut, d.date_fin, d.date_create, d.date_valid, d.date_approve, d.date_paiement,"; // DATES (datetime) $sql.= " d.fk_user_author, d.fk_user_validator, d.fk_c_expensereport_statuts as status, d.fk_c_paiement,"; - $sql.= " d.fk_user_valid, d.fk_user_paid,"; // FOREING KEY 2 (int) + $sql.= " d.fk_user_valid, d.fk_user_approve, d.fk_user_paid,"; $sql.= " dp.libelle as libelle_paiement, dp.code as code_paiement"; // INNER JOIN paiement $sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element." d LEFT JOIN ".MAIN_DB_PREFIX."c_paiement dp ON d.fk_c_paiement = dp.id"; if ($ref) $sql.= " WHERE d.ref = '".$this->db->escape($ref)."'"; @@ -282,20 +286,22 @@ class ExpenseReport extends CommonObject $this->detail_refuse = $obj->detail_refuse; $this->detail_cancel = $obj->detail_cancel; - $this->date_debut = $obj->date_debut; - $this->date_fin = $obj->date_fin; - $this->date_paiement = $obj->date_paiement; - $this->date_valide = $obj->date_valide; - $this->date_create = $obj->date_create; - $this->date_refuse = $obj->date_refuse; - $this->date_cancel = $obj->date_cancel; + $this->date_debut = $this->db->jdate($obj->date_debut); + $this->date_fin = $this->db->jdate($obj->date_fin); + $this->date_paiement = $this->db->jdate($obj->date_paiement); + $this->date_valid = $this->db->jdate($obj->date_valid); + $this->date_approve = $this->db->jdate($obj->date_approve); + $this->date_create = $this->db->jdate($obj->date_create); + $this->date_refuse = $this->db->jdate($obj->date_refuse); + $this->date_cancel = $this->db->jdate($obj->date_cancel); $this->fk_user_author = $obj->fk_user_author; $this->fk_user_validator = $obj->fk_user_validator; $this->fk_user_valid = $obj->fk_user_valid; - $this->fk_user_paid = $obj->fk_user_paid; $this->fk_user_refuse = $obj->fk_user_refuse; $this->fk_user_cancel = $obj->fk_user_cancel; + $this->fk_user_approve = $obj->fk_user_approve; + $this->fk_user_paid = $obj->fk_user_paid; $user_author = new User($this->db); if ($this->fk_user_author > 0) $user_author->fetch($this->fk_user_author); @@ -404,10 +410,12 @@ class ExpenseReport extends CommonObject $sql = "SELECT f.rowid,"; $sql.= " f.date_create as datec,"; $sql.= " f.tms as date_modification,"; - $sql.= " f.date_valide as datev,"; - $sql.= " f.fk_user_author,"; + $sql.= " f.date_valid as datev,"; + $sql.= " f.date_approve as datea,"; + $sql.= " f.fk_user_author as fk_user_creation,"; $sql.= " f.fk_user_modif as fk_user_modification,"; - $sql.= " f.fk_user_validator"; + $sql.= " f.fk_user_valid,"; + $sql.= " f.fk_user_approve"; $sql.= " FROM ".MAIN_DB_PREFIX."expensereport as f"; $sql.= " WHERE f.rowid = ".$id; $sql.= " AND f.entity = ".$conf->entity; @@ -424,11 +432,18 @@ class ExpenseReport extends CommonObject $this->date_creation = $this->db->jdate($obj->datec); $this->date_modification = $this->db->jdate($obj->date_modification); $this->date_validation = $this->db->jdate($obj->datev); + $this->date_approbation = $this->db->jdate($obj->datea); $cuser = new User($this->db); $cuser->fetch($obj->fk_user_author); $this->user_creation = $cuser; + if ($obj->fk_user_creation) + { + $cuser = new User($this->db); + $cuser->fetch($obj->fk_user_creation); + $this->user_creation = $cuser; + } if ($obj->fk_user_valid) { $vuser = new User($this->db); @@ -739,14 +754,14 @@ class ExpenseReport extends CommonObject $sql.= ' WHERE rowid = '.$this->id; $result = $this->db->query($sql); $objp = $this->db->fetch_object($result); - $this->date_debut = $objp->date_debut; - $expld_date_debut = explode("-",$this->date_debut); - $this->date_debut = $expld_date_debut[0].$expld_date_debut[1].$expld_date_debut[2]; + $this->date_debut = $this->db->jdate($objp->date_debut); // Création du ref_number suivant if($ref_next) { - $this->ref = strtoupper($user->login).$expld_car."NDF".$this->ref.$expld_car.$this->date_debut; + $prefix="ER"; + if (! empty($conf->global->EXPENSE_REPORT_PREFIX)) $prefix=$conf->global->EXPENSE_REPORT_PREFIX; + $this->ref = strtoupper($user->login).$expld_car.$prefix.$this->ref.$expld_car.dol_print_date($this->date_debut,'%y%m%d'); } if ($this->fk_c_expensereport_statuts != 2) @@ -793,9 +808,7 @@ class ExpenseReport extends CommonObject $objp = $this->db->fetch_object($result); - $this->date_debut = $objp->date_debut; - $expld_date_debut = explode("-",$this->date_debut); - $this->date_debut = $expld_date_debut[0].$expld_date_debut[1].$expld_date_debut[2]; + $this->date_debut = $this->db->jdate($objp->date_debut); if ($this->fk_c_expensereport_statuts != 2) { @@ -829,13 +842,15 @@ class ExpenseReport extends CommonObject */ function setApproved($user) { - // date de validation - $this->date_valide = $this->db->idate(gmmktime()); + $now=dol_now(); + + // date approval + $this->date_approve = $this->db->idate($now); if ($this->fk_c_expensereport_statuts != 5) { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; $sql.= " SET ref = '".$this->ref."', fk_c_expensereport_statuts = 5, fk_user_approve = ".$user->id.","; - $sql.= " date_valide='".$this->date_valide."'"; + $sql.= " date_approve='".$this->date_approve."'"; $sql.= ' WHERE rowid = '.$this->id; if ($this->db->query($sql)) { @@ -854,15 +869,15 @@ class ExpenseReport extends CommonObject } /** - * set_refuse + * setDeny * * @param User $user User * @param Details $details Details */ - function set_refuse($user,$details) + function setDeny($user,$details) { $now = dol_now(); - + // date de refus if ($this->fk_c_expensereport_statuts != 99) { @@ -870,6 +885,7 @@ class ExpenseReport extends CommonObject $sql.= " SET ref = '".$this->ref."', fk_c_expensereport_statuts = 99, fk_user_refuse = ".$user->id.","; $sql.= " date_refuse='".$this->db->idate($now)."',"; $sql.= " detail_refuse='".$this->db->escape($details)."'"; + $sql.= " fk_user_approve=NULL,"; $sql.= ' WHERE rowid = '.$this->id; if ($this->db->query($sql)) { @@ -887,7 +903,7 @@ class ExpenseReport extends CommonObject } else { - dol_syslog(get_class($this)."::set_refuse expensereport already with refuse status", LOG_WARNING); + dol_syslog(get_class($this)."::setDeny expensereport already with refuse status", LOG_WARNING); } } @@ -899,16 +915,17 @@ class ExpenseReport extends CommonObject */ function setPaid($user) { - $this->date_paiement = $this->db->idate(gmmktime()); + $now= dol_now(); + + $this->date_paiement = $this->db->idate($now); if ($this->fk_c_expensereport_statuts != 6) { $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; $sql.= " SET fk_c_expensereport_statuts = 6, fk_user_paid = ".$user->id.","; - $sql.= " date_paiement='".$this->date_paiement."'"; + $sql.= " date_paiement='".$this->db->idate($this->date_paiement)."'"; $sql.= ' WHERE rowid = '.$this->id; dol_syslog(get_class($this)."::setPaid sql=".$sql, LOG_DEBUG); - if ($this->db->query($sql)) { return 1; @@ -1236,9 +1253,9 @@ class ExpenseReport extends CommonObject * @param Date $date_fin End date * @return int <0 if KO, >0 if OK */ - function periode_existe($user,$date_debut,$date_fin) + function periode_existe($user, $date_debut, $date_fin) { - $sql = "SELECT rowid,date_debut,date_fin"; + $sql = "SELECT rowid, date_debut, date_fin"; $sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element; $sql.= " WHERE fk_user_author = '{$user->id}'"; @@ -1250,10 +1267,8 @@ class ExpenseReport extends CommonObject if ($num_lignes>0) { - $date_d_form = explode("-",$date_debut); // 1 - $date_f_form = explode("-",$date_fin); // 2 - $date_d_form = mktime(12,0,0,$date_d_form[1],$date_d_form[2],$date_d_form[0]); - $date_f_form = mktime(12,0,0,$date_f_form[1],$date_f_form[2],$date_f_form[0]); + $date_d_form = $date_debut; + $date_f_form = $date_fin; $existe = false; @@ -1261,12 +1276,10 @@ class ExpenseReport extends CommonObject { $objp = $this->db->fetch_object($result); - $date_d_req = explode("-",$objp->date_debut); // 3 - $date_f_req = explode("-",$objp->date_fin); // 4 - $date_d_req = mktime(12,0,0,$date_d_req[1],$date_d_req[2],$date_d_req[0]); - $date_f_req = mktime(12,0,0,$date_f_req[1],$date_f_req[2],$date_f_req[0]); + $date_d_req = $this->db->jdate($objp->date_debut); // 3 + $date_f_req = $this->db->jdate($objp->date_fin); // 4 - if(!($date_f_form < $date_d_req OR $date_d_form > $date_f_req)) $existe = true; + if (!($date_f_form < $date_d_req || $date_d_form > $date_f_req)) $existe = true; $i++; } @@ -1374,14 +1387,12 @@ class ExpenseReportLine function fetch($rowid) { $sql = 'SELECT fde.rowid, fde.fk_expensereport, fde.fk_c_type_fees, fde.fk_projet, fde.date,'; - $sql.= ' fde.fk_c_tva, fde.comments, fde.qty, fde.value_unit, fde.total_ht, fde.total_tva, fde.total_ttc,'; + $sql.= ' fde.fk_c_tva as tva_taux, fde.comments, fde.qty, fde.value_unit, fde.total_ht, fde.total_tva, fde.total_ttc,'; $sql.= ' ctf.code as type_fees_code, ctf.label as type_fees_libelle,'; - $sql.= ' pjt.rowid as projet_id, pjt.title as projet_title, pjt.ref as projet_ref,'; - $sql.= ' tva.rowid as tva_id, tva.taux as tva_taux'; + $sql.= ' pjt.rowid as projet_id, pjt.title as projet_title, pjt.ref as projet_ref'; $sql.= ' FROM '.MAIN_DB_PREFIX.'expensereport_det fde'; $sql.= ' INNER JOIN '.MAIN_DB_PREFIX.'c_type_fees ctf ON fde.fk_c_type_fees=ctf.id'; $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'projet pjt ON fde.fk_projet=pjt.rowid'; - $sql.= ' INNER JOIN '.MAIN_DB_PREFIX.'c_tva tva ON fde.fk_c_tva=tva.rowid'; $sql.= ' WHERE fde.rowid = '.$rowid; $result = $this->db->query($sql); diff --git a/htdocs/expensereport/class/expensereportstats.class.php b/htdocs/expensereport/class/expensereportstats.class.php index 64d0aaf01ed..e12b4ed2a79 100644 --- a/htdocs/expensereport/class/expensereportstats.class.php +++ b/htdocs/expensereport/class/expensereportstats.class.php @@ -59,7 +59,7 @@ class ExpenseReportStats extends Stats $this->from = MAIN_DB_PREFIX.$object->table_element; $this->field='total_ht'; - $this->where = " fk_c_expensereport_statuts > 0 and date_valide > '2000-01-01'"; + $this->where = " fk_c_expensereport_statuts > 0 and date_valid > '2000-01-01'"; //$this->where.= " AND entity = ".$conf->entity; if ($this->socid) { @@ -70,13 +70,13 @@ class ExpenseReportStats extends Stats /** - * Renvoie le nombre de facture par annee + * Return nb of expense report per year * * @return array Array of values */ function getNbByYear() { - $sql = "SELECT YEAR(date_valide) as dm, count(*)"; + $sql = "SELECT YEAR(date_valid) as dm, count(*)"; $sql.= " FROM ".$this->from; $sql.= " GROUP BY dm DESC"; $sql.= " WHERE ".$this->where; @@ -93,9 +93,9 @@ class ExpenseReportStats extends Stats */ function getNbByMonth($year) { - $sql = "SELECT MONTH(date_valide) as dm, count(*)"; + $sql = "SELECT MONTH(date_valid) as dm, count(*)"; $sql.= " FROM ".$this->from; - $sql.= " WHERE YEAR(date_valide) = ".$year; + $sql.= " WHERE YEAR(date_valid) = ".$year; $sql.= " AND ".$this->where; $sql.= " GROUP BY dm"; $sql.= $this->db->order('dm','DESC'); @@ -114,9 +114,9 @@ class ExpenseReportStats extends Stats */ function getAmountByMonth($year) { - $sql = "SELECT date_format(date_valide,'%m') as dm, sum(".$this->field.")"; + $sql = "SELECT date_format(date_valid,'%m') as dm, sum(".$this->field.")"; $sql.= " FROM ".$this->from; - $sql.= " WHERE date_format(date_valide,'%Y') = '".$year."'"; + $sql.= " WHERE date_format(date_valid,'%Y') = '".$year."'"; $sql.= " AND ".$this->where; $sql.= " GROUP BY dm"; $sql.= $this->db->order('dm','DESC'); @@ -134,9 +134,9 @@ class ExpenseReportStats extends Stats */ function getAverageByMonth($year) { - $sql = "SELECT date_format(date_valide,'%m') as dm, avg(".$this->field.")"; + $sql = "SELECT date_format(date_valid,'%m') as dm, avg(".$this->field.")"; $sql.= " FROM ".$this->from; - $sql.= " WHERE date_format(date_valide,'%Y') = '".$year."'"; + $sql.= " WHERE date_format(date_valid,'%Y') = '".$year."'"; $sql.= " AND ".$this->where; $sql.= " GROUP BY dm"; $sql.= $this->db->order('dm','DESC'); @@ -151,7 +151,7 @@ class ExpenseReportStats extends Stats */ function getAllByYear() { - $sql = "SELECT date_format(date_valide,'%Y') as year, count(*) as nb, sum(".$this->field.") as total, avg(".$this->field.") as avg"; + $sql = "SELECT date_format(date_valid,'%Y') as year, count(*) as nb, sum(".$this->field.") as total, avg(".$this->field.") as avg"; $sql.= " FROM ".$this->from; $sql.= " WHERE ".$this->where; $sql.= " GROUP BY year"; diff --git a/htdocs/expensereport/synchro_compta.php b/htdocs/expensereport/synchro_compta.php index 211f5c4cc0a..11c91d314fb 100755 --- a/htdocs/expensereport/synchro_compta.php +++ b/htdocs/expensereport/synchro_compta.php @@ -137,12 +137,12 @@ else: print ' '; print ""; - $sql = "SELECT d.fk_bank_account, d.ref, d.rowid, d.date_valide, d.fk_user_author, d.total_ttc, d.integration_compta, d.fk_c_expensereport_statuts"; + $sql = "SELECT d.fk_bank_account, d.ref, d.rowid, d.date_valid, d.fk_user_author, d.total_ttc, d.integration_compta, d.fk_c_expensereport_statuts"; $sql.= " ,CONCAT(u.firstname,' ',u.lastname) as declarant_NDF"; $sql.= " FROM ".MAIN_DB_PREFIX."expensereport d"; $sql.= " INNER JOIN ".MAIN_DB_PREFIX."user u ON d.fk_user_author = u.rowid"; $sql.= " WHERE d.fk_c_expensereport_statuts = 6"; - $sql.= " ORDER BY d.date_valide DESC"; + $sql.= " ORDER BY d.date_valid DESC"; $resql=$db->query($sql); if ($resql): @@ -170,7 +170,7 @@ else: $var=!$var; print ""; print ''; - print ''; + print ''; print ''; print ''; diff --git a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql index a697096874a..13c948bea56 100755 --- a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql +++ b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql @@ -118,10 +118,9 @@ ALTER TABLE llx_stock_mouvement ADD COLUMN sellby date DEFAULT NULL; - CREATE TABLE llx_expensereport ( rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY, - ref varchar(50) NOT NULL, + ref varchar(50) NOT NULL, entity integer DEFAULT 1 NOT NULL, -- multi company id ref_number_int integer DEFAULT NULL, ref_ext integer, @@ -132,30 +131,33 @@ CREATE TABLE llx_expensereport ( total_ttc double(24,8) DEFAULT 0, date_debut date NOT NULL, date_fin date NOT NULL, - date_paiement datetime, - date_valide datetime, date_create datetime NOT NULL, + date_valid datetime, + date_approve datetime, + date_refuse datetime, + date_cancel datetime, + date_paiement datetime, tms timestamp, fk_user_author integer NOT NULL, fk_user_modif integer DEFAULT NULL, + fk_user_valid integer DEFAULT NULL, fk_user_validator integer DEFAULT NULL, + fk_user_approve integer DEFAULT NULL, + fk_user_refuse integer DEFAULT NULL, + fk_user_cancel integer DEFAULT NULL, + fk_user_paid integer DEFAULT NULL, fk_c_expensereport_statuts integer NOT NULL, -- 1=brouillon, 2=validé (attente approb), 4=annulé, 5=approuvé, 6=payed, 99=refusé fk_c_paiement integer DEFAULT NULL, note text, note_private text, - fk_user_valid integer DEFAULT NULL, - fk_user_paid integer DEFAULT NULL, detail_refuse varchar(255) DEFAULT NULL, - date_cancel datetime, - date_refuse datetime, detail_cancel varchar(255) DEFAULT NULL, - fk_user_cancel integer DEFAULT NULL, - fk_user_refuse integer DEFAULT NULL, - integration_compta integer DEFAULT NULL, + integration_compta integer DEFAULT NULL, -- not used fk_bank_account integer DEFAULT NULL, model_pdf varchar(50) DEFAULT NULL ) ENGINE=innodb; + CREATE TABLE llx_expensereport_det ( rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY, diff --git a/htdocs/install/mysql/tables/llx_expensereport.sql b/htdocs/install/mysql/tables/llx_expensereport.sql index 5fd3d2a3998..7224ec38b61 100755 --- a/htdocs/install/mysql/tables/llx_expensereport.sql +++ b/htdocs/install/mysql/tables/llx_expensereport.sql @@ -29,27 +29,28 @@ CREATE TABLE llx_expensereport ( total_ttc double(24,8) DEFAULT 0, date_debut date NOT NULL, date_fin date NOT NULL, - date_paiement datetime, - date_valide datetime, date_create datetime NOT NULL, + date_valid datetime, + date_approve datetime, + date_refuse datetime, + date_cancel datetime, + date_paiement datetime, tms timestamp, fk_user_author integer NOT NULL, fk_user_modif integer DEFAULT NULL, + fk_user_valid integer DEFAULT NULL, fk_user_validator integer DEFAULT NULL, + fk_user_approve integer DEFAULT NULL, + fk_user_refuse integer DEFAULT NULL, + fk_user_cancel integer DEFAULT NULL, + fk_user_paid integer DEFAULT NULL, fk_c_expensereport_statuts integer NOT NULL, -- 1=brouillon, 2=validé (attente approb), 4=annulé, 5=approuvé, 6=payed, 99=refusé fk_c_paiement integer DEFAULT NULL, note text, note_private text, - fk_user_valid integer DEFAULT NULL, - fk_user_approve integer DEFAULT NULL, - fk_user_paid integer DEFAULT NULL, detail_refuse varchar(255) DEFAULT NULL, - date_cancel datetime, - date_refuse datetime, detail_cancel varchar(255) DEFAULT NULL, - fk_user_cancel integer DEFAULT NULL, - fk_user_refuse integer DEFAULT NULL, - integration_compta integer DEFAULT NULL, + integration_compta integer DEFAULT NULL, -- not used fk_bank_account integer DEFAULT NULL, model_pdf varchar(50) DEFAULT NULL ) ENGINE=innodb; diff --git a/htdocs/langs/en_US/trips.lang b/htdocs/langs/en_US/trips.lang index b5e950b6a0c..c31b902805e 100644 --- a/htdocs/langs/en_US/trips.lang +++ b/htdocs/langs/en_US/trips.lang @@ -1,4 +1,6 @@ # Dolibarr language file - Source file is en_US - trips +ExpenseReport=Expense report +ExpenseReports=Expense reports Trip=Expense report Trips=Expense reports TripsAndExpenses=Expenses reports @@ -14,6 +16,7 @@ FeesKilometersOrAmout=Amount or kilometers DeleteTrip=Delete expense report ConfirmDeleteTrip=Are you sure you want to delete this expense report ? ListTripsAndExpenses=List of expense reports +ListToApprove=Waiting for approval ExpensesArea=Expense reports area SearchATripAndExpense=Search an expense report ClassifyRefunded=Classify 'Refunded' @@ -28,10 +31,12 @@ DeleteLine=Delete a ligne of the expense report ConfirmDeleteLine=Are you sure you want to delete this line ? TF_OTHER=Other +TF_TRANSPORTATION=Transportation TF_LUNCH=Lunch TF_METRO=Metro TF_TRAIN=Train TF_BUS=Bus +TF_CAR=Car TF_PEAGE=Toll TF_ESSENCE=Fuel TF_HOTEL=Hostel diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index 0b80c7b9cd7..d73187ce822 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -421,7 +421,7 @@ class Project extends CommonObject } if ($type == 'expensereport') { - $sql = "SELECT e.rowid FROM " . MAIN_DB_PREFIX . "expensereport as e, " . MAIN_DB_PREFIX . "expensereport_det as ed WHERE e.rowid = ed.fk_expensereport AND ed.fk_projet=" . $this->id; + $sql = "SELECT ed.rowid FROM " . MAIN_DB_PREFIX . "expensereport as e, " . MAIN_DB_PREFIX . "expensereport_det as ed WHERE e.rowid = ed.fk_expensereport AND ed.fk_projet=" . $this->id; } if ($dates > 0) { @@ -511,7 +511,7 @@ class Project extends CommonObject break; } } - + // Delete tasks if (! $error) { diff --git a/htdocs/projet/element.php b/htdocs/projet/element.php index 226f4afb573..68978cc671f 100644 --- a/htdocs/projet/element.php +++ b/htdocs/projet/element.php @@ -44,11 +44,12 @@ if (! empty($conf->agenda->enabled)) require_once DOL_DOCUMENT_ROOT.'/comm/ $langs->load("projects"); $langs->load("companies"); $langs->load("suppliers"); -if (! empty($conf->facture->enabled)) $langs->load("bills"); -if (! empty($conf->commande->enabled)) $langs->load("orders"); -if (! empty($conf->propal->enabled)) $langs->load("propal"); -if (! empty($conf->ficheinter->enabled)) $langs->load("interventions"); -if (! empty($conf->deplacement->enabled)) $langs->load("trips"); +if (! empty($conf->facture->enabled)) $langs->load("bills"); +if (! empty($conf->commande->enabled)) $langs->load("orders"); +if (! empty($conf->propal->enabled)) $langs->load("propal"); +if (! empty($conf->ficheinter->enabled)) $langs->load("interventions"); +if (! empty($conf->deplacement->enabled)) $langs->load("trips"); +if (! empty($conf->expensereport->enabled)) $langs->load("trips"); $projectid=GETPOST('id','int'); $ref=GETPOST('ref','alpha'); @@ -237,10 +238,10 @@ $listofreferent=array( 'name'=>"ExpenseReports", 'title'=>"ListExpenseReportsAssociatedProject", 'class'=>'ExpenseReportLine', - 'table'=>'expensereport', + 'table'=>'expensereport_det', 'datefieldname'=>'date', 'margin'=>'minus', - 'disableamount'=>1, + 'disableamount'=>0, 'test'=>$conf->expensereport->enabled && $user->rights->expensereport->lire), 'agenda'=>array( 'name'=>"Agenda", @@ -311,10 +312,12 @@ foreach ($listofreferent as $key => $value) print_titre($langs->trans($title)); $selectList=$formproject->select_element($tablename,$project->thirdparty->id); - - if (!$selectList || ($selectList<0)) { - setEventMessage($formproject->error,'errors'); - } else { + if (! $selectList || ($selectList<0)) + { + setEventMessages($formproject->error,$formproject->errors,'errors'); + } + else + { print ''; print ''; print ''; @@ -329,9 +332,14 @@ foreach ($listofreferent as $key => $value) print '
'.$langs->trans("Ref").''; diff --git a/htdocs/install/mysql/tables/llx_expensereport.sql b/htdocs/install/mysql/tables/llx_expensereport.sql index e998343e6db..5fd3d2a3998 100755 --- a/htdocs/install/mysql/tables/llx_expensereport.sql +++ b/htdocs/install/mysql/tables/llx_expensereport.sql @@ -41,6 +41,7 @@ CREATE TABLE llx_expensereport ( note text, note_private text, fk_user_valid integer DEFAULT NULL, + fk_user_approve integer DEFAULT NULL, fk_user_paid integer DEFAULT NULL, detail_refuse varchar(255) DEFAULT NULL, date_cancel datetime, diff --git a/htdocs/install/mysql/tables/llx_expensereport_det.sql b/htdocs/install/mysql/tables/llx_expensereport_det.sql index 98e7c33265e..418f1ce6cc5 100644 --- a/htdocs/install/mysql/tables/llx_expensereport_det.sql +++ b/htdocs/install/mysql/tables/llx_expensereport_det.sql @@ -21,7 +21,7 @@ CREATE TABLE llx_expensereport_det rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY, fk_expensereport integer NOT NULL, fk_c_type_fees integer NOT NULL, - fk_projet integer NOT NULL, + fk_projet integer, fk_c_tva integer NOT NULL, comments text NOT NULL, product_type integer DEFAULT -1, diff --git a/htdocs/langs/en_US/suppliers.lang b/htdocs/langs/en_US/suppliers.lang index 5919ffea61e..fb7dbd26032 100644 --- a/htdocs/langs/en_US/suppliers.lang +++ b/htdocs/langs/en_US/suppliers.lang @@ -30,7 +30,7 @@ ExportDataset_fournisseur_2=Supplier invoices and payments ExportDataset_fournisseur_3=Supplier orders and order lines ApproveThisOrder=Approve this order ConfirmApproveThisOrder=Are you sure you want to approve order %s ? -DenyingThisOrder=Denying this order +DenyingThisOrder=Deny this order ConfirmDenyingThisOrder=Are you sure you want to deny this order %s ? ConfirmCancelThisOrder=Are you sure you want to cancel this order %s ? AddCustomerOrder=Create customer order diff --git a/htdocs/langs/en_US/trips.lang b/htdocs/langs/en_US/trips.lang index e34f58715d8..b5e950b6a0c 100644 --- a/htdocs/langs/en_US/trips.lang +++ b/htdocs/langs/en_US/trips.lang @@ -37,71 +37,63 @@ TF_ESSENCE=Fuel TF_HOTEL=Hostel TF_TAXI=Taxi -ErrorDoubleDeclaration=ERREUR : Vous avez déclaré au moins une note de frais dans le même intervalle. -ListTripsAndExpenses=Liste des notes de frais -AucuneNDF=Il n'y a aucune note de frais déclarée correspondante à votre recherche! -AucuneLigne=Il n'y a aucune ligne de déclarée dans cette note de frais! -AddLine=Ajouter une ligne -AddLineMini=Ajouter -TotalHT=Montant HT -TotalTTC=Montant TTC -TotalTVA=Total TVA +ErrorDoubleDeclaration=You have declared another expense report into a similar date range. +ListTripsAndExpenses=List of expense reports +AucuneNDF=No expense reports found for this criteria +AucuneLigne=There is no expense report declared yet +AddLine=Add a line +AddLineMini=Add -Date_DEBUT=Date de début période -Date_FIN=Date de fin période -ModePaiement=Mode de paiement +Date_DEBUT=Period date start +Date_FIN=Period date end +ModePaiement=Payment mode Note=Note -Project=Projet +Project=Project -VALIDATOR=Utilisateur informé pour validation -VALIDOR=Validée par -AUTHOR=Enregistrée par -AUTHORPAIEMENT=Payée par -REFUSEUR=Refusée par -CANCEL_USER=Annulée par +VALIDATOR=User to inform for approbation +VALIDOR=Approved by +AUTHOR=Recorded by +AUTHORPAIEMENT=Paied by +REFUSEUR=Denied by +CANCEL_USER=Canceled by -MOTIF_REFUS=Motif de refus -MOTIF_CANCEL=Motif d'annulation +MOTIF_REFUS=Reason +MOTIF_CANCEL=Reason -DATE_REFUS=Date du refus -DATE_CANCEL=Date annulation -DATE_VALIDE=Date de validation -DATE_PAIEMENT=Date de paiement -DATE_SAVE=Date d'enregistrement +DATE_REFUS=Deny date +DATE_CANCEL=Cancelation date +DATE_VALIDE=Validation date +DATE_PAIEMENT=Payment date +DATE_SAVE=Recording date -REFUSE=Refuse +Deny=Deny TO_PAID=Pay BROUILLONNER=Reopen SendToValid=Sent to approve ModifyInfoGen=Edit +ValidateAndSubmit=Validate and submit for approval -NOT_VALIDATOR=Vous n'êtes pas la personne habilitée à valider cette note de frais! -NOT_AUTHOR=Vous n'êtes pas l'auteur de cette note de frais, impossible de réaliser l'opération voulue! -NOT_VALIDOR=Vous n'êtes pas le valideur de cette note de frais, vous ne pouvez donc pas réaliser cette opération! -NotUserRightToView=Vous n'avez pas le droit d'afficher cette note de frais. +NOT_VALIDATOR=You are not allowed to approve this expense report +NOT_AUTHOR=You are not the author of this expense report. Operation cancelled. -RefuseTrip=Refuser une note de frais -ConfirmRefuseTrip=Êtes vous sûr de vouloir refuser cette note de frais ? +RefuseTrip=Deny an expense report +ConfirmRefuseTrip=Are you sure you want to deny this expense report ? -ValideTrip=Valider une note de frais -ConfirmValideTrip=Êtes vous sûr de vouloir valider cette note de frais ? +ValideTrip=Approve expense report +ConfirmValideTrip=Are you sure you want to approve this expense report ? -PaidTrip=Payer une note de frais -ConfirmPaidTrip=Êtes vous sûr de vouloir payer cette note de frais ? +PaidTrip=Pay an expense report +ConfirmPaidTrip=Are you sure you want to change status of this expense report to "Paid" ? -CancelTrip=Annuler une note de frais -ConfirmCancelTrip=Êtes vous sûr de vouloir annuler cette note de frais ? +CancelTrip=Cancel an expense report +ConfirmCancelTrip=Are you sure you want to cancel this expense report ? -BrouillonnerTrip=Remettre une note de frais en brouillon -ConfirmBrouillonnerTrip=Êtes vous sûr de vouloir remettre cette note de frais en brouillon ? +BrouillonnerTrip=Move back expense report to status "Draft"n +ConfirmBrouillonnerTrip=Are you sure you want to move this expense report to status "Draft" ? -SaveTrip=Enregistrement de votre note de frais -ConfirmSaveTrip=Êtes vous sûr de vouloir enregistrer cette note de frais? (elle sera transmise par mail pour validation) +SaveTrip=Validate expense report +ConfirmSaveTrip=Are you sure you want to validate this expense report ? -INFOS_DATES=Infos Workflow -INFOS_NDF=Infos générales note de frais - -StatsTrip=Statistiques Synchro_Compta=NDF <-> Compte TripSynch=Synchronisation : Notes de frais <-> Compte courant diff --git a/htdocs/langs/fr_FR/expensereport.lang b/htdocs/langs/fr_FR/expensereport.lang deleted file mode 100755 index 6af74164f2d..00000000000 --- a/htdocs/langs/fr_FR/expensereport.lang +++ /dev/null @@ -1,137 +0,0 @@ -# Dolibarr language file - fr_FR - trips -CHARSET=UTF-8 -Trip=Note de frais -Trips=Notes de frais -TripsAndExpenses=Notes de frais -TripId=Id note de frais -TripCard=Fiche note de frais -AddTrip=Ajouter note de frais -ListOfTrips=Liste des notes de frais -ListOfFees=Liste des notes de frais -NewTrip=Nouvelle note de frais -CancelAddTrip=Annuler -ExportTripCSV=Exporter en CSV -AnyOtherInThisListCanValidate=Toute personne dans la liste pourra valider. Le choix détermine qui sera informé. -TripSociete=Informations société -TripSalarie=Informations salarié -TripNDF=Informations note de frais - -DeleteTrip=Supprimer note de frais -ConfirmDeleteTrip=Êtes vous sûr de vouloir supprimer cette note de frais ? - -DeleteLine=Supprimer une ligne de la note de frais -ConfirmDeleteLine=Êtes vous sûr de vouloir supprimer cette ligne ? - -TF_OTHER=Autre -TF_LUNCH=Repas -TF_METRO=Métro -TF_TRAIN=Train -TF_RATP=Ratp -TF_BUS=Bus -TF_PEAGE=Péage -TF_ESSENCE=Essence -TF_SNCF=SNCF (Autre) -TF_HOTEL=Hôtel -TF_TRANSPORT=SNCF (Train) -TF_TAXI=Taxi - -ErrorDoubleDeclaration=ERREUR : Vous avez déclaré au moins une note de frais dans le même intervalle. -ListTripsAndExpenses=Liste des notes de frais -AucuneNDF=Il n'y a aucune note de frais déclarée correspondante à votre recherche! -AucuneLigne=Il n'y a aucune ligne de déclarée dans cette note de frais! -AddLine=Ajouter une ligne -AddLineMini=Ajouter -TotalHT=Montant HT -TotalTTC=Montant TTC -TotalTVA=Total TVA - -Date_DEBUT=Date de début période -Date_FIN=Date de fin période -ModePaiement=Mode de paiement -Note=Note -Project=Projet - -VALIDATOR=Utilisateur informé pour validation -VALIDOR=Validée par -AUTHOR=Enregistrée par -AUTHORPAIEMENT=Payée par -REFUSEUR=Refusée par -CANCEL_USER=Annulée par - -MOTIF_REFUS=Motif de refus -MOTIF_CANCEL=Motif d'annulation - -DATE_REFUS=Date du refus -DATE_CANCEL=Date annulation -DATE_VALIDE=Date de validation -DATE_PAIEMENT=Date de paiement -DATE_SAVE=Date d'enregistrement - -VALIDATE=Valider -REFUSE=Refuser -CANCEL=Annuler -TO_PAID=Payer -BROUILLONNER=Remettre en brouillon -SendToValid=Envoyer en validation -ModifyInfoGen=Modifier les infos générales - -Module20130304Name=Notes de frais -Module20130304Desc=Gestion des notes de frais et déplacement (par ') - -NOT_VALIDATOR=Vous n'êtes pas la personne habilitée à valider cette note de frais! -NOT_AUTHOR=Vous n'êtes pas l'auteur de cette note de frais, impossible de réaliser l'opération voulue! -NOT_VALIDOR=Vous n'êtes pas le valideur de cette note de frais, vous ne pouvez donc pas réaliser cette opération! -NotUserRightToView=Vous n'avez pas le droit d'afficher cette note de frais. - -RefuseTrip=Refuser une note de frais -ConfirmRefuseTrip=Êtes vous sûr de vouloir refuser cette note de frais ? - -ValideTrip=Valider une note de frais -ConfirmValideTrip=Êtes vous sûr de vouloir valider cette note de frais ? - -PaidTrip=Payer une note de frais -ConfirmPaidTrip=Êtes vous sûr de vouloir payer cette note de frais ? - -CancelTrip=Annuler une note de frais -ConfirmCancelTrip=Êtes vous sûr de vouloir annuler cette note de frais ? - -BrouillonnerTrip=Remettre une note de frais en brouillon -ConfirmBrouillonnerTrip=Êtes vous sûr de vouloir remettre cette note de frais en brouillon ? - -SaveTrip=Enregistrement de votre note de frais -ConfirmSaveTrip=Êtes vous sûr de vouloir enregistrer cette note de frais? (elle sera transmise par mail pour validation) - -INFOS_DATES=Infos Workflow -INFOS_NDF=Infos générales note de frais - -EURO=€ -PriceUNITAIRE=Prix U. (TTC) - -StatsTrip=Statistiques -Synchro_Compta=NDF <-> Compte - -TripSynch=Synchronisation : Notes de frais <-> Compte courant -TripToSynch=Notes de frais à intégrer dans la compta -AucuneTripToSynch=Aucune note de frais n'est en statut "Payée". -ViewAccountSynch=Voir le compte - -ConfirmNdfToAccount=Êtes-vous sûr de vouloir intégrer cette note de frais dans le compte courant? -ndfToAccount=Note de frais - Intégration - -ConfirmAccountToNdf=Êtes-vous sûr de vouloir retirer cette note de frais du compte courant? -AccountToNdf=Note de frais - Retrait - -USER_AUTHOR=Auteur -PU=P.U. -Q=Q - -LINE_NOT_ADDED=Ligne non ajoutée : -NO_PROJECT=Aucun projet sélectionné. -NO_DATE=Aucune date sélectionnée. -NO_PRICE=Aucun prix indiqué. - -TripForValid=à Valider -TripForPaid=à Payer -TripPaid=Payée - -NoTripsToExportCSV=Il n'y a pas de notes de frais à exporter pour cette période. \ No newline at end of file diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index 1103396658f..0f6a74f1a48 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -466,7 +466,7 @@ if ($action == 'create' && $user->rights->projet->creer) // Budget print '
'.$langs->trans("Budget").'
'.$langs->trans("DATE_SAVE").''.$object->date_create.'
'.dol_print_date($object->date_create,'dayhour').'
'.$object->date_paiement.'
'.$langs->trans("VALIDATOR").'
'.$langs->trans("DATE_CANCEL").''.$object->date_cancel.'
'.dol_print_date($object->date_cancel,'dayhour').'
'.$langs->trans("VALIDOR").''.$langs->trans("Approbator").''; - if ($object->fk_user_valid > 0) + if ($object->fk_user_approve > 0) { - $userfee=new User($db); - $userfee->fetch($object->fk_user_valid); - print $userfee->getNomUrl(1); + $userapp=new User($db); + $userapp->fetch($object->fk_user_approve); + print $userapp->getNomUrl(1); } print '
'.$langs->trans("DATE_VALIDE").''.$object->date_valide.'
'.$langs->trans("DateApprove").''.dol_print_date($object->date_approve,'dayhour').'
'.$langs->trans("DATE_REFUS").''.$object->date_refuse; + print ''.dol_print_date($object->date_refuse,'dayhour'); if ($object->detail_refuse) print ' - '.$object->detail_refuse; print '
'.$objp->ref.''.dol_print_date($db->jdate($objp->date_valide),'day').''.dol_print_date($db->jdate($objp->date_valid),'day').''.img_object($langs->trans("ShowUser"),"user").' '.$objp->declarant_NDF.''.$objp->total_ttc.' '.$langs->trans("EURO").'
'; print ''; - print ''; + print ''; + print ''; print ''; - print ''; + // Thirdparty or user + print ''; if (empty($value['disableamount'])) print ''; else print ''; if (empty($value['disableamount'])) print ''; @@ -360,7 +368,17 @@ foreach ($listofreferent as $key => $value) for ($i = 0; $i < $num; $i++) { $element->fetch($elementarray[$i]); - $element->fetch_thirdparty(); + + if ($tablename != 'expensereport_det') + { + $element->fetch_thirdparty(); + } + else + { + $expensereport=new ExpenseReport($db); + $expensereport->fetch($element->fk_expensereport); + } + //print $classname; if ($breakline && $saved_third_id != $element->thirdparty->id) @@ -384,12 +402,17 @@ foreach ($listofreferent as $key => $value) $var=!$var; print ""; - print '\n"; // Ref print '\n"; // Date @@ -403,9 +426,15 @@ foreach ($listofreferent as $key => $value) } print ''; - // Third party + // Third party or user print ''; // Amount without tax @@ -431,7 +460,10 @@ foreach ($listofreferent as $key => $value) else print ''; // Status - print ''; + print ''; print ''; @@ -520,13 +552,15 @@ foreach ($listofreferent as $key => $value) } } -// Profit for all project + +// Show profit summary for whole project + $langs->load("suppliers"); $langs->load("bills"); $langs->load("orders"); $langs->load("proposals"); $langs->load("margins"); -print_fiche_titre($langs->trans("Profit"),'',''); +print_fiche_titre($langs->trans("Profit"),''); print '
'.$langs->trans("Ref").''.$langs->trans("Ref").''.$langs->trans("Date").''.$langs->trans("ThirdParty").''; + if ($tablename == 'expensereport_det') print $langs->trans("User"); + else print $langs->trans("ThirdParty"); + print ''.$langs->trans("AmountHT").''.$langs->trans("AmountTTC").'
'; + print ''; print '' . img_picto($langs->trans('Unlink'), 'editdelete') . ''; print "'; - print $element->getNomUrl(1); + + if ($tablename == 'expensereport_det') + { + print $expensereport->getNomUrl(1); + } + else print $element->getNomUrl(1); print "'.dol_print_date($date,'day').''; if (is_object($element->thirdparty)) print $element->thirdparty->getNomUrl(1,'',48); + else if ($tablename == 'expensereport_det') + { + $tmpuser=new User($db); + $tmpuser->fetch($expensereport->fk_user_author); + print $tmpuser->getNomUrl(1,'',48); + } print ''.$element->getLibStatut(5).''; + if ($tablename == 'expensereport_det') print $expensereport->getLibStatut(5); + else print $element->getLibStatut(5); + print '
'; print ''; print ''; @@ -543,7 +577,7 @@ foreach ($listofreferent as $key => $value) $tablename=$value['table']; $qualified=$value['test']; $margin = $value['margin']; - if (isset($margin)) + if ($qualified && isset($margin)) // If this element must be included into profit calculation ($margin is 'minus' or 'plus') { $element = new $classname($db); @@ -557,13 +591,10 @@ foreach ($listofreferent as $key => $value) for ($i = 0; $i < $num; $i++) { $element->fetch($elementarray[$i]); - $element->fetch_thirdparty(); - //print $classname; - if ($qualified) - { - $total_ht = $total_ht + $element->total_ht; - $total_ttc = $total_ttc + $element->total_ttc; - } + if ($tablename != 'expensereport_det') $element->fetch_thirdparty(); + + $total_ht = $total_ht + $element->total_ht; + $total_ttc = $total_ttc + $element->total_ttc; } print ''; From 6d1324b46330712566923a51ca609e90166c4e4c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 21 Feb 2015 16:15:54 +0100 Subject: [PATCH 169/173] Work on expense report module --- htdocs/core/actions_sendmails.inc.php | 8 +- htdocs/core/lib/functions.lib.php | 6 +- .../core/modules/modExpenseReport.class.php | 4 +- htdocs/expensereport/card.php | 140 ++++++++++-------- .../class/expensereport.class.php | 36 +---- .../class/expensereportstats.class.php | 13 +- htdocs/expensereport/index.php | 8 +- htdocs/expensereport/list.php | 15 +- htdocs/expensereport/stats/index.php | 4 +- htdocs/langs/en_US/trips.lang | 3 +- htdocs/user/class/user.class.php | 4 +- 11 files changed, 120 insertions(+), 121 deletions(-) diff --git a/htdocs/core/actions_sendmails.inc.php b/htdocs/core/actions_sendmails.inc.php index 80385d34735..cc898d02c85 100644 --- a/htdocs/core/actions_sendmails.inc.php +++ b/htdocs/core/actions_sendmails.inc.php @@ -210,19 +210,17 @@ if (($action == 'send' || $action == 'relance') && ! $_POST['addfile'] && ! $_PO else { $langs->load("other"); - $mesg='
'; if ($mailfile->error) { + $mesg=''; $mesg.=$langs->trans('ErrorFailedToSendMail',$from,$sendto); $mesg.='
'.$mailfile->error; + setEventMessage($mesg,'errors'); } else { - $mesg.='No mail sent. Feature is disabled by option MAIN_DISABLE_ALL_MAILS'; + setEventMessage('No mail sent. Feature is disabled by option MAIN_DISABLE_ALL_MAILS', 'warnings'); } - $mesg.='
'; - - setEventMessage($mesg,'warnings'); $action = 'presend'; } } diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 6355a871e8e..537cf68986b 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -4189,15 +4189,15 @@ function get_date_range($date_start,$date_end,$format = '',$outputlangs='', $wit if ($date_start && $date_end) { - $out.= ($withparenthesis?' (':'').$outputlangs->trans('DateFromTo',dol_print_date($date_start, $format, false, $outputlangs),dol_print_date($date_end, $format, false, $outputlangs)).($withparenthesis?')':''); + $out.= ($withparenthesis?' (':'').$outputlangs->transnoentitiesnoconv('DateFromTo',dol_print_date($date_start, $format, false, $outputlangs),dol_print_date($date_end, $format, false, $outputlangs)).($withparenthesis?')':''); } if ($date_start && ! $date_end) { - $out.= ($withparenthesis?' (':'').$outputlangs->trans('DateFrom',dol_print_date($date_start, $format, false, $outputlangs)).($withparenthesis?')':''); + $out.= ($withparenthesis?' (':'').$outputlangs->transnoentitiesnoconv('DateFrom',dol_print_date($date_start, $format, false, $outputlangs)).($withparenthesis?')':''); } if (! $date_start && $date_end) { - $out.= ($withparenthesis?' (':'').$outputlangs->trans('DateUntil',dol_print_date($date_end, $format, false, $outputlangs)).($withparenthesis?')':''); + $out.= ($withparenthesis?' (':'').$outputlangs->transnoentitiesnoconv('DateUntil',dol_print_date($date_end, $format, false, $outputlangs)).($withparenthesis?')':''); } return $out; diff --git a/htdocs/core/modules/modExpenseReport.class.php b/htdocs/core/modules/modExpenseReport.class.php index b5b45ea23f8..1bf00f86f31 100755 --- a/htdocs/core/modules/modExpenseReport.class.php +++ b/htdocs/core/modules/modExpenseReport.class.php @@ -162,7 +162,7 @@ class modExpenseReport extends DolibarrModules $this->rights[6][1] = 'Approve expense reports'; $this->rights[6][2] = 'w'; $this->rights[6][3] = 0; - $this->rights[6][4] = 'to_validate'; + $this->rights[6][4] = 'approve'; $this->rights[7][0] = 776; $this->rights[7][1] = 'Pay expense reports'; @@ -267,7 +267,7 @@ class modExpenseReport extends DolibarrModules 'langs'=>'trips', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. 'position'=>100, 'enabled'=>'$conf->expensereport->enabled', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. - 'perms'=>'$user->rights->expensereport->lire', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules + 'perms'=>'$user->rights->expensereport->approve', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules 'target'=>'', 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both $r++; diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index cfe3c86058b..75ab8b7cb45 100755 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -70,6 +70,11 @@ if (! empty($conf->multicompany->enabled) && ! empty($conf->entity) && $conf->en $conf->expensereport->dir_output = $rootfordata.'/expensereport'; $conf->expensereport->dir_output = $rootfordata.'/expensereport'; +// Define $urlwithroot +$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root)); +$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file +//$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current + /* @@ -166,67 +171,74 @@ if ($action == "confirm_save" && GETPOST("confirm") == "yes" && $id > 0 && $user $object = new ExpenseReport($db); $object->fetch($id); $result = $object->setValidate($user); - if ($result > 0) + if ($result > 0 && $object->fk_user_validator > 0) { - // Send mail - if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) + $langs->load("mails"); + + // TO + $destinataire = new User($db); + $destinataire->fetch($object->fk_user_validator); + $emailTo = $destinataire->email; + + // FROM + $expediteur = new User($db); + $expediteur->fetch($object->fk_user_author); + $emailFrom = $expediteur->email; + + // SUBJECT + $subject = $langs->trans("ExpenseReportWaitingForApproval"); + + // CONTENT + $link = $urlwithroot.'/expenserecord/card.php?id='.$object->id; + $message = $langs->trans("ExpenseReportWaitingForApprovalMessage", $expediteur->getFullName($langs), get_date_range($object->date_debut,$object->date_fin,'',$langs), $link); + + // Rebuild pdf + /* + $object->setDocModel($user,""); + $resultPDF = expensereport_pdf_create($db,$id,'',"",$langs); + + if($resultPDF): + // ATTACHMENT + $filename=array(); $filedir=array(); $mimetype=array(); + array_push($filename,dol_sanitizeFileName($object->ref).".pdf"); + array_push($filedir,$conf->expensereport->dir_output . "/" . dol_sanitizeFileName($object->ref) . "/" . dol_sanitizeFileName($object->ref).".pdf"); + array_push($mimetype,"application/pdf"); + */ + + // PREPARE SEND + $mailfile = new CMailFile($subject,$emailTo,$emailFrom,$message,$filedir,$mimetype,$filename); + + if ($mailfile) { - // Send mail - - // TO - $destinataire = new User($db); - $destinataire->fetch($object->fk_user_validator); - $emailTo = $destinataire->email; - - // FROM - $expediteur = new User($db); - $expediteur->fetch($object->fk_user_author); - $emailFrom = $expediteur->email; - - // SUBJECT - $subject = "' ERP - Note de frais à valider"; - - // CONTENT - $message = "Bonjour {$destinataire->firstname},\n\n"; - $message.= "Veuillez trouver en pièce jointe une nouvelle note de frais à valider.\n"; - $message.= "- Déclarant : {$expediteur->firstname} {$expediteur->lastname}\n"; - $message.= "- Période : du {$object->date_debut} au {$object->date_fin}\n"; - $message.= "- Lien : {$dolibarr_main_url_root}/expensereport/card.php?id={$object->id}\n\n"; - $message.= "Bien cordialement,\n' SI"; - - // Génération du pdf avant attachement - $object->setDocModel($user,""); - $resultPDF = expensereport_pdf_create($db,$id,'',"",$langs); - - if($resultPDF): - // ATTACHMENT - $filename=array(); $filedir=array(); $mimetype=array(); - array_push($filename,dol_sanitizeFileName($object->ref).".pdf"); - array_push($filedir,$conf->expensereport->dir_output . "/" . dol_sanitizeFileName($object->ref) . "/" . dol_sanitizeFileName($object->ref).".pdf"); - array_push($mimetype,"application/pdf"); - - // PREPARE SEND - $mailfile = new CMailFile($subject,$emailTo,$emailFrom,$message,$filedir,$mimetype,$filename); - - if(!$mailfile->error): - // SEND $result=$mailfile->sendfile(); - if ($result): - Header("Location: ".$_SEVER["PHP_SELF"]."?id=".$id); - exit; - endif; - - else: - - $mesg="Impossible d'envoyer l'email."; - - endif; - // END - Send mail - else: - dol_print_error($db,$resultPDF); - exit; - endif; + if ($result) + { + $mesg=$langs->trans('MailSuccessfulySent',$mailfile->getValidAddress($emailFrom,2),$mailfile->getValidAddress($emailTo,2)); + setEventMessage($mesg); + header("Location: ".$_SEVER["PHP_SELF"]."?id=".$id); + exit; + } + else + { + $langs->load("other"); + if ($mailfile->error) + { + $mesg=''; + $mesg.=$langs->trans('ErrorFailedToSendMail',$from,$sendto); + $mesg.='
'.$mailfile->error; + setEventMessage($mesg,'errors'); + } + else + { + setEventMessage('No mail sent. Feature is disabled by option MAIN_DISABLE_ALL_MAILS', 'warnings'); + } + } + } + else + { + setEventMessages($mailfile->error,$mailfile->errors,'errors'); + $action=''; } } else @@ -311,7 +323,7 @@ if ($action == "confirm_save_from_refuse" && GETPOST("confirm") == "yes" && $id } // Approve -if ($action == "confirm_validate" && GETPOST("confirm") == "yes" && $id > 0 && $user->rights->expensereport->to_validate) +if ($action == "confirm_approve" && GETPOST("confirm") == "yes" && $id > 0 && $user->rights->expensereport->approve) { $object = new ExpenseReport($db); $object->fetch($id); @@ -394,7 +406,7 @@ if ($action == "confirm_validate" && GETPOST("confirm") == "yes" && $id > 0 && $ } } -if ($action == "confirm_refuse" && GETPOST('confirm')=="yes" && $id > 0 && $user->rights->expensereport->to_validate) +if ($action == "confirm_refuse" && GETPOST('confirm')=="yes" && $id > 0 && $user->rights->expensereport->approve) { $object = new ExpenseReport($db); $object->fetch($id); @@ -1120,7 +1132,7 @@ else endif; if ($action == 'validate'): - $ret=$form->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("ValideTrip"),$langs->trans("ConfirmValideTrip"),"confirm_validate","","",1); + $ret=$form->form_confirm($_SEVER["PHP_SELF"]."?id=".$id,$langs->trans("ValideTrip"),$langs->trans("ConfirmValideTrip"),"confirm_approve","","",1); if ($ret == 'html') print '
'; endif; @@ -1633,7 +1645,7 @@ if ($action != 'create' && $action != 'edit') } /* Si l'état est "En attente d'approbation" - * ET user à droit de "to_validate" + * ET user à droit de "approve" * ET fk_user_validator == user courant * Afficher : "Valider" / "Refuser" / "Supprimer" */ @@ -1646,7 +1658,7 @@ if ($action != 'create' && $action != 'edit') } } - if ($user->rights->expensereport->to_validate && $object->fk_c_expensereport_statuts == 2) + if ($user->rights->expensereport->approve && $object->fk_c_expensereport_statuts == 2) { //if($object->fk_user_validator==$user->id) //{ @@ -1692,11 +1704,11 @@ if ($action != 'create' && $action != 'edit') } /* Si l'état est "Payée" - * ET user à droit "to_validate" + * ET user à droit "approve" * ET user à droit "to_paid" * Afficher : "Annuler" */ - if ($user->rights->expensereport->to_validate && $user->rights->expensereport->to_paid && $object->fk_c_expensereport_statuts==6) + if ($user->rights->expensereport->approve && $user->rights->expensereport->to_paid && $object->fk_c_expensereport_statuts==6) { // Annuler print ''.$langs->trans('Cancel').''; diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php index 40be7298a1c..2523ef34154 100755 --- a/htdocs/expensereport/class/expensereport.class.php +++ b/htdocs/expensereport/class/expensereport.class.php @@ -790,7 +790,7 @@ class ExpenseReport extends CommonObject } /** - * set_to_validate + * set_save_from_refuse * * @param User $user User * @return int <0 if KO, >0 if OK @@ -971,38 +971,6 @@ class ExpenseReport extends CommonObject } } - /** - * set_to_validate - * - * @param User $user User - * @return int <0 if KO, >0 if OK - */ - function set_to_valide($user) - { - if ($this->fk_c_expensereport_statuts != 2) - { - $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; - $sql.= " SET fk_c_expensereport_statuts = 2, fk_user_validator = ".$this->fk_user_validator; - $sql.= ' WHERE rowid = '.$this->id; - - dol_syslog(get_class($this)."::set_to_valide sql=".$sql, LOG_DEBUG); - - if ($this->db->query($sql)) - { - return 1; - } - else - { - $this->error=$this->db->error(); - return -1; - } - } - else - { - dol_syslog(get_class($this)."::set_to_valide expensereport already with to-valide status", LOG_WARNING); - } - } - /** * set_cancel * @@ -1312,7 +1280,7 @@ class ExpenseReport extends CommonObject $sql = "SELECT fk_user"; $sql.= " FROM ".MAIN_DB_PREFIX."user_rights as ur, ".MAIN_DB_PREFIX."rights_def as rd"; - $sql.= " WHERE ur.fk_id = rd.id and module = 'expensereport' AND perms = 'to_validate'"; // Permission 'Approve'; + $sql.= " WHERE ur.fk_id = rd.id and module = 'expensereport' AND perms = 'approve'"; // Permission 'Approve'; dol_syslog(get_class($this)."::fetch_users_approver_expensereport sql=".$sql); $result = $this->db->query($sql); diff --git a/htdocs/expensereport/class/expensereportstats.class.php b/htdocs/expensereport/class/expensereportstats.class.php index e12b4ed2a79..9536d59937d 100644 --- a/htdocs/expensereport/class/expensereportstats.class.php +++ b/htdocs/expensereport/class/expensereportstats.class.php @@ -49,7 +49,7 @@ class ExpenseReportStats extends Stats */ function __construct($db, $socid=0, $userid=0) { - global $conf; + global $conf, $user; $this->db = $db; $this->socid = $socid; @@ -65,7 +65,16 @@ class ExpenseReportStats extends Stats { $this->where.=" AND fk_soc = ".$this->socid; } - if ($this->userid > 0) $this->where.=' AND fk_user_author = '.$this->userid; + + // Only me and subordinates + if (empty($user->rights->expensereport->readall) && empty($user->rights->expensereport->lire_tous)) + { + $childids = $user->getAllChildIds(); + $childids[]=$user->id; + $this->where.=" AND fk_user_author IN (".(join(',',$childids)).")"; + } + + if ($this->userid > 0) $this->where.=' AND fk_user_author = '.$this->userid; } diff --git a/htdocs/expensereport/index.php b/htdocs/expensereport/index.php index 2ea024fb3b0..89469609e2a 100644 --- a/htdocs/expensereport/index.php +++ b/htdocs/expensereport/index.php @@ -69,7 +69,13 @@ $totalnb=$totalsum=0; $sql = "SELECT tf.code, tf.label, count(de.rowid) as nb, sum(de.total_ht) as km"; $sql.= " FROM ".MAIN_DB_PREFIX."expensereport as d, ".MAIN_DB_PREFIX."expensereport_det as de, ".MAIN_DB_PREFIX."c_type_fees as tf"; $sql.= " WHERE de.fk_expensereport = d.rowid AND de.fk_c_type_fees = tf.id"; -if (empty($user->rights->expensereport->readall) && empty($user->rights->expensereport->lire_tous)) $sql.=' AND d.fk_user_author IN ('.join(',',$childids).')'; + +// RESTRICT RIGHTS +if (empty($user->rights->expensereport->readall) && empty($user->rights->expensereport->lire_tous)) +{ + $sql.= " AND d.fk_user_author IN (".join(',',$childids).")\n"; +} + $sql.= " GROUP BY tf.code, tf.label"; $result = $db->query($sql); diff --git a/htdocs/expensereport/list.php b/htdocs/expensereport/list.php index 348c564812e..d71a9410c9f 100755 --- a/htdocs/expensereport/list.php +++ b/htdocs/expensereport/list.php @@ -48,7 +48,7 @@ $html = new Form($db); $formother = new FormOther($db); $expensereporttmp=new ExpenseReport($db); -llxHeader(); +llxHeader('', $langs->trans("ListOfExpenseReports")); $max_year = 5; $min_year = 5; @@ -84,13 +84,14 @@ $sql.= " u.rowid as id_user, u.firstname, u.lastname"; $sql.= " FROM ".MAIN_DB_PREFIX."expensereport d\n"; $sql.= " INNER JOIN ".MAIN_DB_PREFIX."user u ON d.fk_user_author = u.rowid\n"; + + // WHERE if(!empty($search_ref)){ $sql.= " WHERE d.ref LIKE '%".$db->escape($search_ref)."%'\n"; }else{ $sql.= " WHERE 1 = 1\n"; } - // DATE START if ($month_start > 0) { if ($year_start > 0) { @@ -148,13 +149,15 @@ if ($month_start > 0) { } } } - -if (!empty($search_user) && $search_user != -1) $sql.= " AND d.fk_user_author = '$search_user'\n"; +if (!empty($search_user) && $search_user > 0) $sql.= " AND d.fk_user_author = ".$search_user."\n"; if($search_state != '') $sql.= " AND d.fk_c_expensereport_statuts = '$search_state'\n"; // RESTRICT RIGHTS -if (empty($user->rights->expensereport->readall) && empty($user->rights->expensereport->lire_tous)){ - $sql.= " AND d.fk_user_author = '{$user->id}'\n"; +if (empty($user->rights->expensereport->readall) && empty($user->rights->expensereport->lire_tous)) +{ + $childids = $user->getAllChildIds(); + $childids[]=$user->id; + $sql.= " AND d.fk_user_author IN (".join(',',$childids).")\n"; } $sql.= $db->order($sortfield,$sortorder); diff --git a/htdocs/expensereport/stats/index.php b/htdocs/expensereport/stats/index.php index 07843985b00..402eb56e01b 100755 --- a/htdocs/expensereport/stats/index.php +++ b/htdocs/expensereport/stats/index.php @@ -222,7 +222,9 @@ print '
'; */ // User print ''; // Year print '
'.$langs->trans("Element").'
'.$langs->trans("User").''; -print $form->select_dolusers($userid,'userid',1); +$include=''; +if (empty($user->rights->expensereport->readall) && empty($user->rights->expensereport->lire_tous)) $include='hierarchy'; +print $form->select_dolusers($userid,'userid',1,'',0,$include); print '
'.$langs->trans("Year").''; diff --git a/htdocs/langs/en_US/trips.lang b/htdocs/langs/en_US/trips.lang index c31b902805e..e5f683eb8fe 100644 --- a/htdocs/langs/en_US/trips.lang +++ b/htdocs/langs/en_US/trips.lang @@ -20,7 +20,8 @@ ListToApprove=Waiting for approval ExpensesArea=Expense reports area SearchATripAndExpense=Search an expense report ClassifyRefunded=Classify 'Refunded' - +ExpenseReportWaitingForApproval=A new expense report has been submitted for approval +ExpenseReportWaitingForApprovalMessage=A new expense report has been submitted and is waiting for approval.\n- User: %s\n- Period: %s\nClick here to validate: %s TripId=Id expense report AnyOtherInThisListCanValidate=Person to inform for validation. TripSociete=Information company diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 16123c86b9c..babac9c33ba 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -2211,7 +2211,7 @@ class User extends CommonObject /** - * Return and array with all instanciated children users of current user + * Return and array with all instanciated first level children users of current user * * @return void */ @@ -2365,7 +2365,7 @@ class User extends CommonObject } /** - * Return list of all childs users in herarchy. + * Return list of all child users id in herarchy (all sublevels). * * @return array Array of user id lower than user. This overwrite this->users. */ From 2bc6ac4671f6e96c1ee6a03f8c589f65011deae8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 22 Feb 2015 13:16:49 +0100 Subject: [PATCH 170/173] Finished new module to manage expense reports ! Fix export to support corectly multicompany --- htdocs/admin/expensereport.php | 499 ++++++++++++++++++ htdocs/core/class/html.formfile.class.php | 8 +- htdocs/core/lib/expensereport.lib.php | 43 ++ htdocs/core/lib/functions.lib.php | 9 +- .../modules/commande/modules_commande.php | 2 +- .../doc/pdf_standard.modules.php | 456 +++++++++------- .../expensereport/modules_expensereport.php | 72 +-- htdocs/core/modules/modAgenda.class.php | 2 +- htdocs/core/modules/modBanque.class.php | 4 +- htdocs/core/modules/modCategorie.class.php | 12 +- htdocs/core/modules/modCommande.class.php | 2 +- htdocs/core/modules/modContrat.class.php | 6 +- htdocs/core/modules/modDeplacement.class.php | 2 +- htdocs/core/modules/modExpedition.class.php | 2 +- .../core/modules/modExpenseReport.class.php | 39 +- htdocs/core/modules/modFacture.class.php | 4 +- htdocs/core/modules/modFicheinter.class.php | 2 +- htdocs/core/modules/modFournisseur.class.php | 6 +- htdocs/core/modules/modProjet.class.php | 26 +- htdocs/core/modules/modPropale.class.php | 2 +- htdocs/core/modules/modSalaries.class.php | 14 - htdocs/core/modules/modStock.class.php | 2 +- htdocs/core/modules/modTax.class.php | 2 +- htdocs/core/modules/modUser.class.php | 2 +- htdocs/expensereport/card.php | 222 +++++++- .../class/expensereport.class.php | 99 +++- htdocs/exports/export.php | 8 +- .../install/mysql/migration/3.7.0-3.8.0.sql | 2 +- .../mysql/tables/llx_expensereport.sql | 2 +- htdocs/langs/en_US/admin.lang | 2 + htdocs/langs/en_US/trips.lang | 9 +- 31 files changed, 1189 insertions(+), 373 deletions(-) create mode 100644 htdocs/admin/expensereport.php diff --git a/htdocs/admin/expensereport.php b/htdocs/admin/expensereport.php new file mode 100644 index 00000000000..d8b3d727bb5 --- /dev/null +++ b/htdocs/admin/expensereport.php @@ -0,0 +1,499 @@ + + * Copyright (C) 2004-2015 Laurent Destailleur + * Copyright (C) 2004 Sebastien Di Cintio + * Copyright (C) 2004 Benoit Mortier + * Copyright (C) 2005-2014 Regis Houssin + * Copyright (C) 2008 Raphael Bertrand (Resultic) + * Copyright (C) 2011-2013 Juanjo Menent + * Copyright (C) 2011-2013 Philippe Grand + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/admin/expensereport.php + * \ingroup expensereport + * \brief Setup page of module ExpenseReport + */ + +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/expensereport.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php'; + +$langs->load("admin"); +$langs->load("errors"); +$langs->load("trips"); +$langs->load('other'); + +if (! $user->admin) accessforbidden(); + +$action = GETPOST('action','alpha'); +$value = GETPOST('value','alpha'); +$label = GETPOST('label','alpha'); +$scandir = GETPOST('scandir','alpha'); +$type='expensereport'; + + +/* + * Actions + */ +if ($action == 'updateMask') +{ + $maskconst=GETPOST('maskconst','alpha'); + $maskvalue=GETPOST('maskvalue','alpha'); + if ($maskconst) $res = dolibarr_set_const($db,$maskconst,$maskvalue,'chaine',0,'',$conf->entity); + + if (! $res > 0) $error++; + + if (! $error) + { + setEventMessage($langs->trans("SetupSaved")); + } + else + { + setEventMessage($langs->trans("Error"),'errors'); + } +} + +else if ($action == 'specimen') // For fiche inter +{ + $modele= GETPOST('module','alpha'); + + $inter = new ExpenseReport($db); + $inter->initAsSpecimen(); + + // Search template files + $file=''; $classname=''; $filefound=0; + $dirmodels=array_merge(array('/'),(array) $conf->modules_parts['models']); + foreach($dirmodels as $reldir) + { + $file=dol_buildpath($reldir."core/modules/expensereport/doc/pdf_".$modele.".modules.php",0); + if (file_exists($file)) + { + $filefound=1; + $classname = "pdf_".$modele; + break; + } + } + + if ($filefound) + { + require_once $file; + + $module = new $classname($db); + + if ($module->write_file($inter,$langs) > 0) + { + header("Location: ".DOL_URL_ROOT."/document.php?modulepart=expensereport&file=SPECIMEN.pdf"); + return; + } + else + { + setEventMessage($obj->error,'errors'); + dol_syslog($obj->error, LOG_ERR); + } + } + else + { + setEventMessage($langs->trans("ErrorModuleNotFound"),'errors'); + dol_syslog($langs->trans("ErrorModuleNotFound"), LOG_ERR); + } +} + +// Define constants for submodules that contains parameters (forms with param1, param2, ... and value1, value2, ...) +if ($action == 'setModuleOptions') +{ + $post_size=count($_POST); + + $db->begin(); + + for($i=0;$i < $post_size;$i++) + { + if (array_key_exists('param'.$i,$_POST)) + { + $param=GETPOST("param".$i,'alpha'); + $value=GETPOST("value".$i,'alpha'); + if ($param) $res = dolibarr_set_const($db,$param,$value,'chaine',0,'',$conf->entity); + if (! $res > 0) $error++; + } + } + if (! $error) + { + $db->commit(); + setEventMessage($langs->trans("SetupSaved")); + } + else + { + $db->rollback(); + setEventMessage($langs->trans("Error"),'errors'); + } +} + +// Activate a model +else if ($action == 'set') +{ + $ret = addDocumentModel($value, $type, $label, $scandir); +} + +else if ($action == 'del') +{ + $ret = delDocumentModel($value, $type); + if ($ret > 0) + { + if ($conf->global->EXPENSEREPORT_ADDON_PDF == "$value") dolibarr_del_const($db, 'EXPENSEREPORT_ADDON_PDF',$conf->entity); + } +} + +// Set default model +else if ($action == 'setdoc') +{ + if (dolibarr_set_const($db, "EXPENSEREPORT_ADDON_PDF",$value,'chaine',0,'',$conf->entity)) + { + // La constante qui a ete lue en avant du nouveau set + // on passe donc par une variable pour avoir un affichage coherent + $conf->global->EXPENSEREPORT_ADDON_PDF = $value; + } + + // On active le modele + $ret = delDocumentModel($value, $type); + if ($ret > 0) + { + $ret = addDocumentModel($value, $type, $label, $scandir); + } +} + +else if ($action == 'setmod') +{ + // TODO Verifier si module numerotation choisi peut etre active + // par appel methode canBeActivated + + dolibarr_set_const($db, "EXPENSEREPORT_ADDON",$value,'chaine',0,'',$conf->entity); +} + +else if ($action == 'set_EXPENSEREPORT_FREE_TEXT') +{ + $freetext= GETPOST('EXPENSEREPORT_FREE_TEXT','alpha'); + $res = dolibarr_set_const($db, "EXPENSEREPORT_FREE_TEXT",$freetext,'chaine',0,'',$conf->entity); + + if (! $res > 0) $error++; + + if (! $error) + { + setEventMessage($langs->trans("SetupSaved")); + } + else + { + setEventMessage($langs->trans("Error"),'errors'); + } +} + +else if ($action == 'set_EXPENSEREPORT_DRAFT_WATERMARK') +{ + $draft= GETPOST('EXPENSEREPORT_DRAFT_WATERMARK','alpha'); + + $res = dolibarr_set_const($db, "EXPENSEREPORT_DRAFT_WATERMARK",trim($draft),'chaine',0,'',$conf->entity); + + if (! $res > 0) $error++; + + if (! $error) + { + setEventMessage($langs->trans("SetupSaved")); + } + else + { + setEventMessage($langs->trans("Error"),'errors'); + } +} + + + +/* + * View + */ + +$dirmodels=array_merge(array('/'),(array) $conf->modules_parts['models']); + +llxHeader(); + +$form=new Form($db); + +$linkback=''.$langs->trans("BackToModuleList").''; +print_fiche_titre($langs->trans("ExpenseReportsSetup"),$linkback,'setup'); + + +$head=expensereport_admin_prepare_head(); + +dol_fiche_head($head, 'expensereport', $langs->trans("ExpenseReports"), 0, 'trip'); + +// Interventions numbering model +/* +print_titre($langs->trans("FicheinterNumberingModules")); + +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print "\n"; + +clearstatcache(); + +foreach ($dirmodels as $reldir) +{ + $dir = dol_buildpath($reldir."core/modules/fichinter/"); + + if (is_dir($dir)) + { + $handle = opendir($dir); + if (is_resource($handle)) + { + $var=true; + + while (($file = readdir($handle))!==false) + { + if (preg_match('/^(mod_.*)\.php$/i',$file,$reg)) + { + $file = $reg[1]; + $classname = substr($file,4); + + require_once $dir.$file.'.php'; + + $module = new $file; + + if ($module->isEnabled()) + { + // Show modules according to features level + if ($module->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2) continue; + if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) continue; + + $var=!$var; + print ''; + + // Show example of numbering model + print ''."\n"; + + print ''; + + $ficheinter=new Fichinter($db); + $ficheinter->initAsSpecimen(); + + // Info + $htmltooltip=''; + $htmltooltip.=''.$langs->trans("Version").': '.$module->getVersion().'
'; + $nextval=$module->getNextValue($mysoc,$ficheinter); + if ("$nextval" != $langs->trans("NotAvailable")) { // Keep " on nextval + $htmltooltip.=''.$langs->trans("NextValue").': '; + if ($nextval) { + if (preg_match('/^Error/',$nextval) || $nextval=='NotConfigured') + $nextval = $langs->trans($nextval); + $htmltooltip.=$nextval.'
'; + } else { + $htmltooltip.=$langs->trans($module->error).'
'; + } + } + print ''; + + print ''; + } + } + } + closedir($handle); + } + } +} + +print '
'.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("Example").''.$langs->trans("Status").''.$langs->trans("ShortInfo").'
'.$module->nom."\n"; + print $module->info(); + print ''; + $tmp=$module->getExample(); + if (preg_match('/^Error/',$tmp)) print '
'.$langs->trans($tmp).'
'; + elseif ($tmp=='NotConfigured') print $langs->trans($tmp); + else print $tmp; + print '
'; + if ($conf->global->FICHEINTER_ADDON == $classname) + { + print img_picto($langs->trans("Activated"),'switch_on'); + } + else + { + print ''.img_picto($langs->trans("Disabled"),'switch_off').''; + } + print ''; + print $form->textwithpicto('',$htmltooltip,1,0); + print '

'; +*/ + +/* + * Documents models for Interventions + */ + +print_titre($langs->trans("TemplatePDFExpenseReports")); + +// Defini tableau def des modeles +$type='expensereport'; +$def = array(); +$sql = "SELECT nom"; +$sql.= " FROM ".MAIN_DB_PREFIX."document_model"; +$sql.= " WHERE type = '".$type."'"; +$sql.= " AND entity = ".$conf->entity; +$resql=$db->query($sql); +if ($resql) +{ + $i = 0; + $num_rows=$db->num_rows($resql); + while ($i < $num_rows) + { + $array = $db->fetch_array($resql); + array_push($def, $array[0]); + $i++; + } +} +else +{ + dol_print_error($db); +} + + +print ''; +print ''; +print ''; +print ''; +print '\n"; +print '\n"; +print ''; +print ''; +print "\n"; + +clearstatcache(); + +$var=true; +foreach ($dirmodels as $reldir) +{ + $dir = dol_buildpath($reldir."core/modules/expensereport/doc"); + + if (is_dir($dir)) + { + $handle=opendir($dir); + if (is_resource($handle)) + { + while (($file = readdir($handle))!==false) + { + $filelist[]=$file; + } + closedir($handle); + arsort($filelist); + + foreach($filelist as $file) + { + if (preg_match('/\.modules\.php$/i',$file) && preg_match('/^(pdf_|doc_)/',$file)) + { + + if (file_exists($dir.'/'.$file)) + { + $var=!$var; + + $name = substr($file, 4, dol_strlen($file) -16); + $classname = substr($file, 0, dol_strlen($file) -12); + + require_once $dir.'/'.$file; + $module = new $classname($db); + + $modulequalified=1; + if ($module->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2) $modulequalified=0; + if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) $modulequalified=0; + + if ($modulequalified) + { + print ''; + + // Active + if (in_array($name, $def)) + { + print ""; + } + else + { + print ""; + } + + // Default + print "'; + + // Info + $htmltooltip = ''.$langs->trans("Name").': '.$module->name; + $htmltooltip.='
'.$langs->trans("Type").': '.($module->type?$module->type:$langs->trans("Unknown")); + $htmltooltip.='
'.$langs->trans("Width").'/'.$langs->trans("Height").': '.$module->page_largeur.'/'.$module->page_hauteur; + $htmltooltip.='

'.$langs->trans("FeaturesSupported").':'; + $htmltooltip.='
'.$langs->trans("Logo").': '.yn($module->option_logo,1,1); + $htmltooltip.='
'.$langs->trans("PaymentMode").': '.yn($module->option_modereg,1,1); + $htmltooltip.='
'.$langs->trans("PaymentConditions").': '.yn($module->option_condreg,1,1); + $htmltooltip.='
'.$langs->trans("MultiLanguage").': '.yn($module->option_multilang,1,1); + $htmltooltip.='
'.$langs->trans("WatermarkOnDraftOrders").': '.yn($module->option_draft_watermark,1,1); + print ''; + + // Preview + print ''; + + print ''; + } + } + } + } + } + } +} + +print '
'.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("Status")."'.$langs->trans("Default")."'.$langs->trans("ShortInfo").''.$langs->trans("Preview").'
'; + print (empty($module->name)?$name:$module->name); + print "\n"; + if (method_exists($module,'info')) print $module->info($langs); + else print $module->description; + print '\n"; + print 'scandir.'&label='.urlencode($module->name).'">'; + print img_picto($langs->trans("Enabled"),'switch_on'); + print ''; + print "\n"; + print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"),'switch_off').''; + print ""; + if ($conf->global->EXPENSEREPORT_ADDON_PDF == "$name") + { + print img_picto($langs->trans("Default"),'on'); + } + else + { + print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"),'off').''; + } + print ''; + print $form->textwithpicto('',$htmltooltip,-1,0); + print ''; + if ($module->type == 'pdf') + { + print ''.img_object($langs->trans("Preview"),'intervention').''; + } + else + { + print img_object($langs->trans("PreviewNotAvailable"),'generic'); + } + print '
'; + +dol_fiche_end(); + + +llxFooter(); + +$db->close(); diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index 241c44cf5f8..8a47e8a0eb1 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -440,11 +440,11 @@ class FormFile } else if ($modulepart != 'agenda') { - // For normalized standard modules - $file=dol_buildpath('/core/modules/'.$modulepart.'/modules_'.$modulepart.'.php',0); + // For normalized standard modules + $file=dol_buildpath('/core/modules/'.$modulepart.'/modules_'.$modulepart.'.php',0); if (file_exists($file)) { - $res=include_once $file; + $res=include_once $file; } // For normalized external modules else @@ -458,7 +458,7 @@ class FormFile $modellist=call_user_func($class.'::liste_modeles',$this->db); } else - { + { dol_print_error($this->db,'Bad value for modulepart'); return -1; } diff --git a/htdocs/core/lib/expensereport.lib.php b/htdocs/core/lib/expensereport.lib.php index f46e6416ec6..0bd2c0f721b 100644 --- a/htdocs/core/lib/expensereport.lib.php +++ b/htdocs/core/lib/expensereport.lib.php @@ -59,3 +59,46 @@ function expensereport_prepare_head($object) return $head; } + + + +/** + * Return array head with list of tabs to view object informations. + * + * @return array head array with tabs + */ +function expensereport_admin_prepare_head() +{ + global $langs, $conf, $user; + + $h = 0; + $head = array(); + + $h = 0; + + $head[$h][0] = DOL_URL_ROOT."/admin/expensereport.php"; + $head[$h][1] = $langs->trans("ExpenseReports"); + $head[$h][2] = 'expensereport'; + $h++; + + // Show more tabs from modules + // Entries must be declared in modules descriptor with line + // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab + // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab + complete_head_from_modules($conf,$langs,null,$head,$h,'expensereport_admin'); + + /*$head[$h][0] = DOL_URL_ROOT.'/fichinter/admin/fichinter_extrafields.php'; + $head[$h][1] = $langs->trans("ExtraFields"); + $head[$h][2] = 'attributes'; + $h++; + + $head[$h][0] = DOL_URL_ROOT.'/fichinter/admin/fichinterdet_extrafields.php'; + $head[$h][1] = $langs->trans("ExtraFieldsLines"); + $head[$h][2] = 'attributesdet'; + $h++; + */ + + complete_head_from_modules($conf,$langs,null,$head,$h,'expensereport_admin','remove'); + + return $head; +} diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 537cf68986b..ebbe6d0d79c 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -95,13 +95,13 @@ function getDoliDBInstance($type, $host, $user, $pass, $name, $port) } /** - * Get entity to use + * Get list of entity id to use * * @param string $element Current element - * @param int $shared 1=Return shared entities + * @param int $shared 0=Return id of entity, 1=Return id entity + shared entities * @return mixed Entity id(s) to use */ -function getEntity($element=false, $shared=false) +function getEntity($element=false, $shared=0) { global $conf, $mc; @@ -112,12 +112,9 @@ function getEntity($element=false, $shared=false) else { $out=''; - $addzero = array('user', 'usergroup'); if (in_array($element, $addzero)) $out.= '0,'; - $out.= $conf->entity; - return $out; } } diff --git a/htdocs/core/modules/commande/modules_commande.php b/htdocs/core/modules/commande/modules_commande.php index 18a586d3b63..2caf1f905e6 100644 --- a/htdocs/core/modules/commande/modules_commande.php +++ b/htdocs/core/modules/commande/modules_commande.php @@ -160,7 +160,7 @@ abstract class ModeleNumRefCommandes * @param int $hidedesc Hide description * @param int $hideref Hide ref * @return int 0 if KO, 1 if OK - * @deprecated Use the new function generateDocument of Commande class + * @deprecated Use the new function generateDocument of Commande class */ function commande_pdf_create(DoliDB $db, Commande $object, $modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0) { diff --git a/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php b/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php index 2ce272af9ef..bdb19778c87 100755 --- a/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php +++ b/htdocs/core/modules/expensereport/doc/pdf_standard.modules.php @@ -3,7 +3,7 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, @@ -19,10 +19,10 @@ /** * \file htdocs/core/modules/expensereport/doc/pdf_standard.modules.php * \ingroup expensereport - * \brief File of class to generate invoices from standard model + * \brief File of class to generate expense report from standard model */ -dol_include_once("/expensereport/core/modules/expensereport/modules_expensereport.php"); +require_once DOL_DOCUMENT_ROOT.'/core/modules/expensereport/modules_expensereport.php'; require_once(DOL_DOCUMENT_ROOT."/product/class/product.class.php"); require_once(DOL_DOCUMENT_ROOT."/core/lib/functions2.lib.php"); require_once(DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php'); @@ -34,9 +34,25 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; /** * Classe permettant de generer les factures au modele Crabe */ -class pdf_ extends ModeleExpenseReport +class pdf_standard extends ModeleExpenseReport { - var $emetteur; // Objet societe qui emet + var $db; + var $name; + var $description; + var $type; + + var $phpmin = array(4,3,0); // Minimum version of PHP required by module + var $version = 'dolibarr'; + + var $page_largeur; + var $page_hauteur; + var $format; + var $marge_gauche; + var $marge_droite; + var $marge_haute; + var $marge_basse; + + var $emetteur; // Objet societe qui emet /** @@ -51,11 +67,11 @@ class pdf_ extends ModeleExpenseReport $langs->load("main"); $langs->load("trips"); $langs->load("project"); - $langs->load("expensereport@expensereport"); + $langs->load("trips"); $this->db = $db; $this->name = ""; - $this->description = $langs->trans('PDFDescription'); + $this->description = $langs->trans('PDFStandardExpenseReports'); // Dimension page pour format A4 $this->type = 'pdf'; @@ -85,17 +101,16 @@ class pdf_ extends ModeleExpenseReport $this->emetteur=$mysoc; if (empty($this->emetteur->country_code)) $this->emetteur->country_code=substr($langs->defaultlang,-2); // By default, if was not defined - // Defini position des colonnes - // Defini position des colonnes + // Define position of columns $this->posxpiece=$this->marge_gauche+1; $this->posxdesc=20; $this->posxdate=85; $this->posxtype=105; $this->posxprojet=125; $this->posxtva=145; - $this->posxup=158; - $this->posxqty=170; - $this->postotalttc=176; + $this->posxup=162; + $this->posxqty=176; + $this->postotalttc=186; if ($this->page_largeur < 210) // To work with US executive format { $this->posxdate-=20; @@ -124,6 +139,7 @@ class pdf_ extends ModeleExpenseReport * @param int $hidedetails Do not show line details * @param int $hidedesc Do not show desc * @param int $hideref Do not show ref + * @return int 1=OK, 0=KO */ function write_file($object,$outputlangs,$srctemplatepath='',$hidedetails=0,$hidedesc=0,$hideref=0) { @@ -133,40 +149,27 @@ class pdf_ extends ModeleExpenseReport // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO if (! empty($conf->global->MAIN_USE_FPDF)) $outputlangs->charset_output='ISO-8859-1'; - - // Hack to use expensereport dir - $rootfordata = DOL_DATA_ROOT; - $rootforuser = DOL_DATA_ROOT; - // If multicompany module is enabled, we redefine the root of data - //if (! empty($this->multicompany->enabled) && ! empty($this->entity) && $this->entity > 1) - //{ - // $rootfordata.='/'.$this->entity; - //} - $conf->expensereport->dir_output = $rootfordata.'/expensereport'; - $conf->expensereport_->dir_output = $rootfordata.'/expensereport'; - - $outputlangs->load("main"); $outputlangs->load("dict"); $outputlangs->load("trips"); $outputlangs->load("project"); - $outputlangs->load("expensereport@expensereport"); - $default_font_size = pdf_getPDFFontSize($outputlangs); + $nblignes = count($object->lines); - if ($conf->expensereport_->dir_output) + if ($conf->expensereport->dir_output) { - // Definition de l'objet $object (pour compatibilite ascendante) - if (! is_object($object)) + // Definition of $dir and $file + if ($object->specimen) { - $id = $object; - $object = new ExpenseReport($db); - $ret=$object->fetch($id,$user); + $dir = $conf->expensereport->dir_output; + $file = $dir . "/SPECIMEN.pdf"; + } + else + { + $objectref = dol_sanitizeFileName($object->ref); + $dir = $conf->expensereport->dir_output . "/" . $objectref; + $file = $dir . "/" . $objectref . ".pdf"; } - - $objectref = dol_sanitizeFileName($object->ref_number); - $dir = $conf->expensereport_->dir_output . "/" . $objectref; - $file = $dir . "/" . $objectref . ".pdf"; if (! file_exists($dir)) { @@ -181,10 +184,24 @@ class pdf_ extends ModeleExpenseReport if (file_exists($dir)) { - $nblignes = count($object->lines); + // Add pdfgeneration hook + if (! is_object($hookmanager)) + { + include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; + $hookmanager=new HookManager($this->db); + } + $hookmanager->initHooks(array('pdfgeneration')); + $parameters=array('file'=>$file,'object'=>$object,'outputlangs'=>$outputlangs); + global $action; + $reshook=$hookmanager->executeHooks('beforePDFCreation',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks // Create pdf instance $pdf=pdf_getInstance($this->format); + $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance + $heightforinfotot = 50; // Height reserved to output the info and total part + $heightforfreetext= (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT)?$conf->global->MAIN_PDF_FREETEXT_HEIGHT:5); // Height reserved to output the free text on last page + $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin) + $pdf->SetAutoPageBreak(1,0); if (class_exists('TCPDF')) { @@ -205,13 +222,12 @@ class pdf_ extends ModeleExpenseReport $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref_number)); $pdf->SetSubject($outputlangs->transnoentities("Trips")); - $pdf->SetCreator(""); + $pdf->SetCreator("Dolibarr ".DOL_VERSION); $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs))); - $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref_number)." ".$outputlangs->transnoentities("Trips")); + $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("Trips")); if (! empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) $pdf->SetCompression(false); $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right - $pdf->SetAutoPageBreak(1,0); // Positionne $this->atleastonediscount si on a au moins une remise for ($i = 0 ; $i < $nblignes ; $i++) @@ -232,17 +248,29 @@ class pdf_ extends ModeleExpenseReport $pdf->SetTextColor(0,0,0); $tab_top = 95; - $tab_top_newpage = 95; + $tab_top_newpage = (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)?95:10); $tab_height = 110; $tab_height_newpage = 110; // Affiche notes - if (! empty($object->note)) + $notetoshow=empty($object->note_public)?'':$object->note_public; + if (! empty($conf->global->MAIN_ADD_SALE_REP_SIGNATURE_IN_NOTE)) { - $tab_top = 93; + // Get first sale rep + if (is_object($object->thirdparty)) + { + $salereparray=$object->thirdparty->getSalesRepresentatives($user); + $salerepobj=new User($this->db); + $salerepobj->fetch($salereparray[0]['id']); + if (! empty($salerepobj->signature)) $notetoshow=dol_concatdesc($notetoshow, $salerepobj->signature); + } + } + if ($notetoshow) + { + $tab_top = 95; $pdf->SetFont('','', $default_font_size - 1); - $pdf->writeHTMLCell(190, 3, $this->posxdesc-1, $tab_top, dol_htmlentitiesbr($object->note), 0, 1); + $pdf->writeHTMLCell(190, 3, $this->posxpiece-1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1); $nexY = $pdf->GetY(); $height_note=$nexY-$tab_top; @@ -265,11 +293,20 @@ class pdf_ extends ModeleExpenseReport // Loop on each lines for ($i = 0 ; $i < $nblignes ; $i++) { + $piece_comptable = $i +1; + $curY = $nexY; $pdf->SetFont('','', $default_font_size - 1); // Into loop to work with multipage $pdf->SetTextColor(0,0,0); - $piece_comptable = $i +1; + $pdf->setTopMargin($tab_top_newpage); + $pdf->setPageOrientation('', 1, $heightforfooter+$heightforfreetext+$heightforinfotot); // The only function to edit the bottom margin of current page to set it. + $pageposbefore=$pdf->getPage(); + + // Description of product line + $curX = $this->posxdesc-1; + + $showpricebeforepagebreak=1; // Piece comptable $pdf->SetFont('','', $default_font_size - 1); @@ -277,46 +314,50 @@ class pdf_ extends ModeleExpenseReport // Comments $pdf->SetFont('','', $default_font_size - 1); - $pdf->SetXY ($this->posxcomment, $curY); - $pdf->writeHTMLCell($this->posxdate-$this->posxdesc-1, 3, $this->posxdesc-1, $curY, $object->lignes[$i]->comments, 0, 1); + $pdf->SetXY($this->posxcomment, $curY); + $pdf->writeHTMLCell($this->posxdate-$this->posxdesc-1, 3, $this->posxdesc-1, $curY, $object->lines[$i]->comments, 0, 1); //nexY $nexY = $pdf->GetY(); + $pageposafter=$pdf->getPage(); + $pdf->setPage($pageposbefore); + $pdf->setTopMargin($this->marge_haute); + $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it. // Date $pdf->SetFont('','', $default_font_size - 1); - $pdf->SetXY ($this->posxdate, $curY); - $pdf->MultiCell($this->posxtype-$this->posxdate-1, 3,dol_print_date($object->lignes[$i]->date,"day",false,$outpulangs), 0, 'C'); + $pdf->SetXY($this->posxdate, $curY); + $pdf->MultiCell($this->posxtype-$this->posxdate-1, 3,dol_print_date($object->lines[$i]->date,"day",false,$outpulangs), 0, 'C'); // Type $pdf->SetFont('','', $default_font_size - 1); - $pdf->SetXY ($this->posxtype, $curY); - $pdf->MultiCell($this->posxprojet-$this->posxtype-1, 3,$outputlangs->transnoentities($object->lignes[$i]->type_fees_code), 0, 'C'); + $pdf->SetXY($this->posxtype, $curY); + $pdf->MultiCell($this->posxprojet-$this->posxtype-1, 3,$outputlangs->transnoentities($object->lines[$i]->type_fees_code), 0, 'C'); // Projet $pdf->SetFont('','', $default_font_size - 1); - $pdf->SetXY ($this->posxprojet, $curY); - $pdf->MultiCell($this->posxtva-$this->posxprojet-1, 3,$object->lignes[$i]->projet_ref, 0, 'C'); + $pdf->SetXY($this->posxprojet, $curY); + $pdf->MultiCell($this->posxtva-$this->posxprojet-1, 3,$object->lines[$i]->projet_ref, 0, 'C'); - // TVA + // VAT Rate $pdf->SetFont('','', $default_font_size - 1); - $pdf->SetXY ($this->posxtva, $curY); - $pdf->MultiCell($this->posxup-$this->posxtva-1, 3,vatrate($object->lignes[$i]->tva_taux,true), 0, 'R'); + $pdf->SetXY($this->posxtva, $curY); + $pdf->MultiCell($this->posxup-$this->posxtva-1, 3,vatrate($object->lines[$i]->tva_taux,true), 0, 'R'); // UP $pdf->SetFont('','', $default_font_size - 1); - $pdf->SetXY ($this->posxup, $curY); - $pdf->MultiCell($this->posxqty-$this->posxup-1, 3,price($object->lignes[$i]->value_unit), 0, 'R'); + $pdf->SetXY($this->posxup, $curY); + $pdf->MultiCell($this->posxqty-$this->posxup-1, 3,price($object->lines[$i]->value_unit), 0, 'R'); - // QTY + // Quantity $pdf->SetFont('','', $default_font_size - 1); - $pdf->SetXY ($this->posxqty, $curY); - $pdf->MultiCell($this->postotalttc-$this->posxqty, 3,$object->lignes[$i]->qty, 0, 'C'); + $pdf->SetXY($this->posxqty, $curY); + $pdf->MultiCell($this->postotalttc-$this->posxqty, 3,$object->lines[$i]->qty, 0, 'C'); // TotalTTC $pdf->SetFont('','', $default_font_size - 1); - $pdf->SetXY ($this->postotalttc-2, $curY); - $pdf->MultiCell(26, 3,price($object->lignes[$i]->total_ttc), 0, 'R'); + $pdf->SetXY($this->postotalttc-2, $curY); + $pdf->MultiCell($this->page_largeur-$this->marge_droite-$this->postotalttc, 3, price($object->lines[$i]->total_ttc), 0, 'R'); $nexY+=5; @@ -338,38 +379,42 @@ class pdf_ extends ModeleExpenseReport $nblineFollowDesc = 0; } - // Test if a new page is required - if ($pagenb == 1) - { - $tab_top_in_current_page=$tab_top; - $tab_height_in_current_page=$tab_height; - } - else - { - $tab_top_in_current_page=$tab_top_newpage; - $tab_height_in_current_page=$tab_height_newpage; - } - if (($nexY+$nblineFollowDesc) > ($tab_top_in_current_page+$tab_height_in_current_page) && $i < ($nblignes - 1)) - { - if ($pagenb == 1): - $this->_tableau($pdf, $tab_top, $tab_height, $nexY, $outputlangs); - $nexY=$tab_top + $tab_height + 1; - else: - $this->_tableau($pdf, $tab_top_newpage, $tab_height_newpage, $nexY, $outputlangs); - $nexY=$tab_top_newpage + $tab_height_newpage + 1; - endif; - - $this->_pagefoot($pdf,$object,$outputlangs); + $nexY+=2; // Passe espace entre les lignes + // Detect if some page were added automatically and output _tableau for past pages + while ($pagenb < $pageposafter) + { + $pdf->setPage($pagenb); + if ($pagenb == 1) + { + $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1); + } + else + { + $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1); + } + $this->_pagefoot($pdf,$object,$outputlangs,1); + $pagenb++; + $pdf->setPage($pagenb); + $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it. + if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs); + } + if (isset($object->lines[$i+1]->pagebreak) && $object->lines[$i+1]->pagebreak) + { + if ($pagenb == 1) + { + $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1); + } + else + { + $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1); + } + $this->_pagefoot($pdf,$object,$outputlangs,1); // New page $pdf->AddPage(); + if (! empty($tplidx)) $pdf->useTemplate($tplidx); $pagenb++; - $this->_pagehead($pdf, $object, 0, $outputlangs); - $pdf->SetFont('','', $default_font_size - 1); - $pdf->MultiCell(0, 3, ''); // Set interline to 3 - $pdf->SetTextColor(0,0,0); - - $nexY = $tab_top_newpage + 7; + if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs); } } @@ -377,30 +422,30 @@ class pdf_ extends ModeleExpenseReport // Show square if ($pagenb == 1) { - $this->_tableau($pdf, $tab_top, $tab_height, $nexY, $outputlangs); - $bottomlasttab=$tab_top + $tab_height + 1; + $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0); + $bottomlasttab=$this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1; } else { - $this->_tableau($pdf, $tab_top_newpage, $tab_height_newpage, $nexY, $outputlangs); - $bottomlasttab=$tab_top_newpage + $tab_height_newpage + 1; + $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0); + $bottomlasttab=$this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1; } - // Affiche zone totaux + // Show total area box $posy=$bottomlasttab+5;//$nexY+95; - $pdf->SetXY(120, $posy); - $pdf->MultiCell(50, 5, $outputlangs->transnoentities("TotalHT"), 1, 'L'); - $pdf->SetXY (170, $posy); - $pdf->MultiCell(30, 5, price($object->total_ht), 1, 'R'); + $pdf->SetXY(100, $posy); + $pdf->MultiCell(60, 5, $outputlangs->transnoentities("TotalHT"), 1, 'L'); + $pdf->SetXY(160, $posy); + $pdf->MultiCell($this->page_largeur - $this->marge_gauche - 160, 5, price($object->total_ht), 1, 'R'); $pdf->SetFillColor(248,248,248); $posy+=5; - $pdf->SetXY (120, $posy); + $pdf->SetXY(100, $posy); $pdf->SetFont('','B', 10); $pdf->SetTextColor(0,0,60); - $pdf->MultiCell(50, 5, $outputlangs->transnoentities("TotalTTC"), 1,'L'); - $pdf->SetXY (170, $posy); - $pdf->MultiCell(30, 5, price($object->total_ttc),1, 'R'); + $pdf->MultiCell(60, 5, $outputlangs->transnoentities("TotalTTC"), 1,'L'); + $pdf->SetXY(160, $posy); + $pdf->MultiCell($this->page_largeur - $this->marge_gauche - 160, 5, price($object->total_ttc),1, 'R'); // Pied de page $this->_pagefoot($pdf,$object,$outputlangs); @@ -411,11 +456,6 @@ class pdf_ extends ModeleExpenseReport $pdf->Output($file,'F'); // Add pdfgeneration hook - if (! is_object($hookmanager)) - { - include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; - $hookmanager=new HookManager($this->db); - } $hookmanager->initHooks(array('pdfgeneration')); $parameters=array('file'=>$file,'object'=>$object,'outputlangs'=>$outputlangs); global $action; @@ -434,7 +474,7 @@ class pdf_ extends ModeleExpenseReport } else { - $this->error=$langs->trans("ErrorConstantNotDefined","DEPLACEMENT_OUTPUTDIR"); + $this->error=$langs->trans("ErrorConstantNotDefined","EXPENSEREPORT_OUTPUTDIR"); return 0; } $this->error=$langs->trans("ErrorUnknown"); @@ -468,9 +508,9 @@ class pdf_ extends ModeleExpenseReport */ // Filligrane brouillon - if($object->fk_c_expensereport_statuts==1) + if ($object->fk_c_expensereport_statuts==1 && ! empty($conf->global->EXPENSEREPORT_FREE_TEXT)) { - pdf_watermark($pdf,$outputlangs,$this->page_hauteur,$this->page_largeur,'mm',"' - PREVIEW ONLY"); + pdf_watermark($pdf,$outputlangs,$this->page_hauteur,$this->page_largeur,'mm',$conf->global->EXPENSEREPORT_FREE_TEXT); } $pdf->SetTextColor(0,0,60); @@ -504,48 +544,37 @@ class pdf_ extends ModeleExpenseReport $pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, 'L'); } - $pdf->SetFont('','B', $default_font_size + 6); + $pdf->SetFont('','B', $default_font_size + 4); $pdf->SetXY($posx,$posy); - $pdf->SetTextColor(255,255,255); - $pdf->SetFillColor(193,219,62); - $ref_text = explode($conf->global->NDF_EXPLODE_CHAR,$object->ref_number); - $ref_text = substr($ref_text[1],3,$conf->global->NDF_NUM_CAR_REF); - $pdf->MultiCell(110,6,"Note de frais ".$ref_text, 0, 'L', 1); + $pdf->SetTextColor(0,0,60); + $pdf->MultiCell($this->page_largeur-$this->marge_droite-$posx,6,$langs->trans("ExpenseReport"), 0, 'L'); $pdf->SetFont('','', $default_font_size -1); // Réf complète $posy+=8; - $pdf->SetXY(100,$posy); + $pdf->SetXY($posx,$posy); $pdf->SetTextColor(0,0,60); - $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Ref")." : " . $object->ref_number, '', 'L'); + $pdf->MultiCell($this->page_largeur-$this->marge_droite-$posx, 3, $outputlangs->transnoentities("Ref")." : " . $object->ref, '', 'L'); // Date début période $posy+=5; - $pdf->SetXY(100,$posy); + $pdf->SetXY($posx,$posy); $pdf->SetTextColor(0,0,60); - $pdf->MultiCell(100, 3, $outputlangs->transnoentities("DateStart")." : " . ($object->date_debut>0?$object->date_debut:dol_print_date($object->date_debut,"day",false,$outpulangs)), '', 'L'); + $pdf->MultiCell($this->page_largeur-$this->marge_droite-$posx, 3, $outputlangs->transnoentities("DateStart")." : " . ($object->date_debut>0?dol_print_date($object->date_debut,"day",false,$outpulangs):''), '', 'L'); // Date fin période $posy+=5; - $pdf->SetXY(100,$posy); + $pdf->SetXY($posx,$posy); $pdf->SetTextColor(0,0,60); - $pdf->MultiCell(100, 3, $outputlangs->transnoentities("DateEnd")." : " . ($object->date_fin>0?dol_print_date($object->date_fin,"day",false,$outpulangs):''), '', 'L'); + $pdf->MultiCell($this->page_largeur-$this->marge_droite-$posx, 3, $outputlangs->transnoentities("DateEnd")." : " . ($object->date_fin>0?dol_print_date($object->date_fin,"day",false,$outpulangs):''), '', 'L'); // Statut NDF - $posy+=7; - $pdf->SetXY(100,$posy); - $pdf->SetFont('','B',20); + $posy+=6; + $pdf->SetXY($posx,$posy); + $pdf->SetFont('','B',18); $pdf->SetTextColor(111,81,124); - if(preg_match("#Pay#",$object->libelle_statut) && !preg_match("#A P#",$object->libelle_statut)): - $pdf->MultiCell(100, 3,$outputlangs->convToOutputCharset("Payée"), '', 'L'); - elseif(preg_match("#Annul#",$object->libelle_statut)): - $pdf->MultiCell(100, 3,$outputlangs->convToOutputCharset("Annulée"), '', 'L'); - elseif(preg_match("#Refus#",$object->libelle_statut)): - $pdf->MultiCell(100, 3,$outputlangs->convToOutputCharset("Refusée"), '', 'L'); - else: - $pdf->MultiCell(100, 3,$object->libelle_statut, '', 'L'); - endif; + $pdf->MultiCell($this->page_largeur-$this->marge_droite-$posx, 3, $object->getLibStatut(0), '', 'R'); // Sender properties $carac_emetteur = ''; @@ -596,64 +625,80 @@ class pdf_ extends ModeleExpenseReport $pdf->SetFont('','B',8); $pdf->SetXY($posx,$posy-5); $pdf->MultiCell(80,5, $outputlangs->transnoentities("TripNDF")." :", 0, 'L'); - $pdf->rect($posx, $posy, 100, $hautcadre); + $pdf->rect($posx, $posy, $this->page_largeur - $this->marge_gauche - $posx, $hautcadre); // Informations for trip (dates and users workflow) - $userfee=new User($this->db); - $userfee->fetch($object->fk_user_author); $posy+=3; - $pdf->SetXY($posx+2,$posy); - $pdf->SetFont('','',10); - $pdf->MultiCell(96,4,$outputlangs->transnoentities("AUTHOR")." : ".$outputlangs->convToOutputCharset($userfee->firstname)." ".$outputlangs->convToOutputCharset($userfee->lastname),0,'L'); - $posy+=5; - $pdf->SetXY($posx+2,$posy); - $pdf->MultiCell(96,4,$outputlangs->transnoentities("DATE_SAVE")." : ".dol_print_date($object->date_create,"day",false,$outpulangs),0,'L'); + if ($object->fk_user_author > 0) + { + $userfee=new User($this->db); + $userfee->fetch($object->fk_user_author); $posy+=3; + $pdf->SetXY($posx+2,$posy); + $pdf->SetFont('','',10); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("AUTHOR")." : ".dolGetFirstLastname($userfee->firstname,$userfee->lastname),0,'L'); + $posy+=5; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("DateCreation")." : ".dol_print_date($object->date_create,"day",false,$outpulangs),0,'L'); + } - if($object->fk_c_expensereport_statuts<3): - $userfee=new User($this->db); - $userfee->fetch($object->fk_user_validator); $posy+=6; - $pdf->SetXY($posx+2,$posy); - $pdf->MultiCell(96,4,$outputlangs->transnoentities("VALIDATOR")." : ".$outputlangs->convToOutputCharset($userfee->firstname)." ".$outputlangs->convToOutputCharset($userfee->lastname),0,'L'); - elseif($object->fk_c_expensereport_statuts==99): - $userfee=new User($this->db); - $userfee->fetch($object->fk_user_refuse); $posy+=6; - $pdf->SetXY($posx+2,$posy); - $pdf->MultiCell(96,4,$outputlangs->transnoentities("REFUSEUR")." : ".$outputlangs->convToOutputCharset($userfee->firstname)." ".$outputlangs->convToOutputCharset($userfee->lastname),0,'L'); - $posy+=5; - $pdf->SetXY($posx+2,$posy); - $pdf->MultiCell(96,4,$outputlangs->transnoentities("MOTIF_REFUS")." : ".$outputlangs->convToOutputCharset($object->detail_refuse),0,'L'); - $posy+=5; - $pdf->SetXY($posx+2,$posy); - $pdf->MultiCell(96,4,$outputlangs->transnoentities("DATE_REFUS")." : ".dol_print_date($object->date_refuse,"day",false,$outpulangs),0,'L'); - elseif($object->fk_c_expensereport_statuts==4): - $userfee=new User($this->db); - $userfee->fetch($object->fk_user_cancel); $posy+=6; - $pdf->SetXY($posx+2,$posy); - $pdf->MultiCell(96,4,$outputlangs->transnoentities("CANCEL_USER")." : ".$outputlangs->convToOutputCharset($userfee->firstname)." ".$outputlangs->convToOutputCharset($userfee->lastname),0,'L'); - $posy+=5; - $pdf->SetXY($posx+2,$posy); - $pdf->MultiCell(96,4,$outputlangs->transnoentities("MOTIF_CANCEL")." : ".$outputlangs->convToOutputCharset($object->detail_cancel),0,'L'); - $posy+=5; - $pdf->SetXY($posx+2,$posy); - $pdf->MultiCell(96,4,$outputlangs->transnoentities("DATE_CANCEL")." : ".dol_print_date($object->date_cancel,"day",false,$outpulangs),0,'L'); - else: - $userfee=new User($this->db); - $userfee->fetch($object->fk_user_validator); $posy+=6; - $pdf->SetXY($posx+2,$posy); - $pdf->MultiCell(96,4,$outputlangs->transnoentities("VALIDOR")." : ".$outputlangs->convToOutputCharset($userfee->firstname)." ".$outputlangs->convToOutputCharset($userfee->lastname),0,'L'); - $posy+=5; - $pdf->SetXY($posx+2,$posy); - $pdf->MultiCell(96,4,$outputlangs->transnoentities("DATE_VALIDE")." : ".dol_print_date($object->date_valide,"day",false,$outpulangs),0,'L'); - endif; + if ($object->fk_c_expensereport_statuts==99) + { + if ($object->fk_user_refuse > 0) + { + $userfee=new User($this->db); + $userfee->fetch($object->fk_user_refuse); $posy+=6; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("REFUSEUR")." : ".dolGetFirstLastname($userfee->firstname,$userfee->lastname),0,'L'); + $posy+=5; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("MOTIF_REFUS")." : ".$outputlangs->convToOutputCharset($object->detail_refuse),0,'L'); + $posy+=5; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("DATE_REFUS")." : ".dol_print_date($object->date_refuse,"day",false,$outpulangs),0,'L'); + } + } + else if($object->fk_c_expensereport_statuts==4) + { + if ($object->fk_user_cancel > 0) + { + $userfee=new User($this->db); + $userfee->fetch($object->fk_user_cancel); $posy+=6; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("CANCEL_USER")." : ".dolGetFirstLastname($userfee->firstname,$userfee->lastname),0,'L'); + $posy+=5; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("MOTIF_CANCEL")." : ".$outputlangs->convToOutputCharset($object->detail_cancel),0,'L'); + $posy+=5; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("DATE_CANCEL")." : ".dol_print_date($object->date_cancel,"day",false,$outpulangs),0,'L'); + } + } + else + { + if ($object->fk_user_approve > 0) + { + $userfee=new User($this->db); + $userfee->fetch($object->fk_user_approve); $posy+=6; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("VALIDOR")." : ".dolGetFirstLastname($userfee->firstname,$userfee->lastname),0,'L'); + $posy+=5; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("DateApprove")." : ".dol_print_date($object->date_approve,"day",false,$outpulangs),0,'L'); + } + } - if($object->fk_c_expensereport_statuts==6): - $userfee=new User($this->db); - $userfee->fetch($object->fk_user_paid); $posy+=6; - $pdf->SetXY($posx+2,$posy); - $pdf->MultiCell(96,4,$outputlangs->transnoentities("AUTHORPAIEMENT")." : ".$outputlangs->convToOutputCharset($userfee->firstname)." ".$outputlangs->convToOutputCharset($userfee->lastname),0,'L'); - $posy+=5; - $pdf->SetXY($posx+2,$posy); - $pdf->MultiCell(96,4,$outputlangs->transnoentities("DATE_PAIEMENT")." : ".dol_print_date($object->date_paiement,"day",false,$outpulangs),0,'L'); - endif; + if($object->fk_c_expensereport_statuts==6) + { + if ($object->fk_user_paid > 0) + { + $userfee=new User($this->db); + $userfee->fetch($object->fk_user_paid); $posy+=6; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("AUTHORPAIEMENT")." : ".dolGetFirstLastname($userfee->firstname,$userfee->lastname),0,'L'); + $posy+=5; + $pdf->SetXY($posx+2,$posy); + $pdf->MultiCell(96,4,$outputlangs->transnoentities("DATE_PAIEMENT")." : ".dol_print_date($object->date_paiement,"day",false,$outpulangs),0,'L'); + } + } } @@ -690,48 +735,48 @@ class pdf_ extends ModeleExpenseReport $pdf->SetFont('','',8); //Piece comptable - $pdf->SetXY ($this->posxpiece-1, $tab_top+1); - $pdf->MultiCell($this->posxpiece-$this->posxpiece-1,1,$outputlangs->transnoentities("Piece"),'','L'); + $pdf->SetXY($this->posxpiece-1, $tab_top+1); + $pdf->MultiCell($this->posxdesc-$this->posxpiece-1,1,'','','R'); //Comments $pdf->line($this->posxdesc-1, $tab_top, $this->posxdesc-1, $tab_top + $tab_height); - $pdf->SetXY ($this->posxdesc-1, $tab_top+1); + $pdf->SetXY($this->posxdesc-1, $tab_top+1); $pdf->MultiCell($this->posxdate-$this->posxdesc-1,1,$outputlangs->transnoentities("Description"),'','L'); //Date $pdf->line($this->posxdate-1, $tab_top, $this->posxdate-1, $tab_top + $tab_height); - $pdf->SetXY ($this->posxdate-1, $tab_top+1); + $pdf->SetXY($this->posxdate-1, $tab_top+1); $pdf->MultiCell($this->posxtype-$this->posxdate-1,2, $outputlangs->transnoentities("Date"),'','C'); //Type $pdf->line($this->posxtype-1, $tab_top, $this->posxtype-1, $tab_top + $tab_height); - $pdf->SetXY ($this->posxtype-1, $tab_top+1); + $pdf->SetXY($this->posxtype-1, $tab_top+1); $pdf->MultiCell($this->posxprojet-$this->posxtype-1,2, $outputlangs->transnoentities("Type"),'','C'); // Projet $pdf->line($this->posxprojet-1, $tab_top, $this->posxprojet-1, $tab_top + $tab_height); - $pdf->SetXY ($this->posxprojet-1, $tab_top+1); + $pdf->SetXY($this->posxprojet-1, $tab_top+1); $pdf->MultiCell($this->posxtva-$this->posxprojet-1,2, $outputlangs->transnoentities("Project"),'','C'); //TVA $pdf->line($this->posxtva-1, $tab_top, $this->posxtva-1, $tab_top + $tab_height); - $pdf->SetXY ($this->posxtva-1, $tab_top+1); + $pdf->SetXY($this->posxtva-1, $tab_top+1); $pdf->MultiCell($this->posxup-$this->posxtva-1,2, $outputlangs->transnoentities("VAT"),'','C'); //PU $pdf->line($this->posxup-1, $tab_top, $this->posxup-1, $tab_top + $tab_height); - $pdf->SetXY ($this->posxup-1, $tab_top+1); - $pdf->MultiCell($this->posxqty-$this->posxup-1,2, $outputlangs->transnoentities("PU"),'','C'); + $pdf->SetXY($this->posxup-1, $tab_top+1); + $pdf->MultiCell($this->posxqty-$this->posxup-1,2, $outputlangs->transnoentities("UP"),'','C'); //QTY $pdf->line($this->posxqty-1, $tab_top, $this->posxqty-1, $tab_top + $tab_height); - $pdf->SetXY ($this->posxqty-1, $tab_top+1); - $pdf->MultiCell($this->postotalttc-$this->posxqty,2, $outputlangs->transnoentities("Q"),'','R'); + $pdf->SetXY($this->posxqty-1, $tab_top+1); + $pdf->MultiCell($this->postotalttc-$this->posxqty,2, $outputlangs->transnoentities("Qty"),'','R'); //TOTALTTC $pdf->line($this->postotalttc, $tab_top, $this->postotalttc, $tab_top + $tab_height); - $pdf->SetXY ($this->postotalttc-4, $tab_top+1); - $pdf->MultiCell(28,2, $outputlangs->transnoentities("TotalTTC"),'','R'); + $pdf->SetXY($this->postotalttc-1, $tab_top+1); + $pdf->MultiCell($this->page_largeur-$this->marge_droite-$this->postotalttc, 2, $outputlangs->transnoentities("TotalTTC"),'','R'); $pdf->SetTextColor(0,0,0); } @@ -747,7 +792,8 @@ class pdf_ extends ModeleExpenseReport */ function _pagefoot(&$pdf,$object,$outputlangs,$hidefreetext=0) { - return pdf_pagefoot($pdf,$outputlangs,'DEPLACEMENT_FREE_TEXT',$this->emetteur,$this->marge_basse,$this->marge_gauche,$this->page_hauteur,$object,0,$hidefreetext); + $showdetails=0; + return pdf_pagefoot($pdf,$outputlangs,'EXPENSEREPORT_FREE_TEXT',$this->emetteur,$this->marge_basse,$this->marge_gauche,$this->page_hauteur,$object,$showdetails,$hidefreetext); } } diff --git a/htdocs/core/modules/expensereport/modules_expensereport.php b/htdocs/core/modules/expensereport/modules_expensereport.php index 86fa894dbaf..641f1de9c98 100755 --- a/htdocs/core/modules/expensereport/modules_expensereport.php +++ b/htdocs/core/modules/expensereport/modules_expensereport.php @@ -49,62 +49,20 @@ class ModeleExpenseReport extends CommonDocGenerator } -function expensereport_pdf_create($db, $id, $message, $modele, $outputlangs) +/** + * expensereport_pdf_create + * + * @param DoliDB $db Database handler + * @param Object $object Object order + * @param string $modele Force le modele a utiliser ('' to not force) + * @param Translate $outputlangs objet lang a utiliser pour traduction + * @param int $hidedetails Hide details of lines + * @param int $hidedesc Hide description + * @param int $hideref Hide ref + * @return int 0 if KO, 1 if OK + * @return number + */ +function expensereport_pdf_create(DoliDB $db, ExpenseReport $object, $message, $modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0) { - global $conf,$langs; - $langs->load("trips"); - - // Increase limit for PDF build - $err=error_reporting(); - error_reporting(0); - @set_time_limit(120); - error_reporting($err); - - $dir = dol_buildpath('/expensereport/core/modules/expensereport/'); - - // Positionne modele sur le nom du modele a utiliser - if (! strlen($modele)) - { - if ($conf->global->DEPLACEMENT_ADDON_PDF) - { - $modele = $conf->global->DEPLACEMENT_ADDON_PDF; - } - else - { - print $langs->trans("Error")." ".$langs->trans("Error_DEPLACEMENT_ADDON_PDF_NotDefined"); - return 0; - } - } - - // Charge le modele - $file = "pdf_".$modele.".modules.php"; - if (file_exists($dir.$file)) - { - $classname = "pdf_".$modele; - require_once($dir.$file); - - $obj = new $classname($db); - $obj->message = $message; - - // We save charset_output to restore it because write_file can change it if needed for - // output format that does not support UTF8. - $sav_charset_output=$outputlangs->charset_output; - if ($obj->write_file($id, $outputlangs) > 0) - { - $outputlangs->charset_output=$sav_charset_output; - return 1; - } - else - { - $outputlangs->charset_output=$sav_charset_output; - dol_print_error($db,"expensereport_pdf_create Error: ".$obj->error); - return -1; - } - - } - else - { - dol_print_error('',$langs->trans("Error")." ".$langs->trans("ErrorFileDoesNotExists",$dir.$file)); - return -1; - } + return $object->generateDocument($modele, $outputlangs, $hidedetails, $hidedesc, $hideref); } diff --git a/htdocs/core/modules/modAgenda.class.php b/htdocs/core/modules/modAgenda.class.php index c633734b227..165b547dff4 100644 --- a/htdocs/core/modules/modAgenda.class.php +++ b/htdocs/core/modules/modAgenda.class.php @@ -393,7 +393,7 @@ class modAgenda extends DolibarrModules $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'socpeople as sp on ac.fk_contact = sp.rowid'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe as s on ac.fk_soc = s.rowid'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'c_country as co on s.fk_pays = co.rowid'; - $this->export_sql_end[$r] .=' Where ac.entity = '.$conf->entity; + $this->export_sql_end[$r] .=' WHERE ac.entity IN ('.getEntity('agenda',1).')'; $this->export_sql_end[$r] .=' ORDER BY ac.datep'; } diff --git a/htdocs/core/modules/modBanque.class.php b/htdocs/core/modules/modBanque.class.php index 0d383603a06..246aac2b6d7 100644 --- a/htdocs/core/modules/modBanque.class.php +++ b/htdocs/core/modules/modBanque.class.php @@ -157,7 +157,7 @@ class modBanque extends DolibarrModules $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX."bank_url as bu ON (bu.fk_bank = b.rowid AND bu.type = 'company')"; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe as s ON bu.url_id = s.rowid'; $this->export_sql_end[$r] .=' WHERE ba.rowid = b.fk_account'; - $this->export_sql_end[$r] .=' AND ba.entity = '.$conf->entity; + $this->export_sql_end[$r] .=' AND ba.entity IN ('.getEntity('bank',1).')'; $this->export_sql_order[$r] =' ORDER BY b.datev, b.num_releve'; $r++; @@ -184,7 +184,7 @@ class modBanque extends DolibarrModules $this->export_sql_end[$r] .=' WHERE ba.rowid = b.fk_account AND bch.rowid = b.fk_bordereau and bch.fk_bank_account=ba.rowid'; $this->export_sql_end[$r] .=" AND b.fk_type = 'CHQ'"; $this->export_sql_end[$r] .=' AND p.fk_paiement = 7'; - $this->export_sql_end[$r] .=' AND ba.entity = '.$conf->entity; + $this->export_sql_end[$r] .=' AND ba.entity IN ('.getEntity('bank',1).')'; $this->export_sql_order[$r] =' ORDER BY b.datev, b.num_releve'; } diff --git a/htdocs/core/modules/modCategorie.class.php b/htdocs/core/modules/modCategorie.class.php index 327608c8814..a75e73e6c3d 100644 --- a/htdocs/core/modules/modCategorie.class.php +++ b/htdocs/core/modules/modCategorie.class.php @@ -122,7 +122,7 @@ class modCategorie extends DolibarrModules $this->export_sql_start[$r]='SELECT DISTINCT '; $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'categorie as u, '.MAIN_DB_PREFIX.'categorie_fournisseur as cf, '.MAIN_DB_PREFIX.'societe as s LEFT JOIN '.MAIN_DB_PREFIX.'c_typent as t ON s.fk_typent = t.id LEFT JOIN '.MAIN_DB_PREFIX.'c_country as c ON s.fk_pays = c.rowid LEFT JOIN '.MAIN_DB_PREFIX.'c_effectif as ce ON s.fk_effectif = ce.id LEFT JOIN '.MAIN_DB_PREFIX.'c_forme_juridique as cfj ON s.fk_forme_juridique = cfj.code'; $this->export_sql_end[$r] .=' WHERE u.rowid = cf.fk_categorie AND cf.fk_societe = s.rowid'; - $this->export_sql_end[$r] .=' AND u.entity = '.$conf->entity; + $this->export_sql_end[$r] .=' AND u.entity IN ('.getEntity('category',1).')'; $this->export_sql_end[$r] .=' AND u.type = 1'; // Supplier categories $r++; @@ -137,7 +137,7 @@ class modCategorie extends DolibarrModules $this->export_sql_start[$r]='SELECT DISTINCT '; $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'categorie as u, '.MAIN_DB_PREFIX.'categorie_societe as cf, '.MAIN_DB_PREFIX.'societe as s LEFT JOIN '.MAIN_DB_PREFIX.'c_typent as t ON s.fk_typent = t.id LEFT JOIN '.MAIN_DB_PREFIX.'c_country as c ON s.fk_pays = c.rowid LEFT JOIN '.MAIN_DB_PREFIX.'c_effectif as ce ON s.fk_effectif = ce.id LEFT JOIN '.MAIN_DB_PREFIX.'c_forme_juridique as cfj ON s.fk_forme_juridique = cfj.code'; $this->export_sql_end[$r] .=' WHERE u.rowid = cf.fk_categorie AND cf.fk_societe = s.rowid'; - $this->export_sql_end[$r] .=' AND u.entity = '.$conf->entity; + $this->export_sql_end[$r] .=' AND u.entity IN ('.getEntity('category',1).')'; $this->export_sql_end[$r] .=' AND u.type = 2'; // Customer/Prospect categories $r++; @@ -152,7 +152,7 @@ class modCategorie extends DolibarrModules $this->export_sql_start[$r]='SELECT DISTINCT '; $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'categorie as u, '.MAIN_DB_PREFIX.'categorie_product as cp, '.MAIN_DB_PREFIX.'product as p'; $this->export_sql_end[$r] .=' WHERE u.rowid = cp.fk_categorie AND cp.fk_product = p.rowid'; - $this->export_sql_end[$r] .=' AND u.entity = '.$conf->entity; + $this->export_sql_end[$r] .=' AND u.entity IN ('.getEntity('category',1).')'; $this->export_sql_end[$r] .=' AND u.type = 0'; // Supplier categories $r++; @@ -167,8 +167,8 @@ class modCategorie extends DolibarrModules $this->export_sql_start[$r]='SELECT DISTINCT '; $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'categorie as u, '.MAIN_DB_PREFIX.'categorie_member as cp, '.MAIN_DB_PREFIX.'adherent as p'; $this->export_sql_end[$r] .=' WHERE u.rowid = cp.fk_categorie AND cp.fk_member = p.rowid'; - $this->export_sql_end[$r] .=' AND u.entity = '.$conf->entity; - $this->export_sql_end[$r] .=' AND u.type = 3'; // Supplier categories + $this->export_sql_end[$r] .=' AND u.entity IN ('.getEntity('category',1).')'; + $this->export_sql_end[$r] .=' AND u.type = 3'; // Member categories $r++; $this->export_code[$r]='category_'.$r; @@ -232,7 +232,7 @@ class modCategorie extends DolibarrModules $this->export_sql_start[$r] = 'SELECT DISTINCT '; $this->export_sql_end[$r] = ' FROM ' . MAIN_DB_PREFIX . 'categorie as u, '.MAIN_DB_PREFIX . 'categorie_contact as cp, '.MAIN_DB_PREFIX . 'socpeople as p'; $this->export_sql_end[$r] .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'c_country as country ON p.fk_pays = country.rowid'; - $this->export_sql_end[$r] .= ' WHERE u.rowid = cp.fk_categorie AND cp.fk_socpeople = p.rowid AND u.entity = ' . $conf->entity; + $this->export_sql_end[$r] .= ' WHERE u.rowid = cp.fk_categorie AND cp.fk_socpeople = p.rowid AND u.entity IN ('.getEntity('category',1).')'; $this->export_sql_end[$r] .= ' AND u.type = 4'; // contact categories // Imports diff --git a/htdocs/core/modules/modCommande.class.php b/htdocs/core/modules/modCommande.class.php index d8cc5647817..c7fb5cfa587 100644 --- a/htdocs/core/modules/modCommande.class.php +++ b/htdocs/core/modules/modCommande.class.php @@ -192,7 +192,7 @@ class modCommande extends DolibarrModules $this->export_sql_end[$r] .=' , '.MAIN_DB_PREFIX.'commandedet as cd'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product as p on cd.fk_product = p.rowid'; $this->export_sql_end[$r] .=' WHERE c.fk_soc = s.rowid AND c.rowid = cd.fk_commande'; - $this->export_sql_end[$r] .=' AND c.entity = '.$conf->entity; + $this->export_sql_end[$r] .=' AND c.entity IN ('.getEntity('commande',1).')'; } diff --git a/htdocs/core/modules/modContrat.class.php b/htdocs/core/modules/modContrat.class.php index 4906d9e3954..dc97964fa45 100644 --- a/htdocs/core/modules/modContrat.class.php +++ b/htdocs/core/modules/modContrat.class.php @@ -42,7 +42,7 @@ class modContrat extends DolibarrModules function __construct($db) { global $conf; - + $this->db = $db; $this->numero = 54; @@ -160,9 +160,9 @@ class modContrat extends DolibarrModules $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'c_country as c on s.fk_pays = c.rowid,'; $this->export_sql_end[$r] .=' '.MAIN_DB_PREFIX.'contrat as co,'; $this->export_sql_end[$r] .=' '.MAIN_DB_PREFIX.'contratdet as cod'; - $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product as p on (cod.fk_product = p.rowid)'; + $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product as p on (cod.fk_product = p.rowid)'; $this->export_sql_end[$r] .=' WHERE co.fk_soc = s.rowid and co.rowid = cod.fk_contrat'; - $this->export_sql_end[$r] .=' AND co.entity = '.$conf->entity; + $this->export_sql_end[$r] .=' AND co.entity IN ('.getEntity('contract',1).')'; } diff --git a/htdocs/core/modules/modDeplacement.class.php b/htdocs/core/modules/modDeplacement.class.php index f08a346577a..47642e5195d 100644 --- a/htdocs/core/modules/modDeplacement.class.php +++ b/htdocs/core/modules/modDeplacement.class.php @@ -124,7 +124,7 @@ class modDeplacement extends DolibarrModules $this->export_sql_end[$r] .=', '.MAIN_DB_PREFIX.'deplacement as d'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe as s ON d.fk_soc = s.rowid'; $this->export_sql_end[$r] .=' WHERE d.fk_user = u.rowid'; - $this->export_sql_end[$r] .=' AND d.entity = '.$conf->entity; + $this->export_sql_end[$r] .=' AND d.entity IN ('.getEntity('deplacement',1).')'; } diff --git a/htdocs/core/modules/modExpedition.class.php b/htdocs/core/modules/modExpedition.class.php index e2c85c60352..2f4b7a88be8 100644 --- a/htdocs/core/modules/modExpedition.class.php +++ b/htdocs/core/modules/modExpedition.class.php @@ -229,7 +229,7 @@ class modExpedition extends DolibarrModules $this->export_sql_end[$r] .=' '.MAIN_DB_PREFIX.'expeditiondet as ed, '.MAIN_DB_PREFIX.'commandedet as cd'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product as p on cd.fk_product = p.rowid'; $this->export_sql_end[$r] .=' WHERE c.fk_soc = s.rowid AND c.rowid = ed.fk_expedition AND ed.fk_origin_line = cd.rowid'; - $this->export_sql_end[$r] .=' AND c.entity = '.$conf->entity; + $this->export_sql_end[$r] .=' AND c.entity IN ('.getEntity('shipment',1).')'; } diff --git a/htdocs/core/modules/modExpenseReport.class.php b/htdocs/core/modules/modExpenseReport.class.php index 1bf00f86f31..c82de294008 100755 --- a/htdocs/core/modules/modExpenseReport.class.php +++ b/htdocs/core/modules/modExpenseReport.class.php @@ -4,7 +4,7 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, @@ -14,7 +14,6 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * or see http://www.gnu.org/ */ /** @@ -50,8 +49,6 @@ class modExpenseReport extends DolibarrModules // Id for module (must be unique). // Use here a free id (See in Home -> System information -> Dolibarr for list of used modules id). $this->numero = 770; - // Key text used to identify module (for permissions, menus, etc...) - $this->rights_class = 'deplacement'; // Family can be 'crm','financial','hr','projects','products','ecm','technic','other' // It is used to group modules in module setup page @@ -83,21 +80,29 @@ class modExpenseReport extends DolibarrModules //$this->style_sheet = '/mymodule/mymodule.css.php'; // Config pages. Put here list of php page names stored in admmin directory used to setup module. - $this->config_page_url = array(); + $this->config_page_url = array('expensereport.php'); // Dependencies $this->depends = array(); // List of modules id that must be enabled if this module is enabled // $this->conflictwith = array("modDeplacement"); $this->requiredby = array(); // List of modules id to disable if this one is disabled $this->phpmin = array(4,3); // Minimum version of PHP required by module - $this->need_dolibarr_version = array(3,0); // Minimum version of Dolibarr required by module - $this->langfiles = array("companies","trips","deplacement@deplacement"); + $this->need_dolibarr_version = array(3,7); // Minimum version of Dolibarr required by module + $this->langfiles = array("companies","trips"); // Constants // Example: $this->const=array(0=>array('MYMODULE_MYNEWCONST1','chaine','myvalue','This is a constant to add',0), // 1=>array('MYMODULE_MYNEWCONST2','chaine','myvalue','This is another constant to add',0) ); // 2=>array('MAIN_MODULE_MYMODULE_NEEDSMARTY','chaine',1,'Constant to say module need smarty',0) $this->const = array(); // List of particular constants to add when module is enabled (key, 'chaine', value, desc, visible, 0 or 'allentities') + $r=0; + + $this->const[$r][0] = "EXPENSEREPORT_ADDON_PDF"; + $this->const[$r][1] = "chaine"; + $this->const[$r][2] = "standard"; + $this->const[$r][3] = 'Name of manager to build PDF expense reports documents'; + $this->const[$r][4] = 0; + $r++; // Array to add new pages in new tabs $this->tabs = array(); @@ -195,19 +200,21 @@ class modExpenseReport extends DolibarrModules $r=0; $r++; - $this->export_code[$r]='trips_'.$r; + $this->export_code[$r]='expensereport_'.$r; $this->export_label[$r]='ListTripsAndExpenses'; + $this->export_icon[$r]='trip'; $this->export_permission[$r]=array(array("expensereport","export")); - $this->export_fields_array[$r]=array('d.rowid'=>"TripId",'d.type'=>"Type",'d.km'=>"FeesKilometersOrAmout",'d.note'=>'NotePrivate','d.note_public'=>'NotePublic','s.nom'=>'ThirdParty','u.lastname'=>'Lastname','u.firstname'=>'Firstname','d.dated'=>"Date"); - $this->export_entities_array[$r]=array('d.rowid'=>"Trip",'d.type'=>"Trip",'d.km'=>"Trip",'d.note'=>'Trip','d.note_public'=>'Trip','s.nom'=>'company','u.lastname'=>'user','u.firstname'=>'user','d.dated'=>"Date"); - $this->export_alias_array[$r]=array('d.rowid'=>"idtrip",'d.type'=>"type",'d.km'=>"km",'d.note'=>'note','d.note_public'=>'note_public','s.nom'=>'companyname','u.lastname'=>'name','u.firstname'=>'firstname','d.dated'=>'date'); + $this->export_fields_array[$r]=array('d.rowid'=>"TripId",'d.ref'=>'Ref','d.date_debut'=>'DateStart','d.date_fin'=>'DateEnd','d.date_create'=>'DateCreation','d.date_approve'=>'DateApprove','d.total_ht'=>"TotalHT",'d.total_tva'=>'TotalVAT','d.total_ttc'=>'TotalTTC','d.note_private'=>'NotePrivate','d.note_public'=>'NotePublic','u.lastname'=>'Lastname','u.firstname'=>'Firstname','u.login'=>"Login",'ed.rowid'=>'LineId','tf.code'=>'Type','ed.date'=>'Date','ed.fk_c_tva'=>'VATRate','ed.total_ht'=>'TotalHT','ed.total_tva'=>'TotalVAT','ed.total_ttc'=>'TotalTTC','ed.comments'=>'Comment','p.rowid'=>'ProjectId','p.ref'=>'Ref'); + $this->export_entities_array[$r]=array('u.lastname'=>'user','u.firstname'=>'user','u.login'=>'user','ed.rowid'=>'expensereport_line','ed.date'=>'expensereport_line','ed.fk_c_tva'=>'expensereport_line','ed.total_ht'=>'expensereport_line','ed.total_tva'=>'expensereport_line','ed.total_ttc'=>'expensereport_line','ed.comments'=>'expensereport_line','tf.code'=>'expensereport_line','p.project_ref'=>'expensereport_line','p.rowid'=>'project','p.ref'=>'project'); + $this->export_alias_array[$r]=array('d.rowid'=>"idtrip",'d.type'=>"type",'d.note_private'=>'note_private','d.note_public'=>'note_public','u.lastname'=>'name','u.firstname'=>'firstname','u.login'=>'login'); + $this->export_dependencies_array[$r]=array('expensereport_line'=>'ed.rowid','type_fees'=>'tf.rowid'); // To add unique key if we ask a field of a child to avoid the DISTINCT to discard them $this->export_sql_start[$r]='SELECT DISTINCT '; - $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'user as u'; - $this->export_sql_end[$r] .=', '.MAIN_DB_PREFIX.'expensereport as d'; - $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe as s ON d.fk_soc = s.rowid'; - $this->export_sql_end[$r] .=' WHERE d.fk_user = u.rowid'; - $this->export_sql_end[$r] .=' AND d.entity = '.$conf->entity; + $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'expensereport as d, '.MAIN_DB_PREFIX.'user as u,'; + $this->export_sql_end[$r] .=' '.MAIN_DB_PREFIX.'expensereport_det as ed LEFT JOIN '.MAIN_DB_PREFIX.'c_type_fees as tf ON ed.fk_c_type_fees = tf.id'; + $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'projet as p ON ed.fk_projet = p.rowid'; + $this->export_sql_end[$r] .=' WHERE ed.fk_expensereport = d.rowid AND d.fk_user_author = u.rowid'; + $this->export_sql_end[$r] .=' AND d.entity IN ('.getEntity('expensereport',1).')'; diff --git a/htdocs/core/modules/modFacture.class.php b/htdocs/core/modules/modFacture.class.php index 38a06576c9e..86762fbb87c 100644 --- a/htdocs/core/modules/modFacture.class.php +++ b/htdocs/core/modules/modFacture.class.php @@ -228,7 +228,7 @@ class modFacture extends DolibarrModules $this->export_sql_end[$r] .=' , '.MAIN_DB_PREFIX.'facturedet as fd'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product as p on (fd.fk_product = p.rowid)'; $this->export_sql_end[$r] .=' WHERE f.fk_soc = s.rowid AND f.rowid = fd.fk_facture'; - $this->export_sql_end[$r] .=' AND f.entity = '.$conf->entity; + $this->export_sql_end[$r] .=' AND f.entity IN ('.getEntity('facture',1).')'; $r++; $this->export_code[$r]=$this->rights_class.'_'.$r; @@ -284,7 +284,7 @@ class modFacture extends DolibarrModules $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'paiement_facture as pf ON pf.fk_facture = f.rowid'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'paiement as p ON pf.fk_paiement = p.rowid'; $this->export_sql_end[$r] .=' WHERE f.fk_soc = s.rowid'; - $this->export_sql_end[$r] .=' AND f.entity = '.$conf->entity; + $this->export_sql_end[$r] .=' AND f.entity IN ('.getEntity('facture',1).')'; $r++; } diff --git a/htdocs/core/modules/modFicheinter.class.php b/htdocs/core/modules/modFicheinter.class.php index 45d8a0fa7bc..7c54679bd9c 100644 --- a/htdocs/core/modules/modFicheinter.class.php +++ b/htdocs/core/modules/modFicheinter.class.php @@ -147,7 +147,7 @@ class modFicheinter extends DolibarrModules $this->export_sql_start[$r]='SELECT DISTINCT '; $this->export_sql_end[$r] =' FROM ('.MAIN_DB_PREFIX.'fichinter as f, '.MAIN_DB_PREFIX.'fichinterdet as fd, '.MAIN_DB_PREFIX.'societe as s)'; $this->export_sql_end[$r] .=' WHERE f.fk_soc = s.rowid AND f.rowid = fd.fk_fichinter'; - $this->export_sql_end[$r] .=' AND f.entity = '.$conf->entity; + $this->export_sql_end[$r] .=' AND f.entity IN ('.getEntity('intervention',1).')'; $r++; } diff --git a/htdocs/core/modules/modFournisseur.class.php b/htdocs/core/modules/modFournisseur.class.php index 656ef87c191..1f8b3af3ed6 100644 --- a/htdocs/core/modules/modFournisseur.class.php +++ b/htdocs/core/modules/modFournisseur.class.php @@ -297,7 +297,7 @@ class modFournisseur extends DolibarrModules $this->export_sql_end[$r] .=' , '.MAIN_DB_PREFIX.'facture_fourn_det as fd'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product as p on (fd.fk_product = p.rowid)'; $this->export_sql_end[$r] .=' WHERE f.fk_soc = s.rowid AND f.rowid = fd.fk_facture_fourn'; - $this->export_sql_end[$r] .=' AND f.entity = '.$conf->entity; + $this->export_sql_end[$r] .=' AND f.entity IN ('.getEntity('supplier_invoice',1).')'; $r++; $this->export_code[$r]=$this->rights_class.'_'.$r; @@ -351,7 +351,7 @@ class modFournisseur extends DolibarrModules $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'paiementfourn_facturefourn as pf ON pf.fk_facturefourn = f.rowid'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'paiementfourn as p ON pf.fk_paiementfourn = p.rowid'; $this->export_sql_end[$r] .=' WHERE f.fk_soc = s.rowid'; - $this->export_sql_end[$r] .=' AND f.entity = '.$conf->entity; + $this->export_sql_end[$r] .=' AND f.entity IN ('.getEntity('supplier_invoice',1).')'; $r++; $this->export_code[$r]=$this->rights_class.'_'.$r; @@ -369,7 +369,7 @@ class modFournisseur extends DolibarrModules $this->export_sql_end[$r] .=' '.MAIN_DB_PREFIX.'commande_fournisseur as f, '.MAIN_DB_PREFIX.'commande_fournisseurdet as fd'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product as p on (fd.fk_product = p.rowid)'; $this->export_sql_end[$r] .=' WHERE f.fk_soc = s.rowid AND f.rowid = fd.fk_commande'; - $this->export_sql_end[$r] .=' AND f.entity = '.$conf->entity; + $this->export_sql_end[$r] .=' AND f.entity IN ('.getEntity('supplier_order',1).')'; } diff --git a/htdocs/core/modules/modProjet.class.php b/htdocs/core/modules/modProjet.class.php index 4a534c937cc..548306fc022 100644 --- a/htdocs/core/modules/modProjet.class.php +++ b/htdocs/core/modules/modProjet.class.php @@ -94,21 +94,21 @@ class modProjet extends DolibarrModules $this->const[$r][3] = ""; $this->const[$r][4] = 0; $r++; - + $this->const[$r][0] = "PROJECT_TASK_ADDON_PDF"; $this->const[$r][1] = "chaine"; $this->const[$r][2] = ""; $this->const[$r][3] = 'Name of PDF/ODT tasks manager class'; $this->const[$r][4] = 0; $r++; - + $this->const[$r][0] = "PROJECT_TASK_ADDON"; $this->const[$r][1] = "chaine"; $this->const[$r][2] = "mod_task_simple"; $this->const[$r][3] = 'Name of Numbering Rule task manager class'; $this->const[$r][4] = 0; $r++; - + $this->const[$r][0] = "PROJECT_TASK_ADDON_PDF_ODT_PATH"; $this->const[$r][1] = "chaine"; $this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/tasks"; @@ -155,7 +155,7 @@ class modProjet extends DolibarrModules $this->rights[$r][2] = 'd'; // type de la permission (deprecie a ce jour) $this->rights[$r][3] = 0; // La permission est-elle une permission par defaut $this->rights[$r][4] = 'export'; - + $r++; $this->rights[$r][0] = 141; // id de la permission $this->rights[$r][1] = "Lire tous les projets et tâches (y compris prives qui ne me sont pas affectes)"; // libelle de la permission @@ -189,7 +189,7 @@ class modProjet extends DolibarrModules $this->export_label[$r]='ProjectsAndTasksLines'; // Translation key (used only if key ExportDataset_xxx_z not found) $this->export_permission[$r]=array(array("projet","export")); $this->export_dependencies_array[$r]=array('task_time'=>'ppt.rowid'); - + $this->export_TypeFields_array[$r]=array('s.rowid'=>"List:societe:nom",'s.nom'=>'Text','s.address'=>'Text','s.zip'=>'Text','s.town'=>'Text','s.fk_pays'=>'List:c_country:label', 's.phone'=>'Text','s.siren'=>'Text','s.siret'=>'Text','s.ape'=>'Text','s.idprof4'=>'Text','s.code_compta'=>'Text','s.code_compta_fournisseur'=>'Text', 'p.rowid'=>"List:projet:ref",'p.ref'=>"Text",'p.datec'=>"Date",'p.dateo'=>"Date",'p.datee'=>"Date",'p.fk_statut'=>'Status','p.description'=>"Text", @@ -199,11 +199,11 @@ class modProjet extends DolibarrModules $this->export_entities_array[$r]=array('s.rowid'=>"company",'s.nom'=>'company','s.address'=>'company','s.zip'=>'company','s.town'=>'company','s.fk_pays'=>'company', 's.phone'=>'company','s.siren'=>'company','s.siret'=>'company','s.ape'=>'company','s.idprof4'=>'company','s.code_compta'=>'company','s.code_compta_fournisseur'=>'company', 'p.rowid'=>"project",'p.ref'=>"project",'p.datec'=>"project",'p.dateo'=>"project",'p.datee'=>"project",'p.duree'=>"project",'p.fk_statut'=>"project",'p.description'=>"project"); - + $this->export_fields_array[$r]=array('s.rowid'=>"IdCompany",'s.nom'=>'CompanyName','s.address'=>'Address','s.zip'=>'Zip','s.town'=>'Town','s.fk_pays'=>'Country', 's.phone'=>'Phone','s.siren'=>'ProfId1','s.siret'=>'ProfId2','s.ape'=>'ProfId3','s.idprof4'=>'ProfId4','s.code_compta'=>'CustomerAccountancyCode','s.code_compta_fournisseur'=>'SupplierAccountancyCode', 'p.rowid'=>"ProjectId",'p.ref'=>"RefProject",'p.datec'=>"DateCreation",'p.dateo'=>"DateStart",'p.datee'=>"DateEnd",'p.fk_statut'=>'Status','p.description'=>"Description"); - + // Add fields for project $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array()); // Add extra fields @@ -239,7 +239,7 @@ class modProjet extends DolibarrModules $this->export_entities_array[$r][$fieldname]='project'; } } - // End add extra fields + // End add extra fields // Add fields for tasks $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('pt.rowid'=>'RefTask','pt.dateo'=>"TaskDateStart",'pt.datee'=>"TaskDateEnd",'pt.duration_effective'=>"DurationEffective",'pt.planned_workload'=>"PlannedWorkload",'pt.progress'=>"Progress",'pt.description'=>"TaskDescription")); @@ -277,10 +277,10 @@ class modProjet extends DolibarrModules $this->export_entities_array[$r][$fieldname]='projecttask'; } } - // End add extra fields + // End add extra fields $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('ptt.task_date'=>'TaskTimeDate','ptt.task_duration'=>"TimesSpent",'ptt.fk_user'=>"TaskTimeUser",'ptt.note'=>"TaskTimeNote")); $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('ptt.task_date'=>'task_time','ptt.task_duration'=>"task_time",'ptt.fk_user'=>"task_time",'ptt.note'=>"task_time")); - + $this->export_sql_start[$r]='SELECT DISTINCT '; $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'projet as p'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'projet_extrafields as extra ON p.rowid = extra.fk_object'; @@ -289,7 +289,7 @@ class modProjet extends DolibarrModules $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX."projet_task_time as ptt ON pt.rowid = ptt.fk_task,"; $this->export_sql_end[$r] .=' '.MAIN_DB_PREFIX.'societe as s'; $this->export_sql_end[$r] .=' WHERE p.fk_soc = s.rowid'; - $this->export_sql_end[$r] .=' AND p.entity = '.$conf->entity; + $this->export_sql_end[$r] .=' AND p.entity IN ('.getEntity('project',1).')'; } @@ -344,12 +344,12 @@ class modProjet extends DolibarrModules return 0; } } - + $sql = array( "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = '".$this->const[0][2]."' AND entity = ".$conf->entity, "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('".$this->const[0][2]."','invoice',".$conf->entity.")" ); - + $sql = array( "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = '".$this->const[0][2]."' AND entity = ".$conf->entity, "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('".$this->const[0][2]."','project',".$conf->entity.")", diff --git a/htdocs/core/modules/modPropale.class.php b/htdocs/core/modules/modPropale.class.php index de1566578fe..e205c696a97 100644 --- a/htdocs/core/modules/modPropale.class.php +++ b/htdocs/core/modules/modPropale.class.php @@ -186,7 +186,7 @@ class modPropale extends DolibarrModules $this->export_sql_end[$r] .=', '.MAIN_DB_PREFIX.'propaldet as cd'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product as p on (cd.fk_product = p.rowid)'; $this->export_sql_end[$r] .=' WHERE c.fk_soc = s.rowid AND c.rowid = cd.fk_propal'; - $this->export_sql_end[$r] .=' AND c.entity = '.$conf->entity; + $this->export_sql_end[$r] .=' AND c.entity IN ('.getEntity('propal',1).')'; } diff --git a/htdocs/core/modules/modSalaries.class.php b/htdocs/core/modules/modSalaries.class.php index 35f5a145bee..2144c95b1b3 100644 --- a/htdocs/core/modules/modSalaries.class.php +++ b/htdocs/core/modules/modSalaries.class.php @@ -132,21 +132,7 @@ class modSalaries extends DolibarrModules // Exports //-------- $r=0; -/* - $r++; - $this->export_code[$r]=$this->rights_class.'_'.$r; - $this->export_label[$r]='Payment of salaries'; - $this->export_permission[$r]=array(array("tax","charges","export")); - $this->export_fields_array[$r]=array('cc.libelle'=>"Type",'c.rowid'=>"IdSocialContribution",'c.libelle'=>"Label",'c.date_ech'=>'DateDue','c.periode'=>'Period','c.amount'=>"AmountExpected","c.paye"=>"Status",'p.rowid'=>'PaymentId','p.datep'=>'DatePayment','p.amount'=>'AmountPayment','p.num_paiement'=>'Numero'); - $this->export_TypeFields_array[$r]=array('cc.libelle'=>"List:c_chargesociales:libelle:id",'c.libelle'=>"Text",'c.date_ech'=>'Date','c.periode'=>'Period','c.amount'=>"Number","c.paye"=>"Boolean",'p.datep'=>'Date','p.amount'=>'Number','p.num_paiement'=>'Number'); - $this->export_entities_array[$r]=array('cc.libelle'=>"tax_type",'c.rowid'=>"tax",'c.libelle'=>'tax','c.date_ech'=>'tax','c.periode'=>'tax','c.amount'=>"tax","c.paye"=>"tax",'p.rowid'=>'payment','p.datep'=>'payment','p.amount'=>'payment','p.num_paiement'=>'payment'); - $this->export_sql_start[$r]='SELECT DISTINCT '; - $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'c_chargesociales as cc, '.MAIN_DB_PREFIX.'chargesociales as c'; - $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'paiementcharge as p ON p.fk_charge = c.rowid'; - $this->export_sql_end[$r] .=' WHERE c.fk_type = cc.id'; - $this->export_sql_end[$r] .=' AND c.entity = '.$conf->entity; - */ } diff --git a/htdocs/core/modules/modStock.class.php b/htdocs/core/modules/modStock.class.php index 43c7cec6fb3..8f6840a21b0 100644 --- a/htdocs/core/modules/modStock.class.php +++ b/htdocs/core/modules/modStock.class.php @@ -131,7 +131,7 @@ class modStock extends DolibarrModules $this->export_sql_start[$r]='SELECT DISTINCT '; $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'product as p, '.MAIN_DB_PREFIX.'product_stock as ps, '.MAIN_DB_PREFIX.'entrepot as e'; $this->export_sql_end[$r] .=' WHERE p.rowid = ps.fk_product AND ps.fk_entrepot = e.rowid'; - $this->export_sql_end[$r] .=' AND e.entity = '.$conf->entity; + $this->export_sql_end[$r] .=' AND e.entity IN ('.getEntity('stock',1).')'; // Imports diff --git a/htdocs/core/modules/modTax.class.php b/htdocs/core/modules/modTax.class.php index f4942d567c9..6f47d66f5a9 100644 --- a/htdocs/core/modules/modTax.class.php +++ b/htdocs/core/modules/modTax.class.php @@ -133,7 +133,7 @@ class modTax extends DolibarrModules $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'c_chargesociales as cc, '.MAIN_DB_PREFIX.'chargesociales as c'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'paiementcharge as p ON p.fk_charge = c.rowid'; $this->export_sql_end[$r] .=' WHERE c.fk_type = cc.id'; - $this->export_sql_end[$r] .=' AND c.entity = '.$conf->entity; + $this->export_sql_end[$r] .=' AND c.entity IN ('.getEntity('tax',1).')'; } diff --git a/htdocs/core/modules/modUser.class.php b/htdocs/core/modules/modUser.class.php index 55e96f02262..c683c2b34cc 100644 --- a/htdocs/core/modules/modUser.class.php +++ b/htdocs/core/modules/modUser.class.php @@ -220,7 +220,7 @@ class modUser extends DolibarrModules } $this->export_sql_start[$r]='SELECT DISTINCT '; $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'user as u'; - $this->export_sql_end[$r] .=' WHERE u.entity IN (0,'.$conf->entity.')'; + $this->export_sql_end[$r] .=' WHERE u.entity IN ('.getEntity('user',1).')'; } diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index 75ab8b7cb45..8cbb25fcc53 100755 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -33,8 +33,8 @@ require_once(DOL_DOCUMENT_ROOT."/projet/class/project.class.php"); require_once(DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'); require_once(DOL_DOCUMENT_ROOT."/core/lib/expensereport.lib.php"); require_once(DOL_DOCUMENT_ROOT."/core/lib/price.lib.php"); -dol_include_once('/expensereport/core/modules/expensereport/modules_expensereport.php'); -dol_include_once("/expensereport/class/expensereport.class.php"); +require_once(DOL_DOCUMENT_ROOT."/core/modules/expensereport/modules_expensereport.php"); +require_once(DOL_DOCUMENT_ROOT."/expensereport/class/expensereport.class.php"); $langs->load("trips"); @@ -68,13 +68,17 @@ if (! empty($conf->multicompany->enabled) && ! empty($conf->entity) && $conf->en $rootfordata.='/'.$conf->entity; } $conf->expensereport->dir_output = $rootfordata.'/expensereport'; -$conf->expensereport->dir_output = $rootfordata.'/expensereport'; // Define $urlwithroot $urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root)); $urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current +// PDF +$hidedetails = (GETPOST('hidedetails', 'int') ? GETPOST('hidedetails', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0)); +$hidedesc = (GETPOST('hidedesc', 'int') ? GETPOST('hidedesc', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0)); +$hideref = (GETPOST('hideref', 'int') ? GETPOST('hideref', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF) ? 1 : 0)); + /* @@ -83,7 +87,7 @@ $urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain if ($cancel) $action=''; -if ($action == 'confirm_delete' && $_GET["confirm"] == "yes" && $id > 0 && $user->rights->expensereport->supprimer) +if ($action == 'confirm_delete' && GETPOST("confirm") == "yes" && $id > 0 && $user->rights->expensereport->supprimer) { $object = new ExpenseReport($db); $result=$object->delete($id); @@ -171,6 +175,27 @@ if ($action == "confirm_save" && GETPOST("confirm") == "yes" && $id > 0 && $user $object = new ExpenseReport($db); $object->fetch($id); $result = $object->setValidate($user); + + if ($result > 0) + { + // Define output language + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) + { + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id')) $newlang = GETPOST('lang_id','alpha'); + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; + if (! empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $model=$object->modelpdf; + $ret = $object->fetch($id); // Reload to get new records + + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + } + } + if ($result > 0 && $object->fk_user_validator > 0) { $langs->load("mails"); @@ -252,6 +277,27 @@ if ($action == "confirm_save_from_refuse" && GETPOST("confirm") == "yes" && $id $object = new ExpenseReport($db); $object->fetch($id); $result = $object->set_save_from_refuse($user); + + if ($result > 0) + { + // Define output language + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) + { + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id')) $newlang = GETPOST('lang_id','alpha'); + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; + if (! empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $model=$object->modelpdf; + $ret = $object->fetch($id); // Reload to get new records + + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + } + } + if ($result > 0) { // Send mail @@ -283,7 +329,7 @@ if ($action == "confirm_save_from_refuse" && GETPOST("confirm") == "yes" && $id // Génération du pdf avant attachement $object->setDocModel($user,""); - $resultPDF = expensereport_pdf_create($db,$id,'',"",$langs); + $resultPDF = expensereport_pdf_create($db,$object,'',"",$langs); if($resultPDF): // ATTACHMENT @@ -329,6 +375,27 @@ if ($action == "confirm_approve" && GETPOST("confirm") == "yes" && $id > 0 && $u $object->fetch($id); $result = $object->setApproved($user); + + if ($result > 0) + { + // Define output language + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) + { + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id')) $newlang = GETPOST('lang_id','alpha'); + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; + if (! empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $model=$object->modelpdf; + $ret = $object->fetch($id); // Reload to get new records + + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + } + } + if ($result > 0) { if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) @@ -360,7 +427,7 @@ if ($action == "confirm_approve" && GETPOST("confirm") == "yes" && $id > 0 && $u // Génération du pdf avant attachement $object->setDocModel($user,""); - $resultPDF = expensereport_pdf_create($db,$id,'',"",$langs); + $resultPDF = expensereport_pdf_create($db,$object,'',"",$langs); if($resultPDF): // ATTACHMENT @@ -412,6 +479,27 @@ if ($action == "confirm_refuse" && GETPOST('confirm')=="yes" && $id > 0 && $user $object->fetch($id); $result = $object->setDeny($user,GETPOST('detail_refuse')); + + if ($result > 0) + { + // Define output language + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) + { + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id')) $newlang = GETPOST('lang_id','alpha'); + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; + if (! empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $model=$object->modelpdf; + $ret = $object->fetch($id); // Reload to get new records + + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + } + } + if ($result > 0) { if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) @@ -477,6 +565,26 @@ if ($action == "confirm_cancel" && GETPOST('confirm')=="yes" && GETPOST('detail_ { $result = $object->set_cancel($user,GETPOST('detail_cancel')); + if ($result > 0) + { + // Define output language + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) + { + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id')) $newlang = GETPOST('lang_id','alpha'); + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; + if (! empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $model=$object->modelpdf; + $ret = $object->fetch($id); // Reload to get new records + + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + } + } + if ($result > 0) { if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) @@ -541,6 +649,27 @@ if ($action == "confirm_paid" && GETPOST('confirm')=="yes" && $id > 0 && $user-> $object->fetch($id); $result = $object->setPaid($user); + + if ($result > 0) + { + // Define output language + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) + { + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id')) $newlang = GETPOST('lang_id','alpha'); + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; + if (! empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $model=$object->modelpdf; + $ret = $object->fetch($id); // Reload to get new records + + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + } + } + if ($result > 0) { if (! empty($conf->global->DEPLACEMENT_TO_CLEAN)) @@ -569,7 +698,7 @@ if ($action == "confirm_paid" && GETPOST('confirm')=="yes" && $id > 0 && $user-> // Génération du pdf avant attachement $object->setDocModel($user,""); - $resultPDF = expensereport_pdf_create($db,$id,'',"",$langs); + $resultPDF = expensereport_pdf_create($db,$object,'',"",$langs); // PREPARE SEND $mailfile = new CMailFile($subject,$emailTo,$emailFrom,$message); @@ -638,6 +767,27 @@ if ($action == "confirm_brouillonner" && GETPOST('confirm')=="yes" && $id > 0 && if ($user->id == $object->fk_user_author || $user->id == $object->fk_user_valid) { $result = $object->setStatut(0); + + if ($result > 0) + { + // Define output language + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) + { + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id')) $newlang = GETPOST('lang_id','alpha'); + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; + if (! empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $model=$object->modelpdf; + $ret = $object->fetch($id); // Reload to get new records + + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + } + } + if ($result > 0) { header("Location: ".$_SEVER["PHP_SELF"]."?id=".$id); @@ -746,7 +896,7 @@ if ($action == "addline") $action=''; } -if ($action == 'confirm_delete_line' && $_POST["confirm"] == "yes") +if ($action == 'confirm_delete_line' && GETPOST("confirm") == "yes") { $object = new ExpenseReport($db); $object->fetch($id); @@ -759,6 +909,26 @@ if ($action == 'confirm_delete_line' && $_POST["confirm"] == "yes") $result=$object->deleteline($_GET["rowid"]); if ($result >= 0) { + if ($result > 0) + { + // Define output language + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) + { + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id')) $newlang = GETPOST('lang_id','alpha'); + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; + if (! empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $model=$object->modelpdf; + $ret = $object->fetch($id); // Reload to get new records + + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + } + } + $object->update_totaux_del($object_ligne->total_ht,$object_ligne->total_tva); header("Location: ".$_SERVER["PHP_SELF"]."?id=".$_GET['id']); exit; @@ -801,6 +971,26 @@ if ($action == "updateligne" ) $result = $object->updateline($rowid, $type_fees_id, $projet_id, $c_tva, $comments, $qty, $value_unit, $date, $object_id); if ($result >= 0) { + if ($result > 0) + { + // Define output language + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) + { + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id')) $newlang = GETPOST('lang_id','alpha'); + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; + if (! empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $model=$object->modelpdf; + $ret = $object->fetch($id); // Reload to get new records + + $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); + } + } + $object->recalculer($object_id); header("Location: ".$_SERVER["PHP_SELF"]."?id=".$object_id); exit; @@ -812,20 +1002,6 @@ if ($action == "updateligne" ) } } -if ($action == "recalc" && $id > 0) -{ - $object = new ExpenseReport($db); - $object->fetch($id); - if($object->recalculer($id) > 0) - { - header("Location: ".$_SERVER["PHP_SELF"]."?id=".$_GET['id']); - exit; - } - else - { - setEventMessages($object->error, $object->errors, 'errors'); - } -} /* * Generer ou regenerer le document PDF @@ -846,7 +1022,7 @@ if ($action == 'builddoc') // En get ou en post $outputlangs = new Translate("",$conf); $outputlangs->setDefaultLang($_REQUEST['lang_id']); } - $result=expensereport_pdf_create($db, $depl->id, '', $depl->modelpdf, $outputlangs); + $result=expensereport_pdf_create($db, $depl, '', $depl->modelpdf, $outputlangs); if ($result <= 0) { dol_print_error($db,$result); diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php index 2523ef34154..0ebde8ac92c 100755 --- a/htdocs/expensereport/class/expensereport.class.php +++ b/htdocs/expensereport/class/expensereport.class.php @@ -24,7 +24,8 @@ class ExpenseReport extends CommonObject var $date_fin; var $fk_user_validator; - var $fk_c_expensereport_statuts; // -- 1=brouillon, 2=validé (attente approb), 4=annulé, 5=approuvé, 6=payed, 99=refusé + var $status; + var $fk_c_expensereport_statuts; // -- 1=draft, 2=validated (attente approb), 4=canceled, 5=approved, 6=payed, 99=denied var $fk_c_paiement; var $user_author_infos; @@ -467,6 +468,67 @@ class ExpenseReport extends CommonObject } + + /** + * Initialise an instance with random values. + * Used to build previews or test instances. + * id must be 0 if object instance is a specimen. + * + * @return void + */ + function initAsSpecimen() + { + global $user,$langs,$conf; + + $now=dol_now(); + + // Initialise parametres + $this->id=0; + $this->ref = 'SPECIMEN'; + $this->specimen=1; + $this->date_create = $now; + $this->date_debut = $now; + $this->date_fin = $now; + $this->date_approve = $now; + + $this->status = 5; + $this->fk_c_expensereport_statuts = 5; + + $this->fk_user_author = $user->id; + $this->fk_user_valid = $user->id; + $this->fk_user_approve = $user->id; + $this->fk_user_validator = $user->id; + + $this->note_private='Private note'; + $this->note_public='SPECIMEN'; + $nbp = 5; + $xnbp = 0; + while ($xnbp < $nbp) + { + $line=new ExpenseReportLine($this->db); + $line->comments=$langs->trans("Comment")." ".$xnbp; + $line->date=($now-3600*(1+$xnbp)); + $line->total_ht=100; + $line->total_tva=20; + $line->total_ttc=120; + $line->qty=1; + $line->fk_c_tva=20; + $line->tva_taux=20; + $line->value_unit=120; + $line->fk_expensereport=0; + $line->type_fees_code='TRA'; + + $line->projet_ref = 'ABC'; + + $this->lines[$xnbp]=$line; + $xnbp++; + + $this->total_ht+=$line->total_ht; + $this->total_tva+=$line->total_tva; + $this->total_ttc+=$line->total_ttc; + } + } + /** * fetch_line_by_project * @@ -1302,6 +1364,41 @@ class ExpenseReport extends CommonObject return -1; } } + + /** + * Create a document onto disk accordign to template module. + * + * @param string $modele Force le mnodele a utiliser ('' to not force) + * @param Translate $outputlangs objet lang a utiliser pour traduction + * @param int $hidedetails Hide details of lines + * @param int $hidedesc Hide description + * @param int $hideref Hide ref + * @return int 0 if KO, 1 if OK + */ + public function generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0) + { + global $conf,$langs; + + $langs->load("trips"); + + // Positionne le modele sur le nom du modele a utiliser + if (! dol_strlen($modele)) + { + if (! empty($conf->global->EXPENSEREPORT_ADDON_PDF)) + { + $modele = $conf->global->EXPENSEREPORT_ADDON_PDF; + } + else + { + $modele = 'standard'; + } + } + + $modelpath = "core/modules/expensereport/doc/"; + + return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref); + } + } diff --git a/htdocs/exports/export.php b/htdocs/exports/export.php index 45e78b2ecd3..ca997f0eb59 100644 --- a/htdocs/exports/export.php +++ b/htdocs/exports/export.php @@ -60,7 +60,9 @@ $entitytoicon = array( 'warehouse' => 'stock', 'category' => 'category', 'shipment' => 'sending', - 'shipment_line'=> 'sending' + 'shipment_line'=> 'sending', + 'expensereport'=> 'trip', + 'expensereport_line'=> 'trip' ); // Translation code @@ -95,7 +97,9 @@ $entitytolang = array( 'project' => 'Projects', 'projecttask' => 'Tasks', 'task_time' => 'TaskTimeSpent', - 'action' => 'Action' + 'action' => 'Action', + 'expensereport'=> 'ExpenseReport', + 'expensereport_line'=> 'ExpenseReportLine', ); $array_selected=isset($_SESSION["export_selected_fields"])?$_SESSION["export_selected_fields"]:array(); diff --git a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql index 13c948bea56..4a71995133c 100755 --- a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql +++ b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql @@ -148,7 +148,7 @@ CREATE TABLE llx_expensereport ( fk_user_paid integer DEFAULT NULL, fk_c_expensereport_statuts integer NOT NULL, -- 1=brouillon, 2=validé (attente approb), 4=annulé, 5=approuvé, 6=payed, 99=refusé fk_c_paiement integer DEFAULT NULL, - note text, + note_public text, note_private text, detail_refuse varchar(255) DEFAULT NULL, detail_cancel varchar(255) DEFAULT NULL, diff --git a/htdocs/install/mysql/tables/llx_expensereport.sql b/htdocs/install/mysql/tables/llx_expensereport.sql index 7224ec38b61..e60be7251a5 100755 --- a/htdocs/install/mysql/tables/llx_expensereport.sql +++ b/htdocs/install/mysql/tables/llx_expensereport.sql @@ -46,7 +46,7 @@ CREATE TABLE llx_expensereport ( fk_user_paid integer DEFAULT NULL, fk_c_expensereport_statuts integer NOT NULL, -- 1=brouillon, 2=validé (attente approb), 4=annulé, 5=approuvé, 6=payed, 99=refusé fk_c_paiement integer DEFAULT NULL, - note text, + note_public text, note_private text, detail_refuse varchar(255) DEFAULT NULL, detail_cancel varchar(255) DEFAULT NULL, diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 20d12072b5e..e16a0a30ccc 100755 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1581,3 +1581,5 @@ SortOrder=Sort order Format=Format TypePaymentDesc=0:Customer payment type, 1:Supplier payment type, 2:Both customers and suppliers payment type IncludePath=Include path (defined into variable %s) +ExpenseReportsSetup=Setup of module Expense Reports +TemplatePDFExpenseReports=Document templates to generate expense report document diff --git a/htdocs/langs/en_US/trips.lang b/htdocs/langs/en_US/trips.lang index e5f683eb8fe..c84b8905562 100644 --- a/htdocs/langs/en_US/trips.lang +++ b/htdocs/langs/en_US/trips.lang @@ -27,10 +27,10 @@ AnyOtherInThisListCanValidate=Person to inform for validation. TripSociete=Information company TripSalarie=Informations user TripNDF=Informations expense report - DeleteLine=Delete a ligne of the expense report ConfirmDeleteLine=Are you sure you want to delete this line ? - +PDFStandardExpenseReports=Standard template to generate a PDF document for expense report +ExpenseReportLine=Expense report line TF_OTHER=Other TF_TRANSPORTATION=Transportation TF_LUNCH=Lunch @@ -67,10 +67,11 @@ MOTIF_REFUS=Reason MOTIF_CANCEL=Reason DATE_REFUS=Deny date -DATE_CANCEL=Cancelation date +DATE_SAVE=Validation date DATE_VALIDE=Validation date +DateApprove=Approving date +DATE_CANCEL=Cancelation date DATE_PAIEMENT=Payment date -DATE_SAVE=Recording date Deny=Deny TO_PAID=Pay From 4781707fa444f0b59d71621d3d43bd2ccbf97fc8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 22 Feb 2015 16:01:01 +0100 Subject: [PATCH 171/173] Fix jodconverter can't work without the wrapper jodconverter. --- htdocs/includes/odtphp/odf.php | 15 ++++++----- scripts/odt2pdf/odt2pdf.sh | 49 ++++++++++++++++++++-------------- 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/htdocs/includes/odtphp/odf.php b/htdocs/includes/odtphp/odf.php index d4b79af8013..a13a3923eab 100644 --- a/htdocs/includes/odtphp/odf.php +++ b/htdocs/includes/odtphp/odf.php @@ -486,11 +486,14 @@ IMG; $execmethod=(empty($conf->global->MAIN_EXEC_USE_POPEN)?1:2); // 1 or 2 - $name=str_replace('.odt', '', $name); - if (!empty($conf->global->MAIN_DOL_SCRIPTS_ROOT)) { - $command = $conf->global->MAIN_DOL_SCRIPTS_ROOT.'/scripts/odt2pdf/odt2pdf.sh '.$name; - }else { - $command = '../../scripts/odt2pdf/odt2pdf.sh '.$name; + $name=preg_replace('/\.odt/i', '', $name); + if (!empty($conf->global->MAIN_DOL_SCRIPTS_ROOT)) + { + $command = $conf->global->MAIN_DOL_SCRIPTS_ROOT.'/scripts/odt2pdf/odt2pdf.sh '.$name.' '.(is_numeric($conf->global->MAIN_ODT_AS_PDF)?'jodconverter':$conf->global->MAIN_ODT_AS_PDF); + } + else + { + $command = '../../scripts/odt2pdf/odt2pdf.sh '.$name.' '.(is_numeric($conf->global->MAIN_ODT_AS_PDF)?'jodconverter':$conf->global->MAIN_ODT_AS_PDF); } @@ -620,7 +623,7 @@ IMG; public function getvalue($valuename) { $searchreg="/\\[".$valuename."\\](.*)\\[\\/".$valuename."\\]/"; - preg_match($searchreg, $this->contentXml, $matches); + preg_match($searchreg, $this->contentXml, $matches); $this->contentXml = preg_replace($searchreg, "", $this->contentXml); return $matches[1]; } diff --git a/scripts/odt2pdf/odt2pdf.sh b/scripts/odt2pdf/odt2pdf.sh index c7c768a1244..b44ab3e6d78 100755 --- a/scripts/odt2pdf/odt2pdf.sh +++ b/scripts/odt2pdf/odt2pdf.sh @@ -1,30 +1,27 @@ #!/bin/bash -# @copyright GPL License 2010 - Vikas Mahajan - http://vikasmahajan.wordpress.com -# @copyright GPL License 2013 - Florian HEnry - florian.henry@open-concept.pro +# @copyright GPL License 2010 - Vikas Mahajan - http://vikasmahajan.wordpress.com +# @copyright GPL License 2013 - Florian HEnry - florian.henry@open-concept.pro +# @copyright GPL License 2015 - Laurent Destailleur - eldy@users.sourceforge.net # -# Convert an ODT into a PDF using "jodconverter" tool. -# Dolibarr variable MAIN_ODT_AS_PDF must be defined to have this script called after ODT generation. +# Convert an ODT into a PDF using "jodconverter" or "pyodconverter" tool. +# Dolibarr variable MAIN_ODT_AS_PDF must be defined to value "jodconverter" to call jodconverter wrapper after ODT generation +# or value "pyodconverter" to call DocumentConverter.py after ODT generation. +# or value "/pathto/jodconverter-cli-file.jar" to call jodconverter java tool without wrapper after ODT generation. # Dolibarr variable MAIN_DOL_SCRIPTS_ROOT must be defined to path of script directories (otherwise dolibarr will try to guess). -#if [ -f "$1.odt" ] -# then -# soffice --invisible --convert-to pdf:writer_pdf_Export --outdir $2 "$1.odt" -# retcode=$? -# if [ $retcode -ne 0 ] -# then -# echo "Error while converting odt to pdf: $retcode"; -# exit 1 -# fi -# else -# echo "Error: Odt file does not exist" -# exit 1 -#fi +if [ "x$1" == "x" ] +then + echo "Usage: odt2pdf.sh fullfilename [jodconverter|pyodconverter|pathtojodconverterjar]" + echo "Example: odt2pdf.sh myfile ~/jodconverter/jodconverter-cli-2.2.2.jar" + exit +fi + if [ -f "$1.odt" ] then nbprocess=$(pgrep -c soffice) - if [ $nbprocess -ne 1 ] + if [ $nbprocess -ne 1 ] # If there is some soffice process running then soffice --invisible --accept="socket,host=127.0.0.1,port=8100;urp;" --nofirststartwizard --headless & retcode=$? @@ -35,7 +32,19 @@ if [ -f "$1.odt" ] fi sleep 2 fi - jodconverter "$1.odt" "$1.pdf" + + if [ "x$2" == "xjodconverter" ] + then + jodconverter "$1.odt" "$1.pdf" + else + if [ "x$2" == "xpyodconverter" ] + then + python DocumentConverter.py "$1.odt" "$1.pdf" + else + java -jar $2 "$1.odt" "$1.pdf" + fi + fi + retcode=$? if [ $retcode -ne 0 ] then @@ -44,6 +53,6 @@ if [ -f "$1.odt" ] fi sleep 1 else - echo "Error: Odt file does not exist" + echo "Error: Odt file $1.odt does not exist" exit 1 fi From 6e10dd3cce61650f330591b6ee48bdd1b1c6ebcd Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 22 Feb 2015 17:10:13 +0100 Subject: [PATCH 172/173] Trad --- htdocs/install/mysql/migration/3.7.0-3.8.0.sql | 7 +++++++ htdocs/langs/en_US/main.lang | 1 + 2 files changed, 8 insertions(+) diff --git a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql index 4a71995133c..fb644e5b9a7 100755 --- a/htdocs/install/mysql/migration/3.7.0-3.8.0.sql +++ b/htdocs/install/mysql/migration/3.7.0-3.8.0.sql @@ -19,6 +19,12 @@ -- -- VMYSQL4.1 DELETE FROM llx_usergroup_user WHERE fk_usergroup NOT IN (SELECT rowid from llx_usergroup); +ALTER TABLE llx_commande_fournisseur MODIFY COLUMN date_livraison datetime; + +-- Add id commandefourndet in llx_commande_fournisseur_dispatch to correct /fourn/commande/dispatch.php display when several times same product in supplier order +ALTER TABLE llx_commande_fournisseur_dispatch ADD COLUMN fk_commandefourndet INT(11) NOT NULL DEFAULT '0' AFTER fk_product; + + -- Remove menu entries of removed or renamed modules DELETE FROM llx_menu where module = 'printipp'; @@ -190,3 +196,4 @@ CREATE TABLE llx_expensereport_det ALTER TABLE llx_projet ADD COLUMN budget_amount double(24,8); + diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index d7e82aa43b8..0b5347f6e38 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -141,6 +141,7 @@ Cancel=Cancel Modify=Modify Edit=Edit Validate=Validate +ValidateAndApprove=Validate and Approve ToValidate=To validate Save=Save SaveAs=Save As From 1bba3a01e27f10685dee62c15b21cb4c7a7c893f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 22 Feb 2015 23:41:34 +0100 Subject: [PATCH 173/173] phpcs --- htdocs/core/modules/expensereport/modules_expensereport.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/expensereport/modules_expensereport.php b/htdocs/core/modules/expensereport/modules_expensereport.php index 641f1de9c98..7e40d9df1a2 100755 --- a/htdocs/core/modules/expensereport/modules_expensereport.php +++ b/htdocs/core/modules/expensereport/modules_expensereport.php @@ -54,13 +54,13 @@ class ModeleExpenseReport extends CommonDocGenerator * * @param DoliDB $db Database handler * @param Object $object Object order + * @param string $message Message * @param string $modele Force le modele a utiliser ('' to not force) * @param Translate $outputlangs objet lang a utiliser pour traduction * @param int $hidedetails Hide details of lines * @param int $hidedesc Hide description * @param int $hideref Hide ref * @return int 0 if KO, 1 if OK - * @return number */ function expensereport_pdf_create(DoliDB $db, ExpenseReport $object, $message, $modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0) {