From aa28079e789df1c306aa3702029fd2761b7a1f27 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Wed, 27 Mar 2019 12:42:31 +0100 Subject: [PATCH 001/132] NEW morphy value in member type add value: mor / phy / both(aka null) --- htdocs/adherents/type.php | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/htdocs/adherents/type.php b/htdocs/adherents/type.php index 72ea99ff18d..31ce9768de1 100644 --- a/htdocs/adherents/type.php +++ b/htdocs/adherents/type.php @@ -1,10 +1,11 @@ +/* Copyright (C) 2001-2002 Rodolphe Quiedeville * Copyright (C) 2003 Jean-Louis Bergamo * Copyright (C) 2004-2011 Laurent Destailleur * Copyright (C) 2005-2017 Regis Houssin * Copyright (C) 2013 Florian Henry * Copyright (C) 2015 Alexandre Spangaro + * Copyright (C) 2019 Thibault Foucart * * 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 @@ -57,6 +58,7 @@ if (! $sortorder) { $sortorder="DESC"; } if (! $sortfield) { $sortfield="d.lastname"; } $label=GETPOST("label", "alpha"); +$morphy=GETPOST("morphy","alpha"); $statut=GETPOST("statut", "int"); $subscription=GETPOST("subscription", "int"); $vote=GETPOST("vote", "int"); @@ -103,6 +105,7 @@ if ($cancel) { if ($action == 'add' && $user->rights->adherent->configurer) { $object->label = trim($label); + $object->morphy = trim($morphy); $object->statut = (int) $statut; $object->subscription = (int) $subscription; $object->note = trim($comment); @@ -157,6 +160,7 @@ if ($action == 'update' && $user->rights->adherent->configurer) $object->oldcopy = clone $object; $object->label = trim($label); + $object->morphy = trim($morphy); $object->statut = (int) $statut; $object->subscription = (int) $subscription; $object->note = trim($comment); @@ -215,7 +219,7 @@ if (! $rowid && $action != 'create' && $action != 'edit') { //dol_fiche_head(''); - $sql = "SELECT d.rowid, d.libelle as label, d.subscription, d.vote, d.statut"; + $sql = "SELECT d.rowid, d.libelle as label, d.subscription, d.vote, d.statut, d.morphy"; $sql.= " FROM ".MAIN_DB_PREFIX."adherent_type as d"; $sql.= " WHERE d.entity IN (".getEntity('member_type').")"; @@ -256,6 +260,7 @@ if (! $rowid && $action != 'create' && $action != 'edit') print ''; print ''.$langs->trans("Ref").''; print ''.$langs->trans("Label").''; + print ''.$langs->trans("Nature").''; print ''.$langs->trans("SubscriptionRequired").''; print ''.$langs->trans("VoteAllowed").''; print ''.$langs->trans("Status").''; @@ -277,6 +282,11 @@ if (! $rowid && $action != 'create' && $action != 'edit') //'.img_object($langs->trans("ShowType"),'group').' '.$objp->rowid.' print ''; print ''.dol_escape_htmltag($objp->label).''; + print ''; + if ($objp->morphy == 'phy') { print $langs->trans("Physical"); } + elseif ($objp->morphy == 'mor') { print $langs->trans("Moral"); } + else print $langs->trans("Physical & Morale"); + print ''; print ''.yn($objp->subscription).''; print ''.yn($objp->vote).''; print ''; @@ -330,6 +340,14 @@ if ($action == 'create') print ''.$langs->trans("Status").''; print $form->selectarray('statut', array('0'=>$langs->trans('ActivityCeased'),'1'=>$langs->trans('InActivity')), 1); print ''; + + // Morphy + $morphys[""] = $langs->trans("Physical & Morale"); + $morphys["phy"] = $langs->trans("Physical"); + $morphys["mor"] = $langs->trans("Morale"); + print ''.$langs->trans("Nature").''; + print $form->selectarray("morphy", $morphys, isset($_POST["morphy"])?$_POST["morphy"]:$object->morphy); + print ""; print ''.$langs->trans("SubscriptionRequired").''; print $form->selectyesno("subscription", 1, 1); @@ -411,6 +429,10 @@ if ($rowid > 0) print img_picto($langs->trans('TypeStatusInactive'), 'statut5').' '.$langs->trans("ActivityCeased"); } print ''; + + // Morphy + print ''.$langs->trans("Nature").''.$object->getmorphylib().''; + print ''; print ''.$langs->trans("SubscriptionRequired").''; print yn($object->subscription); @@ -751,6 +773,14 @@ if ($rowid > 0) print ''.$langs->trans("Status").''; print $form->selectarray('statut', array('0'=>$langs->trans('ActivityCeased'),'1'=>$langs->trans('InActivity')), $object->statut); print ''; + + // Morphy + $morphys[""] = $langs->trans("Physical & Morale"); + $morphys["phy"] = $langs->trans("Physical"); + $morphys["mor"] = $langs->trans("Morale"); + print ''.$langs->trans("Nature").''; + print $form->selectarray("morphy", $morphys, isset($_POST["morphy"])?$_POST["morphy"]:$object->morphy); + print ""; print ''.$langs->trans("SubscriptionRequired").''; print $form->selectyesno("subscription", $object->subscription, 1); From 2e9badd21db0ac0a096c7e796d6fda2cca29a813 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Wed, 27 Mar 2019 12:45:33 +0100 Subject: [PATCH 002/132] Update api_memberstypes.class.php --- htdocs/adherents/class/api_memberstypes.class.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/htdocs/adherents/class/api_memberstypes.class.php b/htdocs/adherents/class/api_memberstypes.class.php index abfaf84993d..519a0cecfb3 100644 --- a/htdocs/adherents/class/api_memberstypes.class.php +++ b/htdocs/adherents/class/api_memberstypes.class.php @@ -79,6 +79,7 @@ class MembersTypes extends DolibarrApi * * @param string $sortfield Sort field * @param string $sortorder Sort order + * @param string $nature Nature of type phy, mor or both (for only both not mor or phy only) * @param int $limit Limit for list * @param int $page Page number * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.libelle:like:'SO-%') and (t.subscription:=:'1')" @@ -86,7 +87,7 @@ class MembersTypes extends DolibarrApi * * @throws RestException */ - public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $sqlfilters = '') + public function index($sortfield = "t.rowid", $sortorder = 'ASC', $nature = 'all', $limit = 100, $page = 0, $sqlfilters = '') { global $db, $conf; @@ -100,6 +101,15 @@ class MembersTypes extends DolibarrApi $sql.= " FROM ".MAIN_DB_PREFIX."adherent_type as t"; $sql.= ' WHERE t.entity IN ('.getEntity('member_type').')'; + // Nature + if ($nature != 'all') { + if ($nature == 'both') { + $sql.= ' AND t.morphy IS NULL '; + } else { + $sql.= ' AND (t.morphy IS NULL OR t.morphy = "'.$nature.'")'; + } + } + // Add sql filters if ($sqlfilters) { From fa302db84fff94f565c947a109e1ab27122b4bda Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Wed, 27 Mar 2019 12:48:18 +0100 Subject: [PATCH 003/132] Update adherent_type.class.php --- htdocs/adherents/class/adherent_type.class.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/htdocs/adherents/class/adherent_type.class.php b/htdocs/adherents/class/adherent_type.class.php index 65085caf42a..9c7fcfc5baa 100644 --- a/htdocs/adherents/class/adherent_type.class.php +++ b/htdocs/adherents/class/adherent_type.class.php @@ -1,8 +1,9 @@ +/* Copyright (C) 2002 Rodolphe Quiedeville * Copyright (C) 2004-2008 Laurent Destailleur * Copyright (C) 2009-2017 Regis Houssin * Copyright (C) 2016 Charlie Benke + * Copyright (C) 2019 Thibault Foucart * * 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 @@ -64,6 +65,11 @@ class AdherentType extends CommonObject * @var string Adherent type label */ public $label; + + /** + * @var string Adherent type nature + */ + public $morphy; /** * @var int Subsription required (0 or 1) @@ -184,6 +190,7 @@ class AdherentType extends CommonObject $sql.= "SET "; $sql.= "statut = ".$this->statut.","; $sql.= "libelle = '".$this->db->escape($this->label) ."',"; + $sql.= "morphy = '".$this->db->escape($this->morphy) ."',"; $sql.= "subscription = '".$this->db->escape($this->subscription)."',"; $sql.= "note = '".$this->db->escape($this->note)."',"; $sql.= "vote = ".(integer) $this->db->escape($this->vote).","; @@ -274,7 +281,7 @@ class AdherentType extends CommonObject */ public function fetch($rowid) { - $sql = "SELECT d.rowid, d.libelle as label, d.statut, d.subscription, d.mail_valid, d.note, d.vote"; + $sql = "SELECT d.rowid, d.libelle as label, d.morphy, d.statut, d.subscription, d.mail_valid, d.note, d.vote"; $sql .= " FROM ".MAIN_DB_PREFIX."adherent_type as d"; $sql .= " WHERE d.rowid = ".(int) $rowid; @@ -290,6 +297,7 @@ class AdherentType extends CommonObject $this->id = $obj->rowid; $this->ref = $obj->rowid; $this->label = $obj->label; + $this->morphy = $obj->morphy; $this->statut = $obj->statut; $this->subscription = $obj->subscription; $this->mail_valid = $obj->mail_valid; From 63ad6b779ace4dad5ef242c8cdf72df2877ecc41 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Wed, 27 Mar 2019 12:49:26 +0100 Subject: [PATCH 004/132] Update llx_adherent_type.sql --- htdocs/install/mysql/tables/llx_adherent_type.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/install/mysql/tables/llx_adherent_type.sql b/htdocs/install/mysql/tables/llx_adherent_type.sql index 88867f9d2ad..084d0457941 100644 --- a/htdocs/install/mysql/tables/llx_adherent_type.sql +++ b/htdocs/install/mysql/tables/llx_adherent_type.sql @@ -29,6 +29,7 @@ create table llx_adherent_type tms timestamp, statut smallint NOT NULL DEFAULT 0, libelle varchar(50) NOT NULL, + morphy varchar(3) NOT NULL, subscription varchar(3) NOT NULL DEFAULT 'yes', vote varchar(3) NOT NULL DEFAULT 'yes', note text, From 3723da43ca6c509bcf83d8861360eac27df33871 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Wed, 27 Mar 2019 12:50:16 +0100 Subject: [PATCH 005/132] Update 9.0.0-10.0.0.sql --- htdocs/install/mysql/migration/9.0.0-10.0.0.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/install/mysql/migration/9.0.0-10.0.0.sql b/htdocs/install/mysql/migration/9.0.0-10.0.0.sql index f75c618612d..5b16aa18151 100644 --- a/htdocs/install/mysql/migration/9.0.0-10.0.0.sql +++ b/htdocs/install/mysql/migration/9.0.0-10.0.0.sql @@ -84,6 +84,7 @@ create table llx_mailing_unsubscribe ALTER TABLE llx_mailing_unsubscribe ADD UNIQUE uk_mailing_unsubscribe(email, entity, unsubscribegroup); ALTER TABLE llx_adherent ADD gender VARCHAR(10); +ALTER TABLE llx_adherent_type ADD morphy VARCHAR(3); ALTER TABLE llx_subscription ADD fk_type integer; -- Add url_id into unique index of bank_url From 7a84cb1fc8e0153d486f5661c7c1f556c3ea013a Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Wed, 27 Mar 2019 14:03:37 +0100 Subject: [PATCH 006/132] Update type.php --- htdocs/adherents/type.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/adherents/type.php b/htdocs/adherents/type.php index 31ce9768de1..9a241c027ab 100644 --- a/htdocs/adherents/type.php +++ b/htdocs/adherents/type.php @@ -58,7 +58,7 @@ if (! $sortorder) { $sortorder="DESC"; } if (! $sortfield) { $sortfield="d.lastname"; } $label=GETPOST("label", "alpha"); -$morphy=GETPOST("morphy","alpha"); +$morphy=GETPOST("morphy", "alpha"); $statut=GETPOST("statut", "int"); $subscription=GETPOST("subscription", "int"); $vote=GETPOST("vote", "int"); From 22ea6fa0ab56e5bd7ac0ff9084938fac5e06e1f7 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Wed, 27 Mar 2019 14:04:13 +0100 Subject: [PATCH 007/132] Update api_memberstypes.class.php --- htdocs/adherents/class/api_memberstypes.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/adherents/class/api_memberstypes.class.php b/htdocs/adherents/class/api_memberstypes.class.php index 519a0cecfb3..c80a3c3fe6c 100644 --- a/htdocs/adherents/class/api_memberstypes.class.php +++ b/htdocs/adherents/class/api_memberstypes.class.php @@ -101,13 +101,13 @@ class MembersTypes extends DolibarrApi $sql.= " FROM ".MAIN_DB_PREFIX."adherent_type as t"; $sql.= ' WHERE t.entity IN ('.getEntity('member_type').')'; - // Nature + // Nature if ($nature != 'all') { if ($nature == 'both') { $sql.= ' AND t.morphy IS NULL '; } else { - $sql.= ' AND (t.morphy IS NULL OR t.morphy = "'.$nature.'")'; - } + $sql.= ' AND (t.morphy IS NULL OR t.morphy = "'.$nature.'")'; + } } // Add sql filters From 2da9cfbbe45404482dd208c32aa8c349acd7987c Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Mon, 1 Apr 2019 20:25:37 +0200 Subject: [PATCH 008/132] Update api_memberstypes.class.php --- htdocs/adherents/class/api_memberstypes.class.php | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/htdocs/adherents/class/api_memberstypes.class.php b/htdocs/adherents/class/api_memberstypes.class.php index c80a3c3fe6c..1b477fd567c 100644 --- a/htdocs/adherents/class/api_memberstypes.class.php +++ b/htdocs/adherents/class/api_memberstypes.class.php @@ -79,7 +79,6 @@ class MembersTypes extends DolibarrApi * * @param string $sortfield Sort field * @param string $sortorder Sort order - * @param string $nature Nature of type phy, mor or both (for only both not mor or phy only) * @param int $limit Limit for list * @param int $page Page number * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.libelle:like:'SO-%') and (t.subscription:=:'1')" @@ -87,7 +86,7 @@ class MembersTypes extends DolibarrApi * * @throws RestException */ - public function index($sortfield = "t.rowid", $sortorder = 'ASC', $nature = 'all', $limit = 100, $page = 0, $sqlfilters = '') + public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $sqlfilters = '') { global $db, $conf; @@ -100,15 +99,6 @@ class MembersTypes extends DolibarrApi $sql = "SELECT t.rowid"; $sql.= " FROM ".MAIN_DB_PREFIX."adherent_type as t"; $sql.= ' WHERE t.entity IN ('.getEntity('member_type').')'; - - // Nature - if ($nature != 'all') { - if ($nature == 'both') { - $sql.= ' AND t.morphy IS NULL '; - } else { - $sql.= ' AND (t.morphy IS NULL OR t.morphy = "'.$nature.'")'; - } - } // Add sql filters if ($sqlfilters) From abd8dca3eac7f4e56cf845a8a78e4ce42fc2e6be Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Mon, 1 Apr 2019 20:26:04 +0200 Subject: [PATCH 009/132] Update api_memberstypes.class.php --- htdocs/adherents/class/api_memberstypes.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/adherents/class/api_memberstypes.class.php b/htdocs/adherents/class/api_memberstypes.class.php index 1b477fd567c..abfaf84993d 100644 --- a/htdocs/adherents/class/api_memberstypes.class.php +++ b/htdocs/adherents/class/api_memberstypes.class.php @@ -99,7 +99,7 @@ class MembersTypes extends DolibarrApi $sql = "SELECT t.rowid"; $sql.= " FROM ".MAIN_DB_PREFIX."adherent_type as t"; $sql.= ' WHERE t.entity IN ('.getEntity('member_type').')'; - + // Add sql filters if ($sqlfilters) { From 41a82023e385046afbb9d68ff5eb308040288a7a Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Wed, 24 Apr 2019 08:17:10 +0200 Subject: [PATCH 010/132] FIX missing compatibility with multicompany --- htdocs/core/tpl/card_presend.tpl.php | 2 +- htdocs/user/class/user.class.php | 27 +++++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/htdocs/core/tpl/card_presend.tpl.php b/htdocs/core/tpl/card_presend.tpl.php index 58758daab09..54464488f0b 100644 --- a/htdocs/core/tpl/card_presend.tpl.php +++ b/htdocs/core/tpl/card_presend.tpl.php @@ -171,7 +171,7 @@ if ($action == 'presend') $listeuser=array(); $fuserdest = new User($db); - $result= $fuserdest->fetchAll('ASC', 't.lastname', 0, 0, array('customsql'=>'t.statut=1 AND t.employee=1 AND t.email IS NOT NULL AND t.email<>\'\'')); + $result= $fuserdest->fetchAll('ASC', 't.lastname', 0, 0, array('customsql'=>'t.statut=1 AND t.employee=1 AND t.email IS NOT NULL AND t.email<>\'\''), 'AND', true); if ($result>0 && is_array($fuserdest->users) && count($fuserdest->users)>0) { foreach($fuserdest->users as $uuserdest) { $listeuser[$uuserdest->id] = $uuserdest->user_get_property($uuserdest->id,'email'); diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index a02b4916c91..8fd87c839c7 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -3206,15 +3206,38 @@ class User extends CommonObject * @param int $offset page * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) * @param string $filtermode Filter mode (AND or OR) + * @param bool $entityfilter Activate entity filter * @return int <0 if KO, >0 if OK */ - function fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, $filter=array(), $filtermode='AND') + function fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, $filter=array(), $filtermode='AND', $entityfilter=false) { global $conf; $sql="SELECT t.rowid"; $sql.= ' FROM '.MAIN_DB_PREFIX .$this->table_element.' as t '; - $sql.= " WHERE 1"; + + if ($entityfilter) + { + if (! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) + { + if (! empty($user->admin) && empty($user->entity) && $conf->entity == 1) { + $sql.= " WHERE t.entity IS NOT NULL"; // Show all users + } else { + $sql.= ",".MAIN_DB_PREFIX."usergroup_user as ug"; + $sql.= " WHERE ((ug.fk_user = t.rowid"; + $sql.= " AND ug.entity IN (".getEntity('user')."))"; + $sql.= " OR t.entity = 0)"; // Show always superadmin + } + } + else + { + $sql.= " WHERE t.entity IN (".getEntity('user').")"; + } + } + else + { + $sql.= " WHERE 1"; + } // Manage filter $sqlwhere = array(); From 740fddcd429398b54b09455e1762a9312c00b6a6 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Wed, 24 Apr 2019 08:22:00 +0200 Subject: [PATCH 011/132] FIX missing global $user --- htdocs/user/class/user.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 8fd87c839c7..1bfaa24c066 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -3211,7 +3211,7 @@ class User extends CommonObject */ function fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, $filter=array(), $filtermode='AND', $entityfilter=false) { - global $conf; + global $conf, $user; $sql="SELECT t.rowid"; $sql.= ' FROM '.MAIN_DB_PREFIX .$this->table_element.' as t '; From 57ce70bbc900fb8b542a52c3a8c6384fbea390e6 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Wed, 24 Apr 2019 13:08:13 +0200 Subject: [PATCH 012/132] NEW enhancement management of webhooks active / inactive and sync only needed events --- htdocs/stripe/admin/stripe.php | 82 +++++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 12 deletions(-) diff --git a/htdocs/stripe/admin/stripe.php b/htdocs/stripe/admin/stripe.php index 5e2c27dd392..1336bed8575 100644 --- a/htdocs/stripe/admin/stripe.php +++ b/htdocs/stripe/admin/stripe.php @@ -2,7 +2,7 @@ /* Copyright (C) 2017 Alexandre Spangaro * Copyright (C) 2017 Olivier Geffroy * Copyright (C) 2017 Saasprov - * Copyright (C) 2018 ptibogxiv + * Copyright (C) 2018 Thibault FOUCART * Copyright (C) 2018 Frédéric France * * This program is free software; you can redistribute it and/or modify @@ -30,6 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/stripe/lib/stripe.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; +require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; $servicename='Stripe'; @@ -150,6 +151,8 @@ print ''; dol_fiche_head($head, 'stripeaccount', '', -1); +$stripearrayofwebhookevents=array('payout.created','payout.paid','charge.pending','charge.refunded','charge.succeeded','charge.failed','payment_intent.succeeded','payment_intent.payment_failed','source.chargeable','customer.deleted'); + print $langs->trans("StripeDesc")."
\n"; print '
'; @@ -158,6 +161,7 @@ print ''; print ''; print ''; print ''; +print ''; print "\n"; print ''; @@ -177,24 +181,51 @@ if (empty($conf->stripeconnect->enabled)) print ''.$langs->trans("STRIPE_TEST_PUBLISHABLE_KEY").''; + print ''; print ''; + print ''; print ''; + print '
'.$out; + print ''; } else { print ''; print ''; + print ''; print ''; + print ''; print ''; + print '
'.$out; + print ''; } else { From 6d06f128e775606680593f628307c53b29c47d2a Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Wed, 24 Apr 2019 13:51:41 +0200 Subject: [PATCH 013/132] Update stripe.php --- htdocs/stripe/admin/stripe.php | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/htdocs/stripe/admin/stripe.php b/htdocs/stripe/admin/stripe.php index 1336bed8575..f0b9c6361bf 100644 --- a/htdocs/stripe/admin/stripe.php +++ b/htdocs/stripe/admin/stripe.php @@ -199,15 +199,15 @@ if (empty($conf->stripeconnect->enabled)) $url = dol_buildpath('/public/stripe/ipn.php?test', 2); $out.= ''; $out.= ajax_autoselect("onlinetestwebhookurl", 0); - print '
'.$out; + print '
'.$out; print '
'; } else { print ''; @@ -267,9 +267,9 @@ if ( !empty($conf->global->STRIPE_LIVE_WEBHOOK_KEY) && !empty($conf->global->STR \Stripe\Stripe::setApiKey($conf->global->STRIPE_LIVE_SECRET_KEY); $endpoint = \Stripe\WebhookEndpoint::retrieve($conf->global->STRIPE_LIVE_WEBHOOK_ID); $endpoint->enabled_events = $stripearrayofwebhookevents; -if ( GETPOST('webhook','alpha') == $conf->global->STRIPE_LIVE_WEBHOOK_ID ) { -if ( empty( GETPOST('status','alpha') )) { -$endpoint->disabled = true; +if ( GETPOST('webhook', 'alpha') == $conf->global->STRIPE_LIVE_WEBHOOK_ID ) { +if ( empty( GETPOST('status', 'alpha') )) { +$endpoint->disabled = true; } else { $endpoint->disabled = false; }} @@ -278,15 +278,15 @@ $endpoint->save(); if ($endpoint->status == 'enabled') { print ''; - print img_picto($langs->trans("Activated"),'switch_on'); + print img_picto($langs->trans("Activated"), 'switch_on'); } else { print ''; - print img_picto($langs->trans("Disabled"),'switch_off'); + print img_picto($langs->trans("Disabled"), 'switch_off'); } //print $endpoint; -} else print img_picto($langs->trans("inactive"),'statut5'); +} else print img_picto($langs->trans("inactive"), 'statut5'); print ''; } else From 99e56f9cfa455574b8c8028bdace07e0f7976229 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Wed, 24 Apr 2019 14:53:31 +0200 Subject: [PATCH 014/132] Update stripe.php --- htdocs/stripe/admin/stripe.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/stripe/admin/stripe.php b/htdocs/stripe/admin/stripe.php index f0b9c6361bf..50d4fbf281b 100644 --- a/htdocs/stripe/admin/stripe.php +++ b/htdocs/stripe/admin/stripe.php @@ -209,7 +209,7 @@ if ( GETPOST('webhook', 'alpha') == $conf->global->STRIPE_TEST_WEBHOOK_ID ) { if ( empty( GETPOST('status', 'alpha') )) { $endpoint->disabled = true; } else { -$endpoint->disabled = false; + $endpoint->disabled = false; }} $endpoint->url = dol_buildpath('/public/stripe/ipn.php?test', 2); $endpoint->save(); @@ -269,9 +269,9 @@ $endpoint = \Stripe\WebhookEndpoint::retrieve($conf->global->STRIPE_LIVE_WEBHOOK $endpoint->enabled_events = $stripearrayofwebhookevents; if ( GETPOST('webhook', 'alpha') == $conf->global->STRIPE_LIVE_WEBHOOK_ID ) { if ( empty( GETPOST('status', 'alpha') )) { -$endpoint->disabled = true; + $endpoint->disabled = true; } else { -$endpoint->disabled = false; + $endpoint->disabled = false; }} $endpoint->url = dol_buildpath('/public/stripe/ipn.php', 2); $endpoint->save(); From 70017da95ac0db4c16ad4041f0bdd5ea5fea28f7 Mon Sep 17 00:00:00 2001 From: atm-greg Date: Wed, 24 Apr 2019 14:59:54 +0200 Subject: [PATCH 015/132] testing if customer invoice module is activated doesn't make sense on supplier commande card... --- htdocs/fourn/commande/card.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index a6629b9bd25..7b3561a0bf0 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -2342,14 +2342,11 @@ elseif (! empty($object->id)) } // Create bill - if (! empty($conf->facture->enabled)) + if (! empty($conf->fournisseur->enabled) && ($object->statut >= 2 && $object->statut != 7 && $object->billed != 1)) // statut 2 means approved, 7 means canceled { - if (! empty($conf->fournisseur->enabled) && ($object->statut >= 2 && $object->statut != 7 && $object->billed != 1)) // statut 2 means approved, 7 means canceled + if ($user->rights->fournisseur->facture->creer) { - if ($user->rights->fournisseur->facture->creer) - { - print ''.$langs->trans("CreateBill").''; - } + print ''.$langs->trans("CreateBill").''; } } From c485cc7a89b853f1ef596e712cabc33b4ab5c963 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Wed, 24 Apr 2019 15:41:08 +0200 Subject: [PATCH 016/132] Update stripe.php --- htdocs/stripe/admin/stripe.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/stripe/admin/stripe.php b/htdocs/stripe/admin/stripe.php index 50d4fbf281b..54102b99df5 100644 --- a/htdocs/stripe/admin/stripe.php +++ b/htdocs/stripe/admin/stripe.php @@ -206,7 +206,7 @@ if ( !empty($conf->global->STRIPE_TEST_WEBHOOK_KEY) && !empty($conf->global->STR $endpoint = \Stripe\WebhookEndpoint::retrieve($conf->global->STRIPE_TEST_WEBHOOK_ID); $endpoint->enabled_events = $stripearrayofwebhookevents; if ( GETPOST('webhook', 'alpha') == $conf->global->STRIPE_TEST_WEBHOOK_ID ) { -if ( empty( GETPOST('status', 'alpha') )) { +if ( empty(GETPOST('status', 'alpha')) ) { $endpoint->disabled = true; } else { $endpoint->disabled = false; @@ -261,14 +261,14 @@ if (empty($conf->stripeconnect->enabled)) $url = dol_buildpath('/public/stripe/ipn.php', 2); $out.= ''; $out.= ajax_autoselect("onlinelivewebhookurl", 0); - print '
'.$out; + print '
'.$out; print '
'; print ''; + if ( !empty($conf->global->STRIPE_LIVE_WEBHOOK_KEY) && !empty($conf->global->STRIPE_LIVE_SECRET_KEY) && !empty($conf->global->STRIPE_LIVE_WEBHOOK_ID) ) { + \Stripe\Stripe::setApiKey($conf->global->STRIPE_LIVE_SECRET_KEY); + $endpoint = \Stripe\WebhookEndpoint::retrieve($conf->global->STRIPE_LIVE_WEBHOOK_ID); + $endpoint->enabled_events = $stripearrayofwebhookevents; + if ( GETPOST('webhook', 'alpha') == $conf->global->STRIPE_LIVE_WEBHOOK_ID ) { + if ( empty(GETPOST('status', 'alpha')) ) { + $endpoint->disabled = true; + } else { + $endpoint->disabled = false; + }} + $endpoint->url = dol_buildpath('/public/stripe/ipn.php', 3); + $endpoint->save(); + if ($endpoint->status == 'enabled') + { + print ''; + print img_picto($langs->trans("Activated"), 'switch_on'); + } + else + { + print ''; + print img_picto($langs->trans("Disabled"), 'switch_off'); + } + //print $endpoint; + } else print img_picto($langs->trans("inactive"), 'statut5'); + print ''; } else { From 2e277d643d7417dfbb42e28f52f4d4e5bd57fce2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 24 Apr 2019 21:26:58 +0200 Subject: [PATCH 019/132] Stabilize code to prepare beta freeze. --- htdocs/public/stripe/ipn.php | 2 +- htdocs/stripe/admin/stripe.php | 142 +++++++++++++++++++-------------- 2 files changed, 83 insertions(+), 61 deletions(-) diff --git a/htdocs/public/stripe/ipn.php b/htdocs/public/stripe/ipn.php index 82a0ad525ef..d889041be60 100644 --- a/htdocs/public/stripe/ipn.php +++ b/htdocs/public/stripe/ipn.php @@ -144,7 +144,7 @@ $societeName = $conf->global->MAIN_INFO_SOCIETE_NOM; if (! empty($conf->global->MAIN_APPLICATION_TITLE)) $societeName = $conf->global->MAIN_APPLICATION_TITLE; -dol_syslog("Stripe IPN was calle with event->type = ".$event->type); +dol_syslog("Stripe IPN was called with event->type = ".$event->type); if ($event->type == 'payout.created') { diff --git a/htdocs/stripe/admin/stripe.php b/htdocs/stripe/admin/stripe.php index 3135592d528..134030687df 100644 --- a/htdocs/stripe/admin/stripe.php +++ b/htdocs/stripe/admin/stripe.php @@ -165,7 +165,7 @@ print '
'.$langs->trans("AccountParameter").''.$langs->trans("Value").''.$langs->trans("Status").'
'; print ''; print '   '.$langs->trans("Example").': pk_test_xxxxxxxxxxxxxxxxxxxxxxxx'; - print '
'; print ''.$langs->trans("STRIPE_TEST_SECRET_KEY").''; print ''; print '   '.$langs->trans("Example").': sk_test_xxxxxxxxxxxxxxxxxxxxxxxx'; - print '
'; - print ''.$langs->trans("STRIPE_TEST_WEBHOOK_KEY").''; + print ''.$langs->trans("STRIPE_TEST_WEBHOOK_KEY").''; + print ''; + print '   '.$langs->trans("Example").': we_xxxxxxxxxxxxxxxxxxxxxxxx
'; print ''; print '   '.$langs->trans("Example").': whsec_xxxxxxxxxxxxxxxxxxxxxxxx'; - $out = img_picto('', 'object_globe.png').' '.$langs->trans("ToOfferALinkForTestWebhook").'
'; + $out = img_picto('', 'object_globe.png').' '.$langs->trans("ToOfferALinkForTestWebhook").'
'; $url = dol_buildpath('/public/stripe/ipn.php?test', 2); $out.= ''; $out.= ajax_autoselect("onlinetestwebhookurl", 0); - print '
'.$out; - print '
'; +if ( !empty($conf->global->STRIPE_TEST_WEBHOOK_KEY) && !empty($conf->global->STRIPE_TEST_SECRET_KEY) && !empty($conf->global->STRIPE_TEST_WEBHOOK_ID) ) { +\Stripe\Stripe::setApiKey($conf->global->STRIPE_TEST_SECRET_KEY); +$endpoint = \Stripe\WebhookEndpoint::retrieve($conf->global->STRIPE_TEST_WEBHOOK_ID); +$endpoint->enabled_events = $stripearrayofwebhookevents; +if ( GETPOST('webhook','alpha') == $conf->global->STRIPE_TEST_WEBHOOK_ID ) { +if ( empty( GETPOST('status','alpha') )) { +$endpoint->disabled = true; +} else { +$endpoint->disabled = false; +}} +$endpoint->url = dol_buildpath('/public/stripe/ipn.php?test', 2); +$endpoint->save(); +if ($endpoint->status == 'enabled') +{ + print ''; + print img_picto($langs->trans("Activated"),'switch_on'); +} +else +{ + print ''; + print img_picto($langs->trans("Disabled"),'switch_off'); +} +//print $endpoint; +} else print img_picto($langs->trans("inactive"),'statut5'); + print'
'.$langs->trans("StripeConnect").''.$langs->trans("StripeConnect_Mode").'
'; @@ -212,24 +243,51 @@ if (empty($conf->stripeconnect->enabled)) print ''.$langs->trans("STRIPE_LIVE_PUBLISHABLE_KEY").'
'; print ''; print '   '.$langs->trans("Example").': pk_live_xxxxxxxxxxxxxxxxxxxxxxxx'; - print '
'; print ''.$langs->trans("STRIPE_LIVE_SECRET_KEY").''; print ''; print '   '.$langs->trans("Example").': sk_live_xxxxxxxxxxxxxxxxxxxxxxxx'; - print '
'; - print ''.$langs->trans("STRIPE_LIVE_WEBHOOK_KEY").''; + print ''.$langs->trans("STRIPE_LIVE_WEBHOOK_KEY").''; + print ''; + print '   '.$langs->trans("Example").': we_xxxxxxxxxxxxxxxxxxxxxxxx
'; print ''; print '   '.$langs->trans("Example").': whsec_xxxxxxxxxxxxxxxxxxxxxxxx'; $out = img_picto('', 'object_globe.png').' '.$langs->trans("ToOfferALinkForLiveWebhook").'
'; $url = dol_buildpath('/public/stripe/ipn.php', 2); $out.= ''; $out.= ajax_autoselect("onlinelivewebhookurl", 0); - print '
'.$out; - print '
'; +if ( !empty($conf->global->STRIPE_LIVE_WEBHOOK_KEY) && !empty($conf->global->STRIPE_LIVE_SECRET_KEY) && !empty($conf->global->STRIPE_LIVE_WEBHOOK_ID) ) { +\Stripe\Stripe::setApiKey($conf->global->STRIPE_LIVE_SECRET_KEY); +$endpoint = \Stripe\WebhookEndpoint::retrieve($conf->global->STRIPE_LIVE_WEBHOOK_ID); +$endpoint->enabled_events = $stripearrayofwebhookevents; +if ( GETPOST('webhook','alpha') == $conf->global->STRIPE_LIVE_WEBHOOK_ID ) { +if ( empty( GETPOST('status','alpha') )) { +$endpoint->disabled = true; +} else { +$endpoint->disabled = false; +}} +$endpoint->url = dol_buildpath('/public/stripe/ipn.php', 2); +$endpoint->save(); +if ($endpoint->status == 'enabled') +{ + print ''; + print img_picto($langs->trans("Activated"),'switch_on'); +} +else +{ + print ''; + print img_picto($langs->trans("Disabled"),'switch_off'); +} +//print $endpoint; +} else print img_picto($langs->trans("inactive"),'statut5'); + print '
'; if ( !empty($conf->global->STRIPE_TEST_WEBHOOK_KEY) && !empty($conf->global->STRIPE_TEST_SECRET_KEY) && !empty($conf->global->STRIPE_TEST_WEBHOOK_ID) ) { \Stripe\Stripe::setApiKey($conf->global->STRIPE_TEST_SECRET_KEY); $endpoint = \Stripe\WebhookEndpoint::retrieve($conf->global->STRIPE_TEST_WEBHOOK_ID); $endpoint->enabled_events = $stripearrayofwebhookevents; -if ( GETPOST('webhook','alpha') == $conf->global->STRIPE_TEST_WEBHOOK_ID ) { -if ( empty( GETPOST('status','alpha') )) { -$endpoint->disabled = true; +if ( GETPOST('webhook', 'alpha') == $conf->global->STRIPE_TEST_WEBHOOK_ID ) { +if ( empty( GETPOST('status', 'alpha') )) { + $endpoint->disabled = true; } else { $endpoint->disabled = false; }} @@ -216,15 +216,15 @@ $endpoint->save(); if ($endpoint->status == 'enabled') { print ''; - print img_picto($langs->trans("Activated"),'switch_on'); + print img_picto($langs->trans("Activated"), 'switch_on'); } else { print ''; - print img_picto($langs->trans("Disabled"),'switch_off'); + print img_picto($langs->trans("Disabled"), 'switch_off'); } //print $endpoint; -} else print img_picto($langs->trans("inactive"),'statut5'); +} else print img_picto($langs->trans("inactive"), 'statut5'); print'
'.$langs->trans("StripeConnect").'
'; if ( !empty($conf->global->STRIPE_LIVE_WEBHOOK_KEY) && !empty($conf->global->STRIPE_LIVE_SECRET_KEY) && !empty($conf->global->STRIPE_LIVE_WEBHOOK_ID) ) { \Stripe\Stripe::setApiKey($conf->global->STRIPE_LIVE_SECRET_KEY); $endpoint = \Stripe\WebhookEndpoint::retrieve($conf->global->STRIPE_LIVE_WEBHOOK_ID); $endpoint->enabled_events = $stripearrayofwebhookevents; if ( GETPOST('webhook', 'alpha') == $conf->global->STRIPE_LIVE_WEBHOOK_ID ) { -if ( empty( GETPOST('status', 'alpha') )) { +if ( empty(GETPOST('status', 'alpha')) ) { $endpoint->disabled = true; } else { $endpoint->disabled = false; From 0583cf7804ab5261e7e0dc6af5ca1af652c4ae09 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Wed, 24 Apr 2019 15:44:57 +0200 Subject: [PATCH 017/132] Update adherent_type.class.php --- htdocs/adherents/class/adherent_type.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/adherents/class/adherent_type.class.php b/htdocs/adherents/class/adherent_type.class.php index 9c7fcfc5baa..df7c5c5558c 100644 --- a/htdocs/adherents/class/adherent_type.class.php +++ b/htdocs/adherents/class/adherent_type.class.php @@ -3,7 +3,7 @@ * Copyright (C) 2004-2008 Laurent Destailleur * Copyright (C) 2009-2017 Regis Houssin * Copyright (C) 2016 Charlie Benke - * Copyright (C) 2019 Thibault Foucart + * Copyright (C) 2018-2019 Thibault Foucart * * 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 77f92a5da32bb9949fc75f5e78db708caad92a08 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 24 Apr 2019 21:12:43 +0200 Subject: [PATCH 018/132] Update stripe.php --- htdocs/stripe/admin/stripe.php | 56 +++++++++++++++++----------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/htdocs/stripe/admin/stripe.php b/htdocs/stripe/admin/stripe.php index 02471d57a76..3135592d528 100644 --- a/htdocs/stripe/admin/stripe.php +++ b/htdocs/stripe/admin/stripe.php @@ -215,7 +215,7 @@ if ( empty(GETPOST('status', 'alpha')) ) { } else { $endpoint->disabled = false; }} -$endpoint->url = dol_buildpath('/public/stripe/ipn.php?test', 2); +$endpoint->url = dol_buildpath('/public/stripe/ipn.php?test', 3); $endpoint->save(); if ($endpoint->status == 'enabled') { @@ -256,8 +256,8 @@ if (empty($conf->stripeconnect->enabled)) print '
'; - print ''; - print '   '.$langs->trans("Example").': we_xxxxxxxxxxxxxxxxxxxxxxxx
'; + print ''; + print '   '.$langs->trans("Example").': we_xxxxxxxxxxxxxxxxxxxxxxxx
'; print ''.$langs->trans("STRIPE_LIVE_WEBHOOK_KEY").'
'; print ''; print '   '.$langs->trans("Example").': whsec_xxxxxxxxxxxxxxxxxxxxxxxx'; @@ -267,31 +267,31 @@ if (empty($conf->stripeconnect->enabled)) $out.= ajax_autoselect("onlinelivewebhookurl", 0); print '
'.$out; print '
'; -if ( !empty($conf->global->STRIPE_LIVE_WEBHOOK_KEY) && !empty($conf->global->STRIPE_LIVE_SECRET_KEY) && !empty($conf->global->STRIPE_LIVE_WEBHOOK_ID) ) { -\Stripe\Stripe::setApiKey($conf->global->STRIPE_LIVE_SECRET_KEY); -$endpoint = \Stripe\WebhookEndpoint::retrieve($conf->global->STRIPE_LIVE_WEBHOOK_ID); -$endpoint->enabled_events = $stripearrayofwebhookevents; -if ( GETPOST('webhook', 'alpha') == $conf->global->STRIPE_LIVE_WEBHOOK_ID ) { -if ( empty(GETPOST('status', 'alpha')) ) { - $endpoint->disabled = true; -} else { - $endpoint->disabled = false; -}} -$endpoint->url = dol_buildpath('/public/stripe/ipn.php', 2); -$endpoint->save(); -if ($endpoint->status == 'enabled') -{ - print ''; - print img_picto($langs->trans("Activated"), 'switch_on'); -} -else -{ - print ''; - print img_picto($langs->trans("Disabled"), 'switch_off'); -} -//print $endpoint; -} else print img_picto($langs->trans("inactive"), 'statut5'); - print '
'; print ''; print ''; print ''; -print ''; +print ''; print "\n"; print ''; @@ -177,7 +177,7 @@ print $langs->trans("StripeLiveEnabled").''; +print ''; if (empty($conf->stripeconnect->enabled)) { @@ -195,41 +195,52 @@ if (empty($conf->stripeconnect->enabled)) print ''; + if ($conf->global->MAIN_FEATURES_LEVEL >= 2) + { + if (!empty($conf->global->STRIPE_TEST_WEBHOOK_KEY) && !empty($conf->global->STRIPE_TEST_SECRET_KEY) && !empty($conf->global->STRIPE_TEST_WEBHOOK_ID)) + { + \Stripe\Stripe::setApiKey($conf->global->STRIPE_TEST_SECRET_KEY); + $endpoint = \Stripe\WebhookEndpoint::retrieve($conf->global->STRIPE_TEST_WEBHOOK_ID); + $endpoint->enabled_events = $stripearrayofwebhookevents; + if (GETPOST('webhook', 'alpha') == $conf->global->STRIPE_TEST_WEBHOOK_ID) { + if (empty(GETPOST('status', 'alpha'))) { + $endpoint->disabled = true; + } else { + $endpoint->disabled = false; + } + } + $endpoint->url = dol_buildpath('/public/stripe/ipn.php?test', 3); + $endpoint->save(); + if ($endpoint->status == 'enabled') + { + print ''; + print img_picto($langs->trans("Activated"), 'switch_on'); + } + else + { + print ''; + print img_picto($langs->trans("Disabled"), 'switch_off'); + } + //print $endpoint; + } + else + { + print img_picto($langs->trans("inactive"), 'statut5'); + } + } + print''; } else { print ''; print ''; - print ''; + print ''; } if (empty($conf->stripeconnect->enabled)) @@ -256,47 +267,58 @@ if (empty($conf->stripeconnect->enabled)) print ''; print ''; } else { print ''; - print ''; + print ''; } From aa9184905acf6eb5395e878447ce82b6ef19f409 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 25 Apr 2019 00:11:08 +0200 Subject: [PATCH 020/132] FIX Duration is lost when editing --- htdocs/product/card.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/product/card.php b/htdocs/product/card.php index 5c2862a0b63..50c0d4ab5c9 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -74,8 +74,8 @@ $action=(GETPOST('action', 'alpha') ? GETPOST('action', 'alpha') : 'view'); $cancel=GETPOST('cancel', 'alpha'); $confirm=GETPOST('confirm', 'alpha'); $socid=GETPOST('socid', 'int'); -$duration_value = GETPOST('duration_value'); -$duration_unit = GETPOST('duration_unit'); +$duration_value = GETPOST('duration_value', 'int'); +$duration_unit = GETPOST('duration_unit', 'alpha'); if (! empty($user->societe_id)) $socid=$user->societe_id; $object = new Product($db); @@ -399,8 +399,8 @@ if (empty($reshook)) $object->seuil_stock_alerte = GETPOST('seuil_stock_alerte'); $object->desiredstock = GETPOST('desiredstock'); */ - $object->duration_value = GETPOST('duration_value'); - $object->duration_unit = GETPOST('duration_unit'); + $object->duration_value = GETPOST('duration_value', 'int'); + $object->duration_unit = GETPOST('duration_unit', 'alpha'); $object->canvas = GETPOST('canvas'); $object->weight = GETPOST('weight'); @@ -1025,7 +1025,7 @@ else if ($type == 1) { print ''; } @@ -1401,7 +1401,7 @@ else { // Duration print ''; } From e5c2027dbb69d16eefcc28ae03104f32f30a9685 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 25 Apr 2019 01:16:29 +0200 Subject: [PATCH 021/132] NEW Add accounting code for eec sales and export sales on products --- htdocs/core/class/extrafields.class.php | 2 +- htdocs/langs/en_US/products.lang | 2 +- htdocs/product/card.php | 119 +++++++++++------------- htdocs/product/list.php | 46 +++++++-- 4 files changed, 94 insertions(+), 75 deletions(-) diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index 865aa50b679..26acdf50fcc 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -1837,7 +1837,7 @@ class ExtraFields $out=''; // Only if something to display (perf) - if ($value) // If we have -1 here, pb is into sert, not into ouptu + if ($value) // If we have -1 here, pb is into insert, not into ouptut (fix insert instead of changing code here to compensate) { $param_list=array_keys($param['options']); // $param_list='ObjectName:classPath' diff --git a/htdocs/langs/en_US/products.lang b/htdocs/langs/en_US/products.lang index 3304ab3b3ef..e69d771fa79 100644 --- a/htdocs/langs/en_US/products.lang +++ b/htdocs/langs/en_US/products.lang @@ -294,7 +294,7 @@ ProductSheet=Product sheet ServiceSheet=Service sheet PossibleValues=Possible values GoOnMenuToCreateVairants=Go on menu %s - %s to prepare attribute variants (like colors, size, ...) -UseProductFournDesc=Use vendor descriptions of products in vendor documents +UseProductFournDesc=Add a feature to define the descriptions of products defined by the vendors in addition to descriptions for customers ProductSupplierDescription=Vendor description for the product #Attributes VariantAttributes=Variant attributes diff --git a/htdocs/product/card.php b/htdocs/product/card.php index 50c0d4ab5c9..2c8b70efbd1 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -1218,21 +1218,19 @@ else print ''; - if ($conf->global->MAIN_FEATURES_LEVEL) + // Accountancy_code_sell_intra + if ($mysoc->isInEEC()) { - // Accountancy_code_sell_intra - if ($mysoc->isInEEC()) { - print ''; - print ''; - } - - // Accountancy_code_sell_export - print ''; - print ''; + print ''; } + // Accountancy_code_sell_export + print ''; + print ''; + // Accountancy_code_buy print ''; print ''; - if ($conf->global->MAIN_FEATURES_LEVEL) + // Accountancy_code_sell_intra + if ($mysoc->isInEEC()) { - // Accountancy_code_sell_intra - if ($mysoc->isInEEC()) - { - print ''; - print ''; - } - - // Accountancy_code_sell_export - print ''; + print ''; print ''; } + // Accountancy_code_sell_export + print ''; + print ''; + // Accountancy_code_buy print ''; print ''; - if ($conf->global->MAIN_FEATURES_LEVEL) + // Accountancy_code_sell_intra + if ($mysoc->isInEEC()) { - // Accountancy_code_sell_intra - if ($mysoc->isInEEC()) - { - print ''; - print ''; - } - - // Accountancy_code_sell_export - print ''; - print ''; + print ''; } + // Accountancy_code_sell_export + print ''; + print ''; + // Accountancy_code_buy print ''; print ''; - if ($conf->global->MAIN_FEATURES_LEVEL) + // Accountancy sell code intra-community + if ($mysoc->isInEEC()) { - // Accountancy sell code intra-community - if ($mysoc->isInEEC()) - { - print ''; - } - - // Accountancy sell code export print ''; } + // Accountancy sell code export + print ''; + // Accountancy buy code print ''; // Accountancy code sell - if (! empty($arrayfields['p.accountancy_code_sell']['checked'])) print ''; - // Accountancy code sell + if (! empty($arrayfields['p.accountancy_code_sell']['checked'])) print ''; + if (! empty($arrayfields['p.accountancy_code_sell_intra']['checked'])) print ''; + if (! empty($arrayfields['p.accountancy_code_sell_export']['checked'])) print ''; + // Accountancy code buy if (! empty($arrayfields['p.accountancy_code_buy']['checked'])) print ''; // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; @@ -723,7 +737,13 @@ if ($resql) if (! empty($arrayfields['p.accountancy_code_sell']['checked'])) { print_liste_field_titre($arrayfields['p.accountancy_code_sell']['label'], $_SERVER["PHP_SELF"], "p.accountancy_code_sell", "", $param, '', $sortfield, $sortorder); } - if (! empty($arrayfields['p.accountancy_code_buy']['checked'])) { + if (! empty($arrayfields['p.accountancy_code_sell_intra']['checked'])) { + print_liste_field_titre($arrayfields['p.accountancy_code_sell_intra']['label'], $_SERVER["PHP_SELF"], "p.accountancy_code_sell_intra", "", $param, '', $sortfield, $sortorder); + } + if (! empty($arrayfields['p.accountancy_code_sell_export']['checked'])) { + print_liste_field_titre($arrayfields['p.accountancy_code_sell_export']['label'], $_SERVER["PHP_SELF"], "p.accountancy_code_sell_export", "", $param, '', $sortfield, $sortorder); + } + if (! empty($arrayfields['p.accountancy_code_buy']['checked'])) { print_liste_field_titre($arrayfields['p.accountancy_code_buy']['label'], $_SERVER["PHP_SELF"], "p.accountancy_code_buy", "", $param, '', $sortfield, $sortorder); } // Extra fields @@ -1032,7 +1052,17 @@ if ($resql) print ''; if (! $i) $totalarray['nbfield']++; } - // Accountancy code sell + if (! empty($arrayfields['p.accountancy_code_sell_intra']['checked'])) + { + print ''; + if (! $i) $totalarray['nbfield']++; + } + if (! empty($arrayfields['p.accountancy_code_sell_export']['checked'])) + { + print ''; + if (! $i) $totalarray['nbfield']++; + } + // Accountancy code buy if (! empty($arrayfields['p.accountancy_code_buy']['checked'])) { print ''; From 560b026d68166cc97906c618fabd12967bd34c82 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 25 Apr 2019 01:26:29 +0200 Subject: [PATCH 022/132] Fix CSS --- 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 8b6ca6a5ca3..8922b1675dd 100644 --- a/htdocs/core/lib/project.lib.php +++ b/htdocs/core/lib/project.lib.php @@ -461,7 +461,7 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t } // Ref of task - print ''; // Morphy - print ''; + print ''; print ''; print ''; print_liste_field_titre('Ref', $_SERVER["PHP_SELF"], 'c.rowid', '', $param, '', $sortfield, $sortorder); print ''; + print ''; print ''; print ''; print ''; @@ -711,9 +713,15 @@ if ($rowid > 0) $subscriptionstatic->ref=$objp->crowid; $subscriptionstatic->id=$objp->crowid; + $adht = new AdherentType($db); + $adht->fetch($objp->cfk_type); + print ''; print ''; print '\n"; + print ''; print '\n"; print '\n"; print ''; From e80436469f9034882a4351a0b8a00ddc4629af4c Mon Sep 17 00:00:00 2001 From: Lionel VESSILLER Date: Thu, 25 Apr 2019 16:05:12 +0200 Subject: [PATCH 032/132] Fix default payment condition and method --- htdocs/fourn/commande/orderstoinvoice.php | 25 +++++++++++++---------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/htdocs/fourn/commande/orderstoinvoice.php b/htdocs/fourn/commande/orderstoinvoice.php index 4b9511ce0df..093e0fd331b 100644 --- a/htdocs/fourn/commande/orderstoinvoice.php +++ b/htdocs/fourn/commande/orderstoinvoice.php @@ -298,11 +298,23 @@ if ($action == 'create' && !$error) { if ($socid) $res = $soc->fetch($socid); if ($res) { - $cond_reglement_id = $soc->cond_reglement_id; - $mode_reglement_id = $soc->mode_reglement_id; + $cond_reglement_id = $soc->cond_reglement_supplier_id; + $mode_reglement_id = $soc->mode_reglement_supplier_id; } $dateinvoice = empty($conf->global->MAIN_AUTOFILL_DATE) ? - 1 : ''; + $objectsrc = new CommandeFournisseur($db); + $listoforders = array(); + foreach ($selected as $sel) { + $result = $objectsrc->fetch($sel); + if ($result > 0) { + $listoforders[] = $objectsrc->ref; + } + + if (empty($cond_reglement_id)) $cond_reglement_id = $objectsrc->cond_reglement_id; + if (empty($mode_reglement_id)) $mode_reglement_id = $objectsrc->mode_reglement_id; + } + print '
'; print ''; print ''; @@ -350,15 +362,6 @@ if ($action == 'create' && !$error) { print '
'; } - $objectsrc = new CommandeFournisseur($db); - $listoforders = array (); - foreach ($selected as $sel) { - $result = $objectsrc->fetch($sel); - if ($result > 0) { - $listoforders[] = $objectsrc->ref; - } - } - // Other attributes $parameters = array ( 'objectsrc' => $objectsrc, From 4353925d95e21b8782b47af192cb8af3264d86b0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 25 Apr 2019 19:02:16 +0200 Subject: [PATCH 033/132] Update subscription.php --- htdocs/adherents/subscription.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/htdocs/adherents/subscription.php b/htdocs/adherents/subscription.php index 9961471fdd6..cf85e7b2acf 100644 --- a/htdocs/adherents/subscription.php +++ b/htdocs/adherents/subscription.php @@ -705,6 +705,7 @@ if ($rowid > 0) print "\n"; $accountstatic=new Account($db); + $adht = new AdherentType($db); while ($i < $num) { @@ -713,14 +714,19 @@ if ($rowid > 0) $subscriptionstatic->ref=$objp->crowid; $subscriptionstatic->id=$objp->crowid; - $adht = new AdherentType($db); - $adht->fetch($objp->cfk_type); + if ($objp->cfk_type > 0) + { + $adht->fetch($objp->cfk_type); + } print ''; print ''; print '\n"; print ''; print '\n"; print '\n"; From 23f4536a78426b0b087bf5706feaf56a03591ace Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Thu, 25 Apr 2019 19:22:14 +0200 Subject: [PATCH 034/132] FIX : sync data thirdparty to member --- htdocs/societe/class/societe.class.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 70a06ad8341..4bec5fc6f49 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -1136,12 +1136,16 @@ class Societe extends CommonObject //$lmember->firstname=$this->firstname?$this->firstname:$lmember->firstname; // We keep firstname and lastname of member unchanged //$lmember->lastname=$this->lastname?$this->lastname:$lmember->lastname; // We keep firstname and lastname of member unchanged $lmember->address=$this->address; + $lmember->zip=$this->zip; + $lmember->town=$this->town; $lmember->email=$this->email; $lmember->skype=$this->skype; $lmember->twitter=$this->twitter; $lmember->facebook=$this->facebook; $lmember->linkedin=$this->linkedin; $lmember->phone=$this->phone; + $lmember->state_id=$this->state_id; + $lmember->country_id=$this->country_id; $result=$lmember->update($user, 0, 1, 1, 1); // Use nosync to 1 to avoid cyclic updates if ($result < 0) From 10dde837d0c73c0bec1e9e490e8979c67628fd68 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 25 Apr 2019 17:37:54 +0200 Subject: [PATCH 035/132] Debug email collector --- htdocs/admin/emailcollector_card.php | 30 +- htdocs/core/lib/functions.lib.php | 7 +- htdocs/core/tpl/commonfields_view.tpl.php | 2 +- .../class/emailcollector.class.php | 457 ++++++++++++------ .../class/emailcollectorfilter.class.php | 2 +- .../install/mysql/migration/9.0.0-10.0.0.sql | 1 + .../llx_emailcollector_emailcollector.sql | 1 + htdocs/langs/en_US/admin.lang | 3 + htdocs/langs/en_US/mails.lang | 2 + 9 files changed, 350 insertions(+), 155 deletions(-) diff --git a/htdocs/admin/emailcollector_card.php b/htdocs/admin/emailcollector_card.php index 3d14d8fee2f..31a8520505d 100644 --- a/htdocs/admin/emailcollector_card.php +++ b/htdocs/admin/emailcollector_card.php @@ -452,19 +452,25 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print ''; print ''; if (! empty($val['help'])) print $form->textwithpicto($langs->trans($val['label']), $langs->trans($val['help'])); diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 6249325261a..09675c67fa3 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -92,8 +92,8 @@ class EmailCollector extends CommonObject */ public $fields=array( 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID','visible'=>2, 'enabled'=>1, 'position'=>1, 'notnull'=>1, 'index'=>1), - 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'default'=>1, 'notnull'=>1, 'index'=>1, 'position'=>20), - 'ref' =>array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>10, 'searchall'=>1, 'help'=>'Example: MyCollector1'), + 'entity' => array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'default'=>1, 'notnull'=>1, 'index'=>1, 'position'=>20), + 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'showoncombobox'=>1, 'index'=>1, 'position'=>10, 'searchall'=>1, 'help'=>'Example: MyCollector1'), 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'visible'=>1, 'enabled'=>1, 'position'=>30, 'notnull'=>-1, 'searchall'=>1, 'help'=>'Example: My Email collector'), 'description' => array('type'=>'text', 'label'=>'Description', 'visible'=>-1, 'enabled'=>1, 'position'=>60, 'notnull'=>-1), 'host' => array('type'=>'varchar(255)', 'label'=>'EMailHost', 'visible'=>1, 'enabled'=>1, 'position'=>100, 'notnull'=>1, 'searchall'=>1, 'comment'=>"IMAP server", 'help'=>'Example: imap.gmail.com'), @@ -103,6 +103,7 @@ class EmailCollector extends CommonObject //'filter' => array('type'=>'text', 'label'=>'Filter', 'visible'=>1, 'enabled'=>1, 'position'=>105), //'actiontodo' => array('type'=>'varchar(255)', 'label'=>'ActionToDo', 'visible'=>1, 'enabled'=>1, 'position'=>106), 'target_directory' => array('type'=>'varchar(255)', 'label'=>'MailboxTargetDirectory', 'visible'=>1, 'enabled'=>1, 'position'=>110, 'notnull'=>0, 'comment'=>"Where to store messages once processed"), + 'maxemailpercollect' => array('type'=>'integer', 'label'=>'MaxEmailCollectPerCollect','visible'=>-1, 'enabled'=>1, 'position'=>111, 'default'=>100), 'datelastresult' => array('type'=>'datetime', 'label'=>'DateLastCollectResult', 'visible'=>1, 'enabled'=>'$action != "create" && $action != "edit"', 'position'=>121, 'notnull'=>-1,), 'codelastresult' => array('type'=>'varchar(16)', 'label'=>'CodeLastResult', 'visible'=>1, 'enabled'=>'$action != "create" && $action != "edit"', 'position'=>122, 'notnull'=>-1,), 'lastresult' => array('type'=>'varchar(255)', 'label'=>'LastResult', 'visible'=>1, 'enabled'=>'$action != "create" && $action != "edit"', 'position'=>123, 'notnull'=>-1,), @@ -167,6 +168,7 @@ class EmailCollector extends CommonObject public $password; public $source_directory; public $target_directory; + public $maxemailpercollect; public $datelastresult; public $lastresult; // END MODULEBUILDER PROPERTIES @@ -717,12 +719,6 @@ class EmailCollector extends CommonObject return $nberror; } - /** - * overwitePropertiesOfObject - * - * @return int 0=OK, Nb of error if error - */ - /** * overwitePropertiesOfObject * @@ -755,7 +751,8 @@ class EmailCollector extends CommonObject } if ($tmpclass && ($tmpclass != $object->element)) continue; // Property is for another type of object - if (property_exists($object, $tmpproperty) || preg_match('/^options_/', $tmpproperty)) + //if (property_exists($object, $tmpproperty) || preg_match('/^options_/', $tmpproperty)) + if ($tmpproperty) { $sourcestring=''; $sourcefield=''; @@ -782,8 +779,12 @@ class EmailCollector extends CommonObject if ($sourcestring) { $regforval=array(); - //var_dump($regexstring);var_dump($sourcestring); - if (preg_match('/'.$regexstring.'/ms', $sourcestring, $regforval)) + $regexoptions=''; + if (strtolower($sourcefield) == 'body') $regexoptions='ms'; // The m means ^ and $ char is valid at each new line. The s means the char '.' is valid for new lines char too + if (strtolower($sourcefield) == 'header') $regexoptions='m'; // The m means ^ and $ char is valid at each new line. + + //var_dump($tmpproperty.' - '.$regexstring.' - '.$regexoptions.' - '.$sourcestring); + if (preg_match('/'.$regexstring.'/'.$regexoptions, $sourcestring, $regforval)) { //var_dump($regforval[1]);exit; // Overwrite param $tmpproperty @@ -794,7 +795,6 @@ class EmailCollector extends CommonObject // Regex not found $object->$tmpproperty = null; } - //var_dump($object->$tmpproperty);exit; } else { @@ -806,8 +806,27 @@ class EmailCollector extends CommonObject } elseif (preg_match('/^SET:(.*)$/', $valueforproperty, $reg)) { - if (preg_match('/^options_/', $tmpproperty)) $object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $reg[1]; - else $object->$tmpproperty = $reg[1]; + $valuetouse = $reg[1]; + $substitutionarray=array(); + $matcharray=array(); + preg_match_all('/__([a-z0-9]+(?:_[a-z0-9]+)?)__/i', $valuetouse, $matcharray); + //var_dump($tmpproperty.' - '.$object->$tmpproperty.' - '.$valuetouse); var_dump($matcharray); + if (is_array($matcharray[1])) // $matcharray[1] is array with list of substitution key found without the __ + { + foreach($matcharray[1] as $keytoreplace) + { + if ($keytoreplace && isset($object->$keytoreplace)) + { + $substitutionarray['__'.$keytoreplace.'__']=$object->$keytoreplace; + } + } + } + //var_dump($substitutionarray); + dol_syslog(var_export($substitutionarray, true)); + //var_dump($substitutionarray); + $valuetouse = make_substitutions($valuetouse, $substitutionarray); + if (preg_match('/^options_/', $tmpproperty)) $object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $valuetouse; + else $object->$tmpproperty = $valuetouse; } else { @@ -887,7 +906,8 @@ class EmailCollector extends CommonObject $host=dol_getprefix('email'); // Define the IMAP search string - // See https://tools.ietf.org/html/rfc3501#section-6.4.4 + // See https://tools.ietf.org/html/rfc3501#section-6.4.4 for IMAPv4 (PHP not yet compatible) + // See https://tools.ietf.org/html/rfc1064 page 13 for IMAPv2 //$search='ALL'; $search='UNDELETED'; // Seems not supported by some servers $searchhead=''; @@ -905,8 +925,13 @@ class EmailCollector extends CommonObject if ($rule['type'] == 'body') $search.=($search?' ':'').'BODY "'.str_replace('"', '', $rule['rulevalue']).'"'; if ($rule['type'] == 'header') $search.=($search?' ':'').'HEADER '.$rule['rulevalue']; + if ($rule['type'] == 'notinsubject') $search.=($search?' ':'').'SUBJECT NOT "'.str_replace('"', '', $rule['rulevalue']).'"'; + if ($rule['type'] == 'notinbody') $search.=($search?' ':'').'BODY NOT "'.str_replace('"', '', $rule['rulevalue']).'"'; + if ($rule['type'] == 'seen') $search.=($search?' ':'').'SEEN'; if ($rule['type'] == 'unseen') $search.=($search?' ':'').'UNSEEN'; + if ($rule['type'] == 'unanswered') $search.=($search?' ':'').'UNANSWERED'; + if ($rule['type'] == 'answered') $search.=($search?' ':'').'ANSWERED'; if ($rule['type'] == 'smaller') $search.=($search?' ':'').'SMALLER "'.str_replace('"', '', $rule['rulevalue']).'"'; if ($rule['type'] == 'larger') $search.=($search?' ':'').'LARGER "'.str_replace('"', '', $rule['rulevalue']).'"'; @@ -945,9 +970,87 @@ class EmailCollector extends CommonObject // Loop on each email found if (! $error && ! empty($arrayofemail) && count($arrayofemail) > 0) { + // Loop to get part html and plain + /* + 0 multipart/mixed + 1 multipart/alternative + 1.1 text/plain + 1.2 text/html + 2 message/rfc822 + 2 multipart/mixed + 2.1 multipart/alternative + 2.1.1 text/plain + 2.1.2 text/html + 2.2 message/rfc822 + 2.2 multipart/alternative + 2.2.1 text/plain + 2.2.2 text/html + */ + /** + * create_part_array + * + * @param Object $structure Structure + * @param string $prefix prefix + * @return array Array with number and object + */ + /*function createPartArray($structure, $prefix = "") + { + //print_r($structure); + $part_array=array(); + if (count($structure->parts) > 0) { // There some sub parts + foreach ($structure->parts as $count => $part) { + addPartToArray($part, $prefix.($count+1), $part_array); + } + }else{ // Email does not have a seperate mime attachment for text + $part_array[] = array('part_number' => $prefix.'1', 'part_object' => $structure); + } + return $part_array; + }*/ + + /** + * Sub function for createPartArray(). Only called by createPartArray() and itself. + * + * @param Object $obj Structure + * @param string $partno Part no + * @param array $part_array array + * @return void + */ + /*function addPartToArray($obj, $partno, &$part_array) + { + $part_array[] = array('part_number' => $partno, 'part_object' => $obj); + if ($obj->type == 2) { // Check to see if the part is an attached email message, as in the RFC-822 type + //print_r($obj); + if (array_key_exists('parts', $obj)) { // Check to see if the email has parts + foreach ($obj->parts as $count => $part) { + // Iterate here again to compensate for the broken way that imap_fetchbody() handles attachments + if (count($part->parts) > 0) { + foreach ($part->parts as $count2 => $part2) { + addPartToArray($part2, $partno.".".($count2+1), $part_array); + } + }else{ // Attached email does not have a seperate mime attachment for text + $part_array[] = array('part_number' => $partno.'.'.($count+1), 'part_object' => $obj); + } + } + }else{ // Not sure if this is possible + $part_array[] = array('part_number' => $partno.'.1', 'part_object' => $obj); + } + }else{ // If there are more sub-parts, expand them out. + if (array_key_exists('parts', $obj)) { + foreach ($obj->parts as $count => $p) { + addPartToArray($p, $partno.".".($count+1), $part_array); + } + } + } + }*/ + + dol_syslog("Start of loop on email", LOG_INFO, 1); + foreach($arrayofemail as $imapemail) { - if ($nbemailprocessed > 100) break; // Do not process more than 100 email per launch + if ($nbemailprocessed > 1000) + { + break; // Do not process more than 1000 email per launch (this is a different protection than maxnbcollectedpercollect + } $header = imap_fetchheader($connection, $imapemail, 0); $matches=array(); @@ -988,125 +1091,63 @@ class EmailCollector extends CommonObject $this->db->begin(); - //$message = imap_body($connection, $imapemail, 0); + // GET Email meta datas $overview = imap_fetch_overview($connection, $imapemail, 0); + + dol_syslog("** Process email - msgid=".$overview[0]->message_id." date=".dol_print_date($overview[0]->udate, 'dayrfc', 'gmt')." subject=".$overview[0]->subject); + + // Parse IMAP email structure + global $htmlmsg, $plainmsg, $charset, $attachments; + $this->getmsg($connection, $imapemail); + + //$htmlmsg,$plainmsg,$charset,$attachments + $messagetext = $plainmsg ? $plainmsg : dol_string_nohtmltag($htmlmsg, 0); + /*var_dump($plainmsg); + var_dump($htmlmsg); + var_dump($messagetext);*/ + /*var_dump($charset); + var_dump($attachments); + exit;*/ + + // Parse IMAP email structure + /* $structure = imap_fetchstructure($connection, $imapemail, 0); $partplain = $parthtml = -1; - // Loop to get part html and plain - /* - 0 multipart/mixed - 1 multipart/alternative - 1.1 text/plain - 1.2 text/html - 2 message/rfc822 - 2 multipart/mixed - 2.1 multipart/alternative - 2.1.1 text/plain - 2.1.2 text/html - 2.2 message/rfc822 - 2.2 multipart/alternative - 2.2.1 text/plain - 2.2.2 text/html - */ - /** - * create_part_array - * - * @param Object $structure Structure - * @param string $prefix prefix - * @return array Array with number and object - */ - function createPartArray($structure, $prefix = "") - { - //print_r($structure); - $part_array=array(); - if (count($structure->parts) > 0) { // There some sub parts - foreach ($structure->parts as $count => $part) { - add_part_to_array($part, $prefix.($count+1), $part_array); - } - }else{ // Email does not have a seperate mime attachment for text - $part_array[] = array('part_number' => $prefix.'1', 'part_object' => $obj); - } - return $part_array; - } - - /** - * Sub function for createPartArray(). Only called by createPartArray() and itself. - * - * @param Object $obj Structure - * @param string $partno Part no - * @param array $part_array array - * @return void - */ - function addPartToArray($obj, $partno, &$part_array) - { - $part_array[] = array('part_number' => $partno, 'part_object' => $obj); - if ($obj->type == 2) { // Check to see if the part is an attached email message, as in the RFC-822 type - //print_r($obj); - if (array_key_exists('parts', $obj)) { // Check to see if the email has parts - foreach ($obj->parts as $count => $part) { - // Iterate here again to compensate for the broken way that imap_fetchbody() handles attachments - if (count($part->parts) > 0) { - foreach ($part->parts as $count2 => $part2) { - addPartToArray($part2, $partno.".".($count2+1), $part_array); - } - }else{ // Attached email does not have a seperate mime attachment for text - $part_array[] = array('part_number' => $partno.'.'.($count+1), 'part_object' => $obj); - } - } - }else{ // Not sure if this is possible - $part_array[] = array('part_number' => $partno.'.1', 'part_object' => $obj); - } - }else{ // If there are more sub-parts, expand them out. - if (array_key_exists('parts', $obj)) { - foreach ($obj->parts as $count => $p) { - addPartToArray($p, $partno.".".($count+1), $part_array); - } - } - } - } + $encodingplain = $encodinghtml = ''; $result = createPartArray($structure, ''); - //var_dump($result);exit; + foreach($result as $part) { - if ($part['part_object']->subtype == 'HTML') $parthtml=$part['part_number']; - if ($part['part_object']->subtype == 'PLAIN') $partplain=$part['part_number']; + // $part['part_object']->type seems 0 for content + // $part['part_object']->type seems 5 for attachment + if (empty($part['part_object'])) continue; + if ($part['part_object']->subtype == 'HTML') + { + $parthtml=$part['part_number']; + if ($part['part_object']->encoding == 4) + { + $encodinghtml = 'aaa'; + } + } + if ($part['part_object']->subtype == 'PLAIN') + { + $partplain=$part['part_number']; + if ($part['part_object']->encoding == 4) + { + $encodingplain = 'rr'; + } + } } + //var_dump($result); var_dump($partplain); var_dump($parthtml); - /* OLD CODE to get parthtml and partplain - if (count($structure->parts) > 0) { // There some sub parts - foreach($structure->parts as $key => $part) - { - if ($part->subtype == 'HTML') $parthtml=($key+1); // For example: $parthtml = 1 or 2 - if ($part->subtype == 'PLAIN') $partplain=($key+1); - if ($part->subtype == 'ALTERNATIVE') - { - if (count($part->parts) > 0) - { - foreach($part->parts as $key2 => $part2) - { - if ($part2->subtype == 'HTML') $parthtml=($key+1).'.'.($key2+1); // For example: $parthtml = 1.1 or 1.2 - if ($part2->subtype == 'PLAIN') $partplain=($key+1).'.'.($key2+1); - } - } - else - { - $partplain=($key+1).'.1'; - } - } - } - } - else - { - $partplain=1; - }*/ - - /*var_dump($structure); + var_dump($structure); var_dump($parthtml); - var_dump($partplain);*/ + var_dump($partplain); $messagetext = imap_fetchbody($connection, $imapemail, ($parthtml != '-1' ? $parthtml : ($partplain != '-1' ? $partplain : 1)), FT_PEEK); + */ //var_dump($messagetext); //var_dump($structure->parts[0]->parts); @@ -1282,12 +1323,12 @@ class EmailCollector extends CommonObject elseif ($operation['type'] == 'ticket') $descriptiontitle = $langs->trans("TicketCreatedByEmailCollector", $msgid); else $descriptiontitle = $langs->trans("ActionAC_".$actioncode).' - '.$langs->trans("MailFrom").' '.$from; - $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("Topic").' : '.$subject); - $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("From").' : '.$fromstring); - if ($sender) $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("Sender").' : '.$sender); - $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("To").' : '.$to); - //if ($cc) $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("Cc").' : '.$cc); - //if ($bcc) $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("Bcc").' : '.$bcc); + $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("MailTopic").' : '.dol_escape_htmltag($subject)); + $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("MailFrom").($langs->trans("MailFrom") != 'From' ? ' (From)':'').' : '.dol_escape_htmltag($fromstring)); + if ($sender) $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("Sender").($langs->trans("Sender") != 'Sender' ? ' (Sender)':'').' : '.dol_escape_htmltag($sender)); + $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("MailTo").($langs->trans("MailTo") != 'To' ? ' (To)':'').' : '.dol_escape_htmltag($to)); + if ($sendtocc) $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("MailCC").($langs->trans("MailCC") != 'CC' ? ' (CC)':'').' : '.dol_escape_htmltag($sendtocc)); + //if ($bcc) $descriptionmeta = dol_concatdesc($descriptionmeta, $langs->trans("Bcc").' : '.dol_escape_htmltag($bcc)); } // Search and create thirdparty @@ -1521,12 +1562,12 @@ class EmailCollector extends CommonObject $percent_opp_status = dol_getIdFromCode($this->db, 'PROSP', 'c_lead_status', 'code', 'percent'); $projecttocreate->title = $subject; - $projecttocreate->date_start = $now; + $projecttocreate->date_start = $date; $projecttocreate->date_end = ''; $projecttocreate->opp_status = $id_opp_status; $projecttocreate->opp_percent = $percent_opp_status; $projecttocreate->description = dol_concatdesc(dolGetFirstLineOfText(dol_string_nohtmltag($description, 2), 10), '...'.$langs->transnoentities("SeePrivateNote").'...'); - $projecttocreate->note_private = dol_concatdesc($descriptionfull, dol_string_nohtmltag($descriptionfull, 2)); + $projecttocreate->note_private = $descriptionfull; $projecttocreate->entity = $conf->entity; // Get next project Ref @@ -1616,11 +1657,12 @@ class EmailCollector extends CommonObject $tickettocreate->severity_code = 0; $tickettocreate->origin_email = $from; $tickettocreate->fk_user_create = $user->id; - $tickettocreate->entity = $conf->entity; $tickettocreate->datec = $date; $tickettocreate->fk_project = $projectstatic->id; $tickettocreate->fk_soc = $thirdpartystatic->id; $tickettocreate->notify_tiers_at_create = 0; + $tickettocreate->note_private = $descriptionfull; + $tickettocreate->entity = $conf->entity; //$tickettocreate->fk_contact = $contactstatic->id; // Get next project Ref @@ -1709,12 +1751,26 @@ class EmailCollector extends CommonObject $errorforemail++; } + unset($objectemail); + unset($projectstatic); + unset($thirdpartystatic); + unset($contactstatic); + + $nbemailprocessed++; + if (! $errorforemail) { $nbactiondone += $nbactiondoneforemail; $nbemailok++; $this->db->commit(); + + // Stop the loop to process email if we reach maximum collected per collect + if ($this->maxemailpercollect > 0 && $nbemailok >= $this->maxemailpercollect) + { + dol_syslog("EmailCollect::doCollectOneCollector We reach maximum of ".$nbemailok." collected with success, so we stop this collector now."); + break; + } } else { @@ -1722,16 +1778,11 @@ class EmailCollector extends CommonObject $this->db->rollback(); } - - $nbemailprocessed++; - - unset($objectemail); - unset($projectstatic); - unset($thirdpartystatic); - unset($contactstatic); } $output=$langs->trans('XEmailsDoneYActionsDone', $nbemailprocessed, $nbemailok, $nbactiondone); + + dol_syslog("End of loop on emails", LOG_INFO, -1); } else { @@ -1757,4 +1808,134 @@ class EmailCollector extends CommonObject return $error?-1:1; } + + + + // Loop to get part html and plain. Code found on PHP imap_fetchstructure documentation + + /** + * getmsg + * + * @param Object $mbox Structure + * @param string $mid prefix + * @return array Array with number and object + */ + function getmsg($mbox, $mid) { + // input $mbox = IMAP stream, $mid = message id + // output all the following: + global $charset,$htmlmsg,$plainmsg,$attachments; + $htmlmsg = $plainmsg = $charset = ''; + $attachments = array(); + + // HEADER + //$h = imap_header($mbox,$mid); + // add code here to get date, from, to, cc, subject... + + // BODY + $s = imap_fetchstructure($mbox,$mid); + + if (!$s->parts) // simple + $this->getpart($mbox,$mid,$s,0); // pass 0 as part-number + else { // multipart: cycle through each part + foreach ($s->parts as $partno0=>$p) + { + $this->getpart($mbox, $mid, $p, $partno0+1); + } + } + } + + /* partno string + 0 multipart/mixed + 1 multipart/alternative + 1.1 text/plain + 1.2 text/html + 2 message/rfc822 + 2 multipart/mixed + 2.1 multipart/alternative + 2.1.1 text/plain + 2.1.2 text/html + 2.2 message/rfc822 + 2.2 multipart/alternative + 2.2.1 text/plain + 2.2.2 text/html + */ + /** + * Sub function for getpart(). Only called by createPartArray() and itself. + * + * @param Object $mbox Structure + * @param string $mid Part no + * @param Object $p Object p + * @param string $partno Partno + * @return void + */ + private function getpart($mbox, $mid, $p, $partno) { + // $partno = '1', '2', '2.1', '2.1.3', etc for multipart, 0 if simple + global $htmlmsg,$plainmsg,$charset,$attachments; + + // DECODE DATA + $data = ($partno)? + imap_fetchbody($mbox,$mid,$partno): // multipart + imap_body($mbox,$mid); // simple + // Any part may be encoded, even plain text messages, so check everything. + if ($p->encoding==4) + $data = quoted_printable_decode($data); + elseif ($p->encoding==3) + $data = base64_decode($data); + + // PARAMETERS + // get all parameters, like charset, filenames of attachments, etc. + $params = array(); + if ($p->parameters) + { + foreach ($p->parameters as $x) + { + $params[strtolower($x->attribute)] = $x->value; + } + } + if ($p->dparameters) + { + foreach ($p->dparameters as $x) + { + $params[strtolower($x->attribute)] = $x->value; + } + } + + // ATTACHMENT + // Any part with a filename is an attachment, + // so an attached text file (type 0) is not mistaken as the message. + if ($params['filename'] || $params['name']) { + // filename may be given as 'Filename' or 'Name' or both + $filename = ($params['filename'])? $params['filename'] : $params['name']; + // filename may be encoded, so see imap_mime_header_decode() + $attachments[$filename] = $data; // this is a problem if two files have same name + } + + // TEXT + if ($p->type==0 && $data) { + // Messages may be split in different parts because of inline attachments, + // so append parts together with blank row. + if (strtolower($p->subtype)=='plain') + $plainmsg .= trim($data) ."\n\n"; + else + $htmlmsg .= $data ."

"; + $charset = $params['charset']; // assume all parts are same charset + } + + // EMBEDDED MESSAGE + // Many bounce notifications embed the original message as type 2, + // but AOL uses type 1 (multipart), which is not handled here. + // There are no PHP functions to parse embedded messages, + // so this just appends the raw source to the main message. + elseif ($p->type==2 && $data) { + $plainmsg .= $data."\n\n"; + } + + // SUBPART RECURSION + if ($p->parts) { + foreach ($p->parts as $partno0=>$p2) + { + $this->getpart($mbox,$mid,$p2,$partno.'.'.($partno0+1)); // 1.2, 1.2.1, etc. + } + } + } } diff --git a/htdocs/emailcollector/class/emailcollectorfilter.class.php b/htdocs/emailcollector/class/emailcollectorfilter.class.php index 75a94436ff9..f93ac51f673 100644 --- a/htdocs/emailcollector/class/emailcollectorfilter.class.php +++ b/htdocs/emailcollector/class/emailcollectorfilter.class.php @@ -159,7 +159,7 @@ class EmailCollectorFilter extends CommonObject $this->errors[]=$langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")); return -1; } - if (! in_array($this->type, array('seen','unseen','withtrackingid','withouttrackingid')) && empty($this->rulevalue)) + if (! in_array($this->type, array('seen', 'unseen', 'unanswered', 'answered', 'withtrackingid', 'withouttrackingid')) && empty($this->rulevalue)) { $langs->load("errors"); $this->errors[]=$langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("SearchString")); diff --git a/htdocs/install/mysql/migration/9.0.0-10.0.0.sql b/htdocs/install/mysql/migration/9.0.0-10.0.0.sql index 2ea3132cc6b..9aa395c22d6 100644 --- a/htdocs/install/mysql/migration/9.0.0-10.0.0.sql +++ b/htdocs/install/mysql/migration/9.0.0-10.0.0.sql @@ -285,6 +285,7 @@ ALTER TABLE llx_product ADD INDEX idx_product_fk_project (fk_project); ALTER TABLE llx_actioncomm ADD COLUMN calling_duration integer; ALTER TABLE llx_emailcollector_emailcollector ADD COLUMN datelastok datetime; +ALTER TABLE llx_emailcollector_emailcollector ADD COLUMN maxemailpercollect integer DEFAULT 100; DELETE FROM llx_const WHERE name = 'THEME_ELDY_USE_HOVER' AND value = '0'; DELETE FROM llx_const WHERE name = 'THEME_ELDY_USE_CHECKED' AND value = '0'; diff --git a/htdocs/install/mysql/tables/llx_emailcollector_emailcollector.sql b/htdocs/install/mysql/tables/llx_emailcollector_emailcollector.sql index 6ad62dfd305..2a7bc6a4693 100644 --- a/htdocs/install/mysql/tables/llx_emailcollector_emailcollector.sql +++ b/htdocs/install/mysql/tables/llx_emailcollector_emailcollector.sql @@ -26,6 +26,7 @@ CREATE TABLE llx_emailcollector_emailcollector( password varchar(128), source_directory varchar(255) NOT NULL, target_directory varchar(255), + maxemailpercollect integer DEFAULT 100, datelastresult datetime, codelastresult varchar(16), lastresult varchar(255), diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 24453159a23..3979ee83638 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -72,6 +72,8 @@ UseSearchToSelectContactTooltip=Also if you have a large number of third parties DelaiedFullListToSelectCompany=Wait until a key is pressed before loading content of Third Parties combo list.
This may increase performance if you have a large number of third parties, but it is less convenient. DelaiedFullListToSelectContact=Wait until a key is pressed before loading content of Contact combo list.
This may increase performance if you have a large number of contacts, but it is less convenient) NumberOfKeyToSearch=Number of characters to trigger search: %s +NumberOfBytes=Number of Bytes +SearchString=Search string NotAvailableWhenAjaxDisabled=Not available when Ajax disabled AllowToSelectProjectFromOtherCompany=On document of a third party, can choose a project linked to another third party JavascriptDisabled=JavaScript disabled @@ -1828,6 +1830,7 @@ EMailHost=Host of email IMAP server MailboxSourceDirectory=Mailbox source directory MailboxTargetDirectory=Mailbox target directory EmailcollectorOperations=Operations to do by collector +MaxEmailCollectPerCollect=Max number of emails collected per collect CollectNow=Collect now ConfirmCloneEmailCollector=Are you sure you want to clone the Email collector %s ? DateLastCollectResult=Date latest collect tried diff --git a/htdocs/langs/en_US/mails.lang b/htdocs/langs/en_US/mails.lang index b50faffe2fa..ba334d69a22 100644 --- a/htdocs/langs/en_US/mails.lang +++ b/htdocs/langs/en_US/mails.lang @@ -19,6 +19,8 @@ MailTopic=Email topic MailText=Message MailFile=Attached files MailMessage=Email body +SubjectNotIn=Not in Subject +BodyNotIn=Not in Body ShowEMailing=Show emailing ListOfEMailings=List of emailings NewMailing=New emailing From e332288e730bd011e3aa825c66533cd16ecbc2f2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 25 Apr 2019 19:46:20 +0200 Subject: [PATCH 036/132] Fix concat --- .../emailcollector/class/emailcollector.class.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 09675c67fa3..536e40fb3c6 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -1462,15 +1462,15 @@ class EmailCollector extends CommonObject { if ($projectstatic->id > 0) { - if ($projectfoundby) $descriptionmeta .= dol_concatdesc($descriptionmeta, 'Project found from '.$projectfoundby); + if ($projectfoundby) $descriptionmeta = dol_concatdesc($descriptionmeta, 'Project found from '.$projectfoundby); } if ($thirdpartystatic->id > 0) { - if ($thirdpartyfoundby) $descriptionmeta .= dol_concatdesc($descriptionmeta, 'Third party found from '.$thirdpartyfoundby); + if ($thirdpartyfoundby) $descriptionmeta = dol_concatdesc($descriptionmeta, 'Third party found from '.$thirdpartyfoundby); } if ($contactstatic->id > 0) { - if ($contactfoundby) $descriptionmeta .= dol_concatdesc($descriptionmeta, 'Contact/address found from '.$contactfoundby); + if ($contactfoundby) $descriptionmeta = dol_concatdesc($descriptionmeta, 'Contact/address found from '.$contactfoundby); } $description = $descriptiontitle; @@ -1540,12 +1540,12 @@ class EmailCollector extends CommonObject if ($thirdpartystatic->id > 0) { $projecttocreate->socid = $thirdpartystatic->id; - if ($thirdpartyfoundby) $descriptionmeta .= dol_concatdesc($descriptionmeta, 'Third party found from '.$thirdpartyfoundby); + if ($thirdpartyfoundby) $descriptionmeta = dol_concatdesc($descriptionmeta, 'Third party found from '.$thirdpartyfoundby); } if ($contactstatic->id > 0) { $projecttocreate->contact_id = $contactstatic->id; - if ($contactfoundby) $descriptionmeta .= dol_concatdesc($descriptionmeta, 'Contact/address found from '.$contactfoundby); + if ($contactfoundby) $descriptionmeta = dol_concatdesc($descriptionmeta, 'Contact/address found from '.$contactfoundby); } $description = $descriptiontitle; @@ -1632,12 +1632,12 @@ class EmailCollector extends CommonObject if ($thirdpartystatic->id > 0) { $tickettocreate->socid = $thirdpartystatic->id; - if ($thirdpartyfoundby) $descriptionmeta .= dol_concatdesc($descriptionmeta, 'Third party found from '.$thirdpartyfoundby); + if ($thirdpartyfoundby) $descriptionmeta = dol_concatdesc($descriptionmeta, 'Third party found from '.$thirdpartyfoundby); } if ($contactstatic->id > 0) { $tickettocreate->contact_id = $contactstatic->id; - if ($contactfoundby) $descriptionmeta .= dol_concatdesc($descriptionmeta, 'Contact/address found from '.$contactfoundby); + if ($contactfoundby) $descriptionmeta = dol_concatdesc($descriptionmeta, 'Contact/address found from '.$contactfoundby); } $description = $descriptiontitle; From 1dd8d9fa8f0f68ac1457a7843f2431df8cef7487 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 25 Apr 2019 21:48:35 +0200 Subject: [PATCH 037/132] Fix phpcs --- htdocs/adherents/subscription.php | 4 ++-- .../class/emailcollector.class.php | 16 +++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/htdocs/adherents/subscription.php b/htdocs/adherents/subscription.php index cf85e7b2acf..b28a8b31f2c 100644 --- a/htdocs/adherents/subscription.php +++ b/htdocs/adherents/subscription.php @@ -714,7 +714,7 @@ if ($rowid > 0) $subscriptionstatic->ref=$objp->crowid; $subscriptionstatic->id=$objp->crowid; - if ($objp->cfk_type > 0) + if ($objp->cfk_type > 0) { $adht->fetch($objp->cfk_type); } @@ -723,7 +723,7 @@ if ($rowid > 0) print '
'; print '\n"; print ''; } From bd15bf295241e9612a8c2ab0ac16e90273c23509 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 27 Apr 2019 13:43:11 +0200 Subject: [PATCH 059/132] CSS --- htdocs/projet/tasks/list.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/projet/tasks/list.php b/htdocs/projet/tasks/list.php index 1279a5191fd..94ca4d436d5 100644 --- a/htdocs/projet/tasks/list.php +++ b/htdocs/projet/tasks/list.php @@ -523,7 +523,7 @@ if (! empty($arrayfields['t.label']['checked'])) // Start date if (! empty($arrayfields['t.dateo']['checked'])) { - print ''; From d8d462e36f2c5a64f0909ba58a8f407ec028edaa Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sat, 27 Apr 2019 14:53:14 +0200 Subject: [PATCH 060/132] FIX: dolibarrize civility for fetch member same code as contact or other object --- htdocs/adherents/class/adherent.class.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 201b6610817..5b446ceb047 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -1223,7 +1223,7 @@ class Adherent extends CommonObject { global $langs; - $sql = "SELECT d.rowid, d.ref_ext, d.civility as civility_id, d.gender, d.firstname, d.lastname, d.societe as company, d.fk_soc, d.statut, d.public, d.address, d.zip, d.town, d.note_private,"; + $sql = "SELECT d.rowid, d.ref_ext, d.civility as civility_code, d.gender, d.firstname, d.lastname, d.societe as company, d.fk_soc, d.statut, d.public, d.address, d.zip, d.town, d.note_private,"; $sql.= " d.note_public,"; $sql.= " d.email, d.skype, d.twitter, d.facebook, d.linkedin, d.phone, d.phone_perso, d.phone_mobile, d.login, d.pass, d.pass_crypted,"; $sql.= " d.photo, d.fk_adherent_type, d.morphy, d.entity,"; @@ -1267,7 +1267,11 @@ class Adherent extends CommonObject $this->ref = $obj->rowid; $this->id = $obj->rowid; $this->ref_ext = $obj->ref_ext; - $this->civility_id = $obj->civility_id; + + $this->civility_id = $obj->civility_code; + $this->civility_code = $obj->civility_code; + $this->civility = $obj->civility_code?($langs->trans("Civility".$obj->civility_code) != ("Civility".$obj->civility_code) ? $langs->trans("Civility".$obj->civility_code) : $obj->civility_code):''; + $this->firstname = $obj->firstname; $this->lastname = $obj->lastname; $this->gender = $obj->gender; From f33b7fc744b94084fbe0652ab3e5b22c0ae7a560 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sat, 27 Apr 2019 15:19:39 +0200 Subject: [PATCH 061/132] Update adherent.class.php --- htdocs/adherents/class/adherent.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 5b446ceb047..799e3518865 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -1268,7 +1268,7 @@ class Adherent extends CommonObject $this->id = $obj->rowid; $this->ref_ext = $obj->ref_ext; - $this->civility_id = $obj->civility_code; + $this->civility_id = $obj->civility_code; $this->civility_code = $obj->civility_code; $this->civility = $obj->civility_code?($langs->trans("Civility".$obj->civility_code) != ("Civility".$obj->civility_code) ? $langs->trans("Civility".$obj->civility_code) : $obj->civility_code):''; From 3c9046150266cc651757c8a679a26ac7304dc78d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 27 Apr 2019 17:31:14 +0200 Subject: [PATCH 062/132] Better error message in convert odt to pdf --- htdocs/includes/odtphp/odf.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/htdocs/includes/odtphp/odf.php b/htdocs/includes/odtphp/odf.php index 2c2d90e96d9..6b3a6400bc3 100644 --- a/htdocs/includes/odtphp/odf.php +++ b/htdocs/includes/odtphp/odf.php @@ -584,7 +584,7 @@ IMG; // using windows libreoffice that must be in path // using linux/mac libreoffice that must be in path // Note PHP Config "fastcgi.impersonate=0" must set to 0 - Default is 1 - $command ='soffice -headless -convert-to pdf -outdir '. escapeshellarg(dirname($name)). " ".escapeshellarg($name); + $command ='soffice --headless --convert-to pdf --outdir '. escapeshellarg(dirname($name)). " ".escapeshellarg($name); } elseif (preg_match('/unoconv/', $conf->global->MAIN_ODT_AS_PDF)) { @@ -635,6 +635,7 @@ IMG; //$command = DOL_DOCUMENT_ROOT.'/includes/odtphp/odt2pdf.sh '.$name.' '.$dirname; dol_syslog(get_class($this).'::exportAsAttachedPDF $execmethod='.$execmethod.' Run command='.$command,LOG_DEBUG); + $retval=0; $output_arr=array(); if ($execmethod == 1) { exec($command, $output_arr, $retval); @@ -665,6 +666,7 @@ IMG; if ($retval == 0) { dol_syslog(get_class($this).'::exportAsAttachedPDF $ret_val='.$retval, LOG_DEBUG); + $filename=''; $linenum=0; if (headers_sent($filename, $linenum)) { throw new OdfException("headers already sent ($filename at $linenum)"); } @@ -681,16 +683,17 @@ IMG; } } else { dol_syslog(get_class($this).'::exportAsAttachedPDF $ret_val='.$retval, LOG_DEBUG); - dol_syslog(get_class($this).'::exportAsAttachedPDF $output_arr='.var_export($output_arr,true), LOG_DEBUG); + dol_syslog(get_class($this).'::exportAsAttachedPDF $output_arr='.var_export($output_arr, true), LOG_DEBUG); if ($retval==126) { throw new OdfException('Permission execute convert script : ' . $command); } else { + $errorstring=''; foreach($output_arr as $line) { - $errors.= $line."
"; + $errorstring.= $line."
"; } - throw new OdfException('ODT to PDF convert fail : ' . $errors); + throw new OdfException('ODT to PDF convert fail (option MAIN_ODT_AS_PDF is '.$conf->global->MAIN_ODT_AS_PDF.', command was '.$command.', retval='.$retval.') : ' . $errorstring); } } } From 6b2b996935be31a4997a7b9eaa3df2d72bce5224 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 27 Apr 2019 19:41:47 +0200 Subject: [PATCH 063/132] Missing translation --- htdocs/website/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/website/index.php b/htdocs/website/index.php index 592c3cd4234..c3d1378b1c1 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -1875,7 +1875,7 @@ if (! GETPOST('hide_websitemenu')) } if (! empty($conf->global->WEBSITE_REPLACE_INFO_ABOUT_USAGE_WITH_WEBSERVER)) { - $htmltext.= '
'.$conf->global->WEBSITE_REPLACE_INFO_ABOUT_USAGE_WITH_WEBSERVER; + $htmltext.= '
'.$langs->trans($conf->global->WEBSITE_REPLACE_INFO_ABOUT_USAGE_WITH_WEBSERVER); } else { From 789a76320a05a150e7ffa3fc482080a10994a538 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 27 Apr 2019 19:43:48 +0200 Subject: [PATCH 064/132] Fix info message --- htdocs/website/index.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/website/index.php b/htdocs/website/index.php index c3d1378b1c1..b34ed3a31c1 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -1875,6 +1875,7 @@ if (! GETPOST('hide_websitemenu')) } if (! empty($conf->global->WEBSITE_REPLACE_INFO_ABOUT_USAGE_WITH_WEBSERVER)) { + $linktotestonwebserver.= '
'.$langs->trans($conf->global->WEBSITE_REPLACE_INFO_ABOUT_USAGE_WITH_WEBSERVER); $htmltext.= '
'.$langs->trans($conf->global->WEBSITE_REPLACE_INFO_ABOUT_USAGE_WITH_WEBSERVER); } else From 70975b36c7ed729158bc35853c0f4c1c7f1b65e6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 27 Apr 2019 19:46:53 +0200 Subject: [PATCH 065/132] Fix link --- htdocs/website/index.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/website/index.php b/htdocs/website/index.php index b34ed3a31c1..c3d1378b1c1 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -1875,7 +1875,6 @@ if (! GETPOST('hide_websitemenu')) } if (! empty($conf->global->WEBSITE_REPLACE_INFO_ABOUT_USAGE_WITH_WEBSERVER)) { - $linktotestonwebserver.= '
'.$langs->trans($conf->global->WEBSITE_REPLACE_INFO_ABOUT_USAGE_WITH_WEBSERVER); $htmltext.= '
'.$langs->trans($conf->global->WEBSITE_REPLACE_INFO_ABOUT_USAGE_WITH_WEBSERVER); } else From 5253c759af02633c137727d88120eeaa16bd1818 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 27 Apr 2019 21:42:52 +0200 Subject: [PATCH 066/132] Fix overwrite feature --- htdocs/core/class/translate.class.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/translate.class.php b/htdocs/core/class/translate.class.php index a8d22b61257..c48c1ed6bac 100644 --- a/htdocs/core/class/translate.class.php +++ b/htdocs/core/class/translate.class.php @@ -466,7 +466,9 @@ class Translate if (! $found && ! empty($conf->global->MAIN_ENABLE_OVERWRITE_TRANSLATION)) { // Overwrite translation with database read - $sql="SELECT transkey, transvalue FROM ".MAIN_DB_PREFIX."overwrite_trans where lang='".$db->escape($this->defaultlang)."'"; + $sql ="SELECT transkey, transvalue FROM ".MAIN_DB_PREFIX."overwrite_trans where lang='".$db->escape($this->defaultlang)."' OR lang IS NULL"; + $sql.=" AND entity IN (0, ".getEntity('overwrite_trans').")"; + $sql.=$db->order("lang", "DESC"); $resql=$db->query($sql); if ($resql) From 61f2b84f5f366800db8256dce4e97cc44ca86ba2 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Sun, 28 Apr 2019 00:49:21 +0200 Subject: [PATCH 067/132] FIX : error with call IsInEEC --- htdocs/product/list.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 39e98730365..0a5508ae725 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -35,6 +35,7 @@ require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; if (! empty($conf->categorie->enabled)) require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; From 2154b4a654d7ccad503e7ab685145a8fd39339f4 Mon Sep 17 00:00:00 2001 From: Sof Date: Sun, 28 Apr 2019 12:09:59 +0200 Subject: [PATCH 068/132] FIX : Typo $seearch_cti = $search_cti --- htdocs/contact/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/contact/list.php b/htdocs/contact/list.php index 246fd172dc7..febc613434d 100644 --- a/htdocs/contact/list.php +++ b/htdocs/contact/list.php @@ -400,7 +400,7 @@ $num = $db->num_rows($result); $arrayofselected=is_array($toselect)?$toselect:array(); -if ($num == 1 && ! empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && ($sall != '' || $seearch_cti != '')) +if ($num == 1 && ! empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && ($sall != '' || $search_cti != '')) { $obj = $db->fetch_object($resql); $id = $obj->rowid; From 00db27495633e8a590c27fa107d6bcebe6b2545a Mon Sep 17 00:00:00 2001 From: andreubisquerra Date: Sun, 28 Apr 2019 18:12:33 +0200 Subject: [PATCH 069/132] Add history to view and print previous sales. --- htdocs/compta/facture/list.php | 21 +++++++++++++++++++-- htdocs/langs/en_US/cashdesk.lang | 3 ++- htdocs/takepos/invoice.php | 9 ++++++++- htdocs/takepos/takepos.php | 7 +++++++ 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index d978ddb62e5..42baaab436d 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -67,6 +67,11 @@ $confirm=GETPOST('confirm', 'alpha'); $toselect = GETPOST('toselect', 'array'); $contextpage=GETPOST('contextpage', 'aZ')?GETPOST('contextpage', 'aZ'):'invoicelist'; +if ($contextpage == 'poslist') +{ + $_GET['optioncss'] = 'print'; +} + $lineid=GETPOST('lineid', 'int'); $userid=GETPOST('userid', 'int'); $search_product_category=GETPOST('search_product_category', 'int'); @@ -950,7 +955,12 @@ if ($resql) $totalpay = $facturestatic->total_ttc - $remaintopay; } - print '
'; + print ''; if (! empty($arrayfields['f.ref']['checked'])) { print ''; + // Fields for situation invoice if ($this->situation_cycle_ref) { print ''; + //print ''; } if ($usemargins && ! empty($conf->margin->enabled) && empty($user->societe_id)) diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index 10446760bef..93140c02ef0 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -131,8 +131,10 @@ if ($nolinesbefore) { ?> situation_cycle_ref) { print ''; + //print ''; } if (! empty($usemargins)) { diff --git a/htdocs/core/tpl/objectline_edit.tpl.php b/htdocs/core/tpl/objectline_edit.tpl.php index e373e5fbda2..f43357df781 100644 --- a/htdocs/core/tpl/objectline_edit.tpl.php +++ b/htdocs/core/tpl/objectline_edit.tpl.php @@ -60,12 +60,15 @@ if (!empty($conf->multicurrency->enabled) && $this->multicurrency_code != $conf- global->MAIN_VIEW_LINE_NUMBER)) { ?> - + '; if (!empty($conf->multicurrency->enabled) && $this->multicurrency_code != $conf->currency) { + $coldisplay++; print ''; } @@ -183,6 +188,7 @@ $coldisplay=-1; // We remove first td global->PRODUCT_USE_UNITS) { + $coldisplay++; print ''; @@ -205,12 +211,11 @@ $coldisplay=-1; // We remove first td } if (! empty($usemargins)) { - if (!empty($user->rights->margins->creer)) { -?> - - -rights->margins->creer) { if (! empty($conf->global->DISPLAY_MARGIN_RATES)) { @@ -246,7 +251,7 @@ $coldisplay=-1; // We remove first td ?> - @@ -263,9 +268,9 @@ if (!empty($extrafieldsline)) service->enabled) && $line->product_type == 1 && $dateSelector) { ?> global->MAIN_VIEW_LINE_NUMBER)) { ?> - + - situation_cycle_ref) { + // Fields for situation invoices + if ($this->situation_cycle_ref) + { $coldisplay++; print ''; + //print ''; } if ($usemargins && ! empty($conf->margin->enabled) && empty($user->societe_id)) diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index 38b05e30b9f..b8ffa08fbaf 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -2958,7 +2958,7 @@ table.nobottomiftotal tr.liste_total td { background-color: #fff; border-bottom: 0px !important; } -table.nobottom { +table.nobottom, td.nobottom { border-bottom: 0px !important; } div.liste_titre .tagtd { From 61bf731d17367bd44b6d936c3ea2596f9dea9c53 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 30 Apr 2019 18:11:35 +0200 Subject: [PATCH 100/132] FIX Balance of td --- htdocs/core/class/commonobject.class.php | 2 +- htdocs/core/lib/pdf.lib.php | 5 +- htdocs/core/lib/price.lib.php | 24 ++--- htdocs/core/tpl/objectline_create.tpl.php | 101 ++++++++-------------- htdocs/core/tpl/objectline_edit.tpl.php | 6 +- htdocs/core/tpl/objectline_view.tpl.php | 9 +- htdocs/langs/en_US/main.lang | 1 + 7 files changed, 66 insertions(+), 82 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 8b20479a154..454936d2998 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -3966,7 +3966,7 @@ abstract class CommonObject // Fields for situation invoice if ($this->situation_cycle_ref) { print ''; - //print ''; + print ''; } if ($usemargins && ! empty($conf->margin->enabled) && empty($user->societe_id)) diff --git a/htdocs/core/lib/pdf.lib.php b/htdocs/core/lib/pdf.lib.php index 134cf7c8e5e..cc40fcb9272 100644 --- a/htdocs/core/lib/pdf.lib.php +++ b/htdocs/core/lib/pdf.lib.php @@ -1954,6 +1954,7 @@ function pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails = 0) $total_ht = ($conf->multicurrency->enabled && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht); if ($object->lines[$i]->situation_percent > 0) { + // TODO Remove this. The total should be saved correctly in database instead of being modified here. $prev_progress = 0; $progress = 1; if (method_exists($object->lines[$i], 'get_prev_progress')) @@ -1964,7 +1965,9 @@ function pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails = 0) $result.=price($sign * ($total_ht/($object->lines[$i]->situation_percent/100)) * $progress, 0, $outputlangs); } else - $result.=price($sign * $total_ht, 0, $outputlangs); + { + $result.=price($sign * $total_ht, 0, $outputlangs); + } } } return $result; diff --git a/htdocs/core/lib/price.lib.php b/htdocs/core/lib/price.lib.php index 9d3aa99f306..a649d9d225e 100644 --- a/htdocs/core/lib/price.lib.php +++ b/htdocs/core/lib/price.lib.php @@ -39,7 +39,7 @@ * @param int $qty Quantity * @param float $pu Unit price (HT or TTC selon price_base_type) * @param float $remise_percent_ligne Discount for line - * @param float $txtva 0=do not apply standard tax, Vat rate=apply + * @param float $txtva 0=do not apply VAT tax, VAT rate=apply (this is VAT rate only without text code, we don't need text code because we alreaydy have all tax info into $localtaxes_array) * @param float $uselocaltax1_rate 0=do not use this localtax, >0=apply and get value from localtaxes_array (or database if empty), -1=autodetect according to seller if we must apply, get value from localtaxes_array (or database if empty). Try to always use -1. * @param float $uselocaltax2_rate 0=do not use this localtax, >0=apply and get value from localtaxes_array (or database if empty), -1=autodetect according to seller if we must apply, get value from localtaxes_array (or database if empty). Try to always use -1. * @param float $remise_percent_global 0 @@ -82,7 +82,7 @@ * 25=multicurrency_total_tax1 for total_ht * 26=multicurrency_total_tax2 for total_ht */ -function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocaltax1_rate, $uselocaltax2_rate, $remise_percent_global, $price_base_type, $info_bits, $type, $seller = '', $localtaxes_array = '', $progress = 100, $multicurrency_tx = 1, $pu_devise = 0) +function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocaltax1_rate, $uselocaltax2_rate, $remise_percent_global, $price_base_type, $info_bits, $type, $seller = '', $localtaxes_array='', $progress=100, $multicurrency_tx=1, $pu_devise=0) { global $conf,$mysoc,$db; @@ -131,13 +131,14 @@ function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocalt $localtax2_type = $localtaxes_array[2]; $localtax2_rate = $localtaxes_array[3]; } - else // deprecated method. values and type for localtaxes must be provided by caller and loaded with getLocalTaxesFromRate + else // deprecated method. values and type for localtaxes must be provided by caller and loaded with getLocalTaxesFromRate using the full vat rate (including text code) { - $sql = "SELECT taux, localtax1, localtax2, localtax1_type, localtax2_type"; + dol_syslog("Price.lib::calcul_price_total search vat information using old deprecated method", LOG_WARNING); + + $sql = "SELECT taux, localtax1, localtax2, localtax1_type, localtax2_type"; $sql.= " FROM ".MAIN_DB_PREFIX."c_tva as cv"; $sql.= " WHERE cv.taux = ".$txtva; $sql.= " AND cv.fk_pays = ".$countryid; - dol_syslog("Price.lib::calcul_price_total search vat information using old deprecated method", LOG_WARNING); $resql = $db->query($sql); if ($resql) { @@ -187,9 +188,9 @@ function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocalt //If input unit price is 'HT', we need to have the totals with main VAT for a correct calculation if ($price_base_type != 'TTC') { - $tot_sans_remise_wt = price2num($tot_sans_remise * (1 + ($txtva / 100)), 'MU'); - $tot_avec_remise_wt = price2num($tot_avec_remise * (1 + ($txtva / 100)), 'MU'); - $pu_wt = price2num($pu * (1 + ($txtva / 100)), 'MU'); + $tot_sans_remise_wt = price2num($tot_sans_remise * (1 + ($txtva / 100)),'MU'); + $tot_avec_remise_wt = price2num($tot_avec_remise * (1 + ($txtva / 100)),'MU'); + $pu_wt = price2num($pu * (1 + ($txtva / 100)),'MU'); } else { @@ -291,9 +292,9 @@ function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocalt //If input unit price is 'TTC', we need to have the totals without main VAT for a correct calculation if ($price_base_type == 'TTC') { - $tot_sans_remise= price2num($tot_sans_remise / (1 + ($txtva / 100)), 'MU'); - $tot_avec_remise= price2num($tot_avec_remise / (1 + ($txtva / 100)), 'MU'); - $pu = price2num($pu / (1 + ($txtva / 100)), 'MU'); + $tot_sans_remise= price2num($tot_sans_remise / (1 + ($txtva / 100)),'MU'); + $tot_avec_remise= price2num($tot_avec_remise / (1 + ($txtva / 100)),'MU'); + $pu = price2num($pu / (1 + ($txtva / 100)),'MU'); } $apply_tax = false; @@ -410,3 +411,4 @@ function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocalt return $result; } + diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index 93140c02ef0..04911584809 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -134,7 +134,7 @@ if ($nolinesbefore) { // Fields for situation invoice if ($this->situation_cycle_ref) { print ''; - //print ''; + print ''; } if (! empty($usemargins)) { @@ -163,18 +163,18 @@ if ($nolinesbefore) { ?> global->MAIN_VIEW_LINE_NUMBER)) { - $coldisplay=2; + $coldisplay++; ?> + } + $coldisplay++; + ?> - - multicurrency->enabled) && $this->multicurrency_code != $conf->currency) { ?> + multicurrency->enabled) && $this->multicurrency_code != $conf->currency) { + $coldisplay++; + ?> - + - + global->PRODUCT_USE_UNITS) { + $coldisplay++; print ''; } $remise_percent = $buyer->remise_percent; - if($object->element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier') { + if($object->element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier') + { $remise_percent = $seller->remise_supplier_percent; } + + $coldisplay++; ?> situation_cycle_ref) { $coldisplay++; print ''; + $coldisplay++; + print ''; } + if (! empty($usemargins)) { if (!empty($user->rights->margins->creer)) { + $coldisplay++; ?> rights->margins->creer) @@ -427,12 +445,9 @@ else { $coldisplay++; } } - else - { - if (! empty($conf->global->DISPLAY_MARGIN_RATES)) $coldisplay++; - if (! empty($conf->global->DISPLAY_MARK_RATES)) $coldisplay++; - } } + + $coldisplay+=$colspan; ?> > global->MAIN_VIEW_LINE_NUMBER)) { print ''; } ?> - '; + print ''; + $coldisplay++; + print ''; } if (! empty($usemargins)) { @@ -270,7 +272,7 @@ if (!empty($extrafieldsline)) global->MAIN_VIEW_LINE_NUMBER)) { ?> - global->MAIN_MAX_DECIMALS_UNIT, $conf->global->MAIN_MAX_DECIMALS_TOT); + // Fields for situation invoices if ($this->situation_cycle_ref) { + include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php'; $coldisplay++; print ''; - //print ''; + $coldisplay++; + $locataxes_array = getLocalTaxesFromRate($line->tva.($line->vat_src_code ? ' ('.$line->vat_src_code.')' : ''), 0, ($senderissupplier?$mysoc:$object->thirdparty), ($senderissupplier?$object->thirdparty:$mysoc)); + $tmp = calcul_price_total($line->qty, $line->pu, $line->remise_percent, $line->txtva, -1, -1, 0, 'HT', $line->info_bits, $line->type, ($senderissupplier?$object->thirdparty:$mysoc), $locataxes_array, 100, $object->multicurrency_tx, $line->multicurrency_subprice); + print ''; } if ($usemargins && ! empty($conf->margin->enabled) && empty($user->societe_id)) { - $rounding = min($conf->global->MAIN_MAX_DECIMALS_UNIT, $conf->global->MAIN_MAX_DECIMALS_TOT); ?> rights->margins->creer)) { ?> diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index c739f8d5624..3aec931714b 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -371,6 +371,7 @@ Percentage=Percentage Total=Total SubTotal=Subtotal TotalHTShort=Total (excl.) +TotalHT100Short=Total 100%% (excl.) TotalHTShortCurrency=Total (excl. in currency) TotalTTCShort=Total (inc. tax) TotalHT=Total (excl. tax) From ac304f58b078475f6c3c3c04eb9ec41face9bb65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Tue, 30 Apr 2019 20:37:59 +0200 Subject: [PATCH 101/132] clean new commits --- htdocs/core/lib/price.lib.php | 57 ++++++++--------- htdocs/core/modules/modProduct.class.php | 35 +++++----- htdocs/core/modules/modService.class.php | 78 +++++++++++------------ htdocs/core/tpl/objectline_create.tpl.php | 21 ++---- 4 files changed, 93 insertions(+), 98 deletions(-) diff --git a/htdocs/core/lib/price.lib.php b/htdocs/core/lib/price.lib.php index a649d9d225e..04c9b806c9c 100644 --- a/htdocs/core/lib/price.lib.php +++ b/htdocs/core/lib/price.lib.php @@ -82,7 +82,7 @@ * 25=multicurrency_total_tax1 for total_ht * 26=multicurrency_total_tax2 for total_ht */ -function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocaltax1_rate, $uselocaltax2_rate, $remise_percent_global, $price_base_type, $info_bits, $type, $seller = '', $localtaxes_array='', $progress=100, $multicurrency_tx=1, $pu_devise=0) +function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocaltax1_rate, $uselocaltax2_rate, $remise_percent_global, $price_base_type, $info_bits, $type, $seller = '', $localtaxes_array = '', $progress = 100, $multicurrency_tx = 1, $pu_devise = 0) { global $conf,$mysoc,$db; @@ -188,9 +188,9 @@ function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocalt //If input unit price is 'HT', we need to have the totals with main VAT for a correct calculation if ($price_base_type != 'TTC') { - $tot_sans_remise_wt = price2num($tot_sans_remise * (1 + ($txtva / 100)),'MU'); - $tot_avec_remise_wt = price2num($tot_avec_remise * (1 + ($txtva / 100)),'MU'); - $pu_wt = price2num($pu * (1 + ($txtva / 100)),'MU'); + $tot_sans_remise_wt = price2num($tot_sans_remise * (1 + ($txtva / 100)), 'MU'); + $tot_avec_remise_wt = price2num($tot_avec_remise * (1 + ($txtva / 100)), 'MU'); + $pu_wt = price2num($pu * (1 + ($txtva / 100)), 'MU'); } else { @@ -203,7 +203,7 @@ function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocalt $localtaxes = array(0,0,0); $apply_tax = false; - switch($localtax1_type) { + switch($localtax1_type) { case '2': // localtax on product or service $apply_tax = true; break; @@ -227,16 +227,16 @@ function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocalt } $apply_tax = false; - switch($localtax2_type) { - case '2': // localtax on product or service - $apply_tax = true; - break; - case '4': // localtax on product - if ($type == 0) $apply_tax = true; - break; - case '6': // localtax on service - if ($type == 1) $apply_tax = true; - break; + switch($localtax2_type) { + case '2': // localtax on product or service + $apply_tax = true; + break; + case '4': // localtax on product + if ($type == 0) $apply_tax = true; + break; + case '6': // localtax on service + if ($type == 1) $apply_tax = true; + break; } if ($uselocaltax2_rate && $apply_tax) { $result[15] = price2num(($tot_sans_remise_wt * (1 + ( $localtax2_rate / 100))) - $tot_sans_remise_wt, 'MT'); @@ -292,9 +292,9 @@ function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocalt //If input unit price is 'TTC', we need to have the totals without main VAT for a correct calculation if ($price_base_type == 'TTC') { - $tot_sans_remise= price2num($tot_sans_remise / (1 + ($txtva / 100)),'MU'); - $tot_avec_remise= price2num($tot_avec_remise / (1 + ($txtva / 100)),'MU'); - $pu = price2num($pu / (1 + ($txtva / 100)),'MU'); + $tot_sans_remise= price2num($tot_sans_remise / (1 + ($txtva / 100)), 'MU'); + $tot_avec_remise= price2num($tot_avec_remise / (1 + ($txtva / 100)), 'MU'); + $pu = price2num($pu / (1 + ($txtva / 100)), 'MU'); } $apply_tax = false; @@ -321,16 +321,16 @@ function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocalt } $apply_tax = false; - switch($localtax2_type) { - case '1': // localtax on product or service - $apply_tax = true; - break; - case '3': // localtax on product - if ($type == 0) $apply_tax = true; - break; - case '5': // localtax on service - if ($type == 1) $apply_tax = true; - break; + switch($localtax2_type) { + case '1': // localtax on product or service + $apply_tax = true; + break; + case '3': // localtax on product + if ($type == 0) $apply_tax = true; + break; + case '5': // localtax on service + if ($type == 1) $apply_tax = true; + break; } if ($uselocaltax2_rate && $apply_tax) { $result[15] = price2num(($tot_sans_remise * (1 + ( $localtax2_rate / 100))) - $tot_sans_remise, 'MT'); // amount tax2 for total_ht_without_discount @@ -411,4 +411,3 @@ function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocalt return $result; } - diff --git a/htdocs/core/modules/modProduct.class.php b/htdocs/core/modules/modProduct.class.php index 3358728d095..5ee2a6ba8a3 100644 --- a/htdocs/core/modules/modProduct.class.php +++ b/htdocs/core/modules/modProduct.class.php @@ -201,10 +201,10 @@ class modProduct extends DolibarrModules if (! empty($conf->fournisseur->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('s.nom'=>'product_supplier_ref','pf.ref_fourn'=>'product_supplier_ref','pf.unitprice'=>'product_supplier_ref','pf.quantity'=>'product_supplier_ref','pf.remise_percent'=>'product_supplier_ref','pf.delivery_time_days'=>'product_supplier_ref')); if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('l.lang'=>'translation', 'l.label'=>'translation','l.description'=>'translation','l.note'=>'translation')); if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_dependencies_array[$r]=array('category'=>'p.rowid'); - if (! empty($conf->stock->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.stock'=>'product','p.pmp'=>'product')); - if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.barcode'=>'product')); - if (! empty($conf->fournisseur->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('s.nom'=>'product_supplier_ref','pf.ref_fourn'=>'product_supplier_ref','pf.unitprice'=>'product_supplier_ref','pf.quantity'=>'product_supplier_ref','pf.remise_percent'=>'product_supplier_ref','pf.delivery_time_days'=>'product_supplier_ref')); - if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('l.lang'=>'translation', 'l.label'=>'translation','l.description'=>'translation','l.note'=>'translation')); + if (! empty($conf->stock->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('p.stock'=>'product','p.pmp'=>'product')); + if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('p.barcode'=>'product')); + if (! empty($conf->fournisseur->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('s.nom'=>'product_supplier_ref','pf.ref_fourn'=>'product_supplier_ref','pf.unitprice'=>'product_supplier_ref','pf.quantity'=>'product_supplier_ref','pf.remise_percent'=>'product_supplier_ref','pf.delivery_time_days'=>'product_supplier_ref')); + if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('l.lang'=>'translation', 'l.label'=>'translation','l.description'=>'translation','l.note'=>'translation')); if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_dependencies_array[$r]=array('category'=>'p.rowid'); $this->export_sql_start[$r]='SELECT DISTINCT '; $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'product as p'; @@ -349,7 +349,7 @@ class modProduct extends DolibarrModules 'p.note_public' => "PublicNote",//public note 'p.note' => "PrivateNote",//private note 'p.customcode' => 'CustomCode', - 'p.price' => "SellingPriceHT",//without tax + 'p.price' => "SellingPriceHT",//without 'p.price_min' => "MinPrice", 'p.price_ttc' => "SellingPriceTTC",//with tax 'p.price_min_ttc' => "SellingMinPriceTTC", @@ -518,19 +518,22 @@ class modProduct extends DolibarrModules if (is_object($mysoc) && $mysoc->useLocalTax(1)) $import_sample=array_merge($import_sample, array('p.localtax1_tx'=>'', 'p.localtax1_type'=>'')); if (is_object($mysoc) && $mysoc->useLocalTax(2)) $import_sample=array_merge($import_sample, array('p.localtax2_tx'=>'', 'p.localtax2_type'=>'')); if (! empty($conf->barcode->enabled)) $import_sample=array_merge($import_sample, array('p.barcode'=>'')); - if (! empty($conf->global->PRODUCT_USE_UNITS)) { - $import_sample = array_merge($import_sample, array( - 'p.fk_unit' => 'use a unit of measure from the dictionary. G/KG/M2/M3 etc....matches field "code" in table "' . MAIN_DB_PREFIX . 'c_units"' - )); + if (! empty($conf->global->PRODUCT_USE_UNITS)) { + $import_sample = array_merge( + $import_sample, + array( + 'p.fk_unit' => 'use a unit of measure from the dictionary. G/KG/M2/M3 etc....matches field "code" in table "' . MAIN_DB_PREFIX . 'c_units"' + ) + ); $this->import_convertvalue_array[$r] = array_merge($this->import_convertvalue_array[$r], array( - 'p.fk_unit' => array( - 'rule' => 'fetchidfromcodeorlabel', - 'classfile' => '/core/class/cunits.class.php', - 'class' => 'CUnits', - 'method' => 'fetch', - 'dict' => 'DictionaryUnits' - ) + 'p.fk_unit' => array( + 'rule' => 'fetchidfromcodeorlabel', + 'classfile' => '/core/class/cunits.class.php', + 'class' => 'CUnits', + 'method' => 'fetch', + 'dict' => 'DictionaryUnits' + ) )); } $this->import_examplevalues_array[$r]=array_merge($import_sample, $import_extrafield_sample); diff --git a/htdocs/core/modules/modService.class.php b/htdocs/core/modules/modService.class.php index 119339d6022..022e0c74a54 100644 --- a/htdocs/core/modules/modService.class.php +++ b/htdocs/core/modules/modService.class.php @@ -143,32 +143,32 @@ class modService extends DolibarrModules $this->export_permission[$r]=array(array("service","export")); $this->export_fields_array[$r]=array('p.rowid'=>"Id",'p.ref'=>"Ref",'p.label'=>"Label",'p.description'=>"Description",'p.url'=>"PublicUrl",'p.accountancy_code_sell'=>"ProductAccountancySellCode",'p.accountancy_code_buy'=>"ProductAccountancyBuyCode",'p.note'=>"Note",'p.price_base_type'=>"PriceBase",'p.price'=>"UnitPriceHT",'p.price_ttc'=>"UnitPriceTTC",'p.tva_tx'=>'VATRate','p.tosell'=>"OnSell",'p.tobuy'=>"OnBuy",'p.duration'=>"Duration",'p.datec'=>'DateCreation','p.tms'=>'DateModification'); if (is_object($mysoc) && $mysoc->useNPR()) $this->export_fields_array[$r]['p.recuperableonly']='NPR'; - if (! empty($conf->stock->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('p.stock'=>'Stock','p.seuil_stock_alerte'=>'StockLimit','p.desiredstock'=>'DesiredStock','p.pmp'=>'PMPValue')); - if (! empty($conf->barcode->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('p.barcode'=>'BarCode')); - if (! empty($conf->fournisseur->enabled) || !empty($conf->margin->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('p.cost_price'=>'CostPrice')); + if (! empty($conf->stock->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p.stock'=>'Stock','p.seuil_stock_alerte'=>'StockLimit','p.desiredstock'=>'DesiredStock','p.pmp'=>'PMPValue')); + if (! empty($conf->barcode->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p.barcode'=>'BarCode')); + if (! empty($conf->fournisseur->enabled) || !empty($conf->margin->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p.cost_price'=>'CostPrice')); $keyforselect='product'; $keyforelement='product'; $keyforaliasextra='extra'; include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; - if (! empty($conf->fournisseur->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('s.nom'=>'Supplier','pf.ref_fourn'=>'SupplierRef','pf.quantity'=>'QtyMin','pf.remise_percent'=>'DiscountQtyMin','pf.unitprice'=>'BuyingPrice','pf.delivery_time_days'=>'NbDaysToDelivery')); - if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('group_concat(cat.label)'=>'Categories')); - if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('l.lang'=>'Language', 'l.label'=>'TranslatedLabel','l.description'=>'TranslatedDescription','l.note'=>'TranslatedNote')); + if (! empty($conf->fournisseur->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('s.nom'=>'Supplier','pf.ref_fourn'=>'SupplierRef','pf.quantity'=>'QtyMin','pf.remise_percent'=>'DiscountQtyMin','pf.unitprice'=>'BuyingPrice','pf.delivery_time_days'=>'NbDaysToDelivery')); + if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('group_concat(cat.label)'=>'Categories')); + if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('l.lang'=>'Language', 'l.label'=>'TranslatedLabel','l.description'=>'TranslatedDescription','l.note'=>'TranslatedNote')); if (! empty($conf->global->PRODUCT_USE_UNITS)) $this->export_fields_array[$r]['p.fk_unit'] = 'Unit'; $this->export_TypeFields_array[$r]=array('p.ref'=>"Text",'p.label'=>"Text",'p.description'=>"Text",'p.url'=>"Text",'p.accountancy_code_sell'=>"Text",'p.accountancy_code_buy'=>"Text",'p.note'=>"Text",'p.price_base_type'=>"Text",'p.price'=>"Numeric",'p.price_ttc'=>"Numeric",'p.tva_tx'=>'Numeric','p.tosell'=>"Boolean",'p.tobuy'=>"Boolean",'p.duration'=>"Duree",'p.datec'=>'Date','p.tms'=>'Date'); - if (! empty($conf->stock->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r],array('p.stock'=>'Numeric')); - if (! empty($conf->barcode->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r],array('p.barcode'=>'Text')); - if (! empty($conf->fournisseur->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r],array('s.nom'=>'Text','pf.ref_fourn'=>'Text','pf.unitprice'=>'Numeric','pf.quantity'=>'Numeric','pf.remise_percent'=>'Numeric','pf.delivery_time_days'=>'Numeric')); - if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r],array('l.lang'=>'Text', 'l.label'=>'Text','l.description'=>'Text','l.note'=>'Text')); - if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r],array("group_concat(cat.label)"=>'Text')); + if (! empty($conf->stock->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('p.stock'=>'Numeric')); + if (! empty($conf->barcode->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('p.barcode'=>'Text')); + if (! empty($conf->fournisseur->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('s.nom'=>'Text','pf.ref_fourn'=>'Text','pf.unitprice'=>'Numeric','pf.quantity'=>'Numeric','pf.remise_percent'=>'Numeric','pf.delivery_time_days'=>'Numeric')); + if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('l.lang'=>'Text', 'l.label'=>'Text','l.description'=>'Text','l.note'=>'Text')); + if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array("group_concat(cat.label)"=>'Text')); $this->export_entities_array[$r]=array(); // We define here only fields that use another icon that the one defined into import_icon - if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array("group_concat(cat.label)"=>'category')); - if (! empty($conf->stock->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.stock'=>'product','p.pmp'=>'product')); - if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.barcode'=>'product')); - if (! empty($conf->fournisseur->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('s.nom'=>'product_supplier_ref','pf.ref_fourn'=>'product_supplier_ref','pf.unitprice'=>'product_supplier_ref','pf.quantity'=>'product_supplier_ref','pf.remise_percent'=>'product_supplier_ref','pf.delivery_time_days'=>'product_supplier_ref')); - if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('l.lang'=>'translation', 'l.label'=>'translation','l.description'=>'translation','l.note'=>'translation')); - if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_dependencies_array[$r]=array('category'=>'p.rowid'); - if (! empty($conf->stock->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.stock'=>'product','p.pmp'=>'product')); - if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.barcode'=>'product')); - if (! empty($conf->fournisseur->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('s.nom'=>'product_supplier_ref','pf.ref_fourn'=>'product_supplier_ref','pf.unitprice'=>'product_supplier_ref','pf.quantity'=>'product_supplier_ref','pf.remise_percent'=>'product_supplier_ref','pf.delivery_time_days'=>'product_supplier_ref')); - if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('l.lang'=>'translation', 'l.label'=>'translation','l.description'=>'translation','l.note'=>'translation')); + if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array("group_concat(cat.label)"=>'category')); + if (! empty($conf->stock->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('p.stock'=>'product','p.pmp'=>'product')); + if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('p.barcode'=>'product')); + if (! empty($conf->fournisseur->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('s.nom'=>'product_supplier_ref','pf.ref_fourn'=>'product_supplier_ref','pf.unitprice'=>'product_supplier_ref','pf.quantity'=>'product_supplier_ref','pf.remise_percent'=>'product_supplier_ref','pf.delivery_time_days'=>'product_supplier_ref')); + if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('l.lang'=>'translation', 'l.label'=>'translation','l.description'=>'translation','l.note'=>'translation')); + if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_dependencies_array[$r]= array('category'=>'p.rowid'); + if (! empty($conf->stock->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('p.stock'=>'product','p.pmp'=>'product')); + if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('p.barcode'=>'product')); + if (! empty($conf->fournisseur->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('s.nom'=>'product_supplier_ref','pf.ref_fourn'=>'product_supplier_ref','pf.unitprice'=>'product_supplier_ref','pf.quantity'=>'product_supplier_ref','pf.remise_percent'=>'product_supplier_ref','pf.delivery_time_days'=>'product_supplier_ref')); + if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('l.lang'=>'translation', 'l.label'=>'translation','l.description'=>'translation','l.note'=>'translation')); if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_dependencies_array[$r]=array('category'=>'p.rowid'); $this->export_sql_start[$r]='SELECT DISTINCT '; $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'product as p'; @@ -260,18 +260,18 @@ class modService extends DolibarrModules 'p.price_base_type'=>"PriceBase",'p.price'=>"UnitPriceHT",'p.price_ttc'=>"UnitPriceTTC",'p.tva_tx'=>'VATRate','p.tosell'=>"OnSell", 'p.tobuy'=>"OnBuy",'p.datec'=>'DateCreation','p.tms'=>'DateModification' ); - if (! empty($conf->stock->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('p.stock'=>'Stock','p.seuil_stock_alerte'=>'StockLimit','p.desiredstock'=>'DesiredStock','p.pmp'=>'PMPValue')); - if (! empty($conf->barcode->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('p.barcode'=>'BarCode')); - $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('pa.qty'=>'Qty','pa.incdec'=>'ComposedProductIncDecStock')); + if (! empty($conf->stock->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p.stock'=>'Stock','p.seuil_stock_alerte'=>'StockLimit','p.desiredstock'=>'DesiredStock','p.pmp'=>'PMPValue')); + if (! empty($conf->barcode->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p.barcode'=>'BarCode')); + $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('pa.qty'=>'Qty','pa.incdec'=>'ComposedProductIncDecStock')); $this->export_TypeFields_array[$r]=array( 'p.ref'=>"Text",'p.label'=>"Text",'p.description'=>"Text",'p.url'=>"Text",'p.accountancy_code_sell'=>"Text",'p.accountancy_code_buy'=>"Text", 'p.note'=>"Text",'p.length'=>"Numeric",'p.surface'=>"Numeric",'p.volume'=>"Numeric",'p.weight'=>"Numeric",'p.customcode'=>'Text', 'p.price_base_type'=>"Text",'p.price'=>"Numeric",'p.price_ttc'=>"Numeric",'p.tva_tx'=>'Numeric','p.tosell'=>"Boolean",'p.tobuy'=>"Boolean", 'p.datec'=>'Date','p.tms'=>'Date' ); - if (! empty($conf->stock->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r],array('p.stock'=>'Numeric','p.seuil_stock_alerte'=>'Numeric','p.desiredstock'=>'Numeric','p.pmp'=>'Numeric','p.cost_price'=>'Numeric')); - if (! empty($conf->barcode->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r],array('p.barcode'=>'Text')); - $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r],array('pa.qty'=>'Numeric')); + if (! empty($conf->stock->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('p.stock'=>'Numeric','p.seuil_stock_alerte'=>'Numeric','p.desiredstock'=>'Numeric','p.pmp'=>'Numeric','p.cost_price'=>'Numeric')); + if (! empty($conf->barcode->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('p.barcode'=>'Text')); + $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('pa.qty'=>'Numeric')); $this->export_entities_array[$r]=array( 'p.rowid'=>"virtualproduct",'p.ref'=>"virtualproduct",'p.label'=>"virtualproduct",'p.description'=>"virtualproduct",'p.url'=>"virtualproduct", 'p.accountancy_code_sell'=>'virtualproduct','p.accountancy_code_buy'=>'virtualproduct','p.note'=>"virtualproduct",'p.length'=>"virtualproduct", @@ -279,13 +279,13 @@ class modService extends DolibarrModules 'p.price_base_type'=>"virtualproduct",'p.price'=>"virtualproduct",'p.price_ttc'=>"virtualproduct",'p.tva_tx'=>"virtualproduct", 'p.tosell'=>"virtualproduct",'p.tobuy'=>"virtualproduct",'p.datec'=>"virtualproduct",'p.tms'=>"virtualproduct" ); - if (! empty($conf->stock->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.stock'=>'virtualproduct','p.seuil_stock_alerte'=>'virtualproduct','p.desiredstock'=>'virtualproduct','p.pmp'=>'virtualproduct')); - if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.barcode'=>'virtualproduct')); - $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('pa.qty'=>"subproduct",'pa.incdec'=>'subproduct')); + if (! empty($conf->stock->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('p.stock'=>'virtualproduct','p.seuil_stock_alerte'=>'virtualproduct','p.desiredstock'=>'virtualproduct','p.pmp'=>'virtualproduct')); + if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('p.barcode'=>'virtualproduct')); + $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('pa.qty'=>"subproduct",'pa.incdec'=>'subproduct')); $keyforselect='product'; $keyforelement='product'; $keyforaliasextra='extra'; include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; - $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('p2.rowid'=>"Id",'p2.ref'=>"Ref",'p2.label'=>"Label",'p2.description'=>"Description")); - $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p2.rowid'=>"subproduct",'p2.ref'=>"subproduct",'p2.label'=>"subproduct",'p2.description'=>"subproduct")); + $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p2.rowid'=>"Id",'p2.ref'=>"Ref",'p2.label'=>"Label",'p2.description'=>"Description")); + $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('p2.rowid'=>"subproduct",'p2.ref'=>"subproduct",'p2.label'=>"subproduct",'p2.description'=>"subproduct")); $this->export_sql_start[$r]='SELECT DISTINCT '; $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'product as p'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product_extrafields as extra ON p.rowid = extra.fk_object,'; @@ -363,11 +363,11 @@ class modService extends DolibarrModules 'p.tva_tx'=>'VATRate','p.tosell'=>"OnSell*",'p.tobuy'=>"OnBuy*",'p.fk_product_type'=>"Type*",'p.finished'=>'Nature','p.datec'=>'DateCreation' ); //if (! empty($conf->stock->enabled)) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r],array('p.seuil_stock_alerte'=>'StockLimit','p.desiredstock'=>'DesiredStock','p.pmp'=>'PMPValue')); - if (! empty($conf->fournisseur->enabled) || !empty($conf->margin->enabled)) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r],array('p.cost_price'=>'CostPrice')); - if (is_object($mysoc) && $mysoc->useNPR()) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r],array('p.recuperableonly'=>'NPR')); - if (is_object($mysoc) && $mysoc->useLocalTax(1)) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r],array('p.localtax1_tx'=>'LT1', 'p.localtax1_type'=>'LT1Type')); - if (is_object($mysoc) && $mysoc->useLocalTax(2)) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r],array('p.localtax2_tx'=>'LT2', 'p.localtax2_type'=>'LT2Type')); - if (! empty($conf->barcode->enabled)) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r],array('p.barcode'=>'BarCode')); + if (! empty($conf->fournisseur->enabled) || !empty($conf->margin->enabled)) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r], array('p.cost_price'=>'CostPrice')); + if (is_object($mysoc) && $mysoc->useNPR()) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r], array('p.recuperableonly'=>'NPR')); + if (is_object($mysoc) && $mysoc->useLocalTax(1)) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r], array('p.localtax1_tx'=>'LT1', 'p.localtax1_type'=>'LT1Type')); + if (is_object($mysoc) && $mysoc->useLocalTax(2)) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r], array('p.localtax2_tx'=>'LT2', 'p.localtax2_type'=>'LT2Type')); + if (! empty($conf->barcode->enabled)) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r], array('p.barcode'=>'BarCode')); if (! empty($conf->global->PRODUCT_USE_UNITS)) $this->import_fields_array[$r]['p.fk_unit'] = 'Unit'; // Add extra fields $import_extrafield_sample=array(); @@ -394,7 +394,7 @@ class modService extends DolibarrModules 'p.recuperableonly'=>'^[0|1]$' ); $import_sample=array('p.ref'=>"SERVICE_REF or id:123456",'p.label'=>"My product",'p.description'=>"This is a description example for record",'p.note'=>"Some note",'p.price'=>"100",'p.price_ttc'=>"110",'p.tva_tx'=>'10','p.tosell'=>"0 or 1",'p.tobuy'=>"0 or 1",'p.fk_product_type'=>"0 for product/1 for service",'p.finished'=>'','p.duration'=>"1y",'p.datec'=>'2008-12-31','p.recuperableonly'=>'0 or 1'); - $this->import_examplevalues_array[$r]=array_merge($import_sample,$import_extrafield_sample); + $this->import_examplevalues_array[$r]=array_merge($import_sample, $import_extrafield_sample); $this->import_updatekeys_array[$r] = array('p.ref'=>'Ref'); if (! empty($conf->barcode->enabled)) $this->import_updatekeys_array[$r]=array_merge($this->import_updatekeys_array[$r], array('p.barcode'=>'BarCode'));//only show/allow barcode as update key if Barcode module enabled @@ -470,7 +470,7 @@ class modService extends DolibarrModules 'pr.price_min'=>"MinPriceLevelUnitPriceHT",'pr.price_min_ttc'=>"MinPriceLevelUnitPriceTTC", 'pr.date_price'=>'DateCreation*'); if (! empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) $this->import_fields_array[$r]['pr.tva_tx']='VATRate'; - if (is_object($mysoc) && $mysoc->useNPR()) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r],array('pr.recuperableonly'=>'NPR')); + if (is_object($mysoc) && $mysoc->useNPR()) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r], array('pr.recuperableonly'=>'NPR')); $this->import_regex_array[$r]=array('pr.datec'=>'^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$','pr.recuperableonly'=>'^[0|1]$'); $this->import_convertvalue_array[$r]=array( 'pr.fk_product'=>array('rule'=>'fetchidfromref','classfile'=>'/product/class/product.class.php','class'=>'Product','method'=>'fetch','element'=>'Product') diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index 04911584809..df8301f4104 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -136,7 +136,8 @@ if ($nolinesbefore) { print ''; print ''; } - if (! empty($usemargins)) + if (! empty($usemargins)) + { if (!empty($user->rights->margins->creer)) { ?> @@ -149,9 +150,7 @@ if ($nolinesbefore) { echo $langs->trans('BuyingPrice'); else echo $langs->trans('CostPrice'); - ?> - - '; if ($user->rights->margins->creer && ! empty($conf->global->DISPLAY_MARGIN_RATES)) echo ''; if ($user->rights->margins->creer && ! empty($conf->global->DISPLAY_MARK_RATES)) echo ''; } @@ -168,10 +167,8 @@ $coldisplay=0; // Adds a line numbering column if (! empty($conf->global->MAIN_VIEW_LINE_NUMBER)) { $coldisplay++; - ?> - - '; +} $coldisplay++; ?> @@ -348,14 +345,12 @@ if (! empty($conf->global->MAIN_VIEW_LINE_NUMBER)) { echo $form->selectyesno('date_end_fill', $line->date_end_fill, 1); echo ''; } - ?> - + echo ''; - element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier') // We must have same test in printObjectLines { - ?> $coldisplay++; + ?> @@ -458,9 +453,7 @@ if (! empty($conf->global->MAIN_VIEW_LINE_NUMBER)) { if (is_object($objectline)) { print $objectline->showOptionals($extrafieldsline, 'edit', array('style'=>$bcnd[$var], 'colspan'=>$coldisplay), '', '', empty($conf->global->MAIN_EXTRAFIELDS_IN_ONE_TD)?0:1); } -?> -service->enabled) || ($object->element == 'contrat')) && $dateSelector && GETPOST('type') != '0') // We show date field if required { ?> From 3bda9be775659683fcafd4df0ea95b4a09748ec1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 1 May 2019 13:46:45 +0200 Subject: [PATCH 102/132] Fix error 500 --- htdocs/admin/dolistore/class/dolistore.class.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/htdocs/admin/dolistore/class/dolistore.class.php b/htdocs/admin/dolistore/class/dolistore.class.php index 553ce2e54e0..e82eec71fec 100644 --- a/htdocs/admin/dolistore/class/dolistore.class.php +++ b/htdocs/admin/dolistore/class/dolistore.class.php @@ -17,7 +17,10 @@ */ include_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; -include_once DOL_DOCUMENT_ROOT.'/admin/dolistore/class/PSWebServiceLibrary.class.php'; +if (! class_exists('PrestaShopWebservice')) // We keep this because some modules add this lib too into a different path. This is to avoid "Cannot declare class PrestaShopWebservice" errors. +{ + include_once DOL_DOCUMENT_ROOT.'/admin/dolistore/class/PSWebServiceLibrary.class.php'; +} /** From 50b1a54dca17aa67a705eeac0cf18f2403ce74c7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 1 May 2019 14:06:30 +0200 Subject: [PATCH 103/132] FIX Update/delete currency on same languages --- htdocs/admin/multicurrency.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/htdocs/admin/multicurrency.php b/htdocs/admin/multicurrency.php index 467ffffeb41..4e06f7a5edf 100644 --- a/htdocs/admin/multicurrency.php +++ b/htdocs/admin/multicurrency.php @@ -108,9 +108,7 @@ elseif ($action == 'update_currency') { $error = 0; - $submit = GETPOST('submit', 'alpha'); - - if ($submit == $langs->trans('Modify')) + if (GETPOST('updatecurrency', 'alpha')) { $fk_multicurrency = GETPOST('fk_multicurrency', 'int'); $rate = price2num(GETPOST('rate', 'alpha')); @@ -129,7 +127,7 @@ elseif ($action == 'update_currency') } } } - elseif ($submit == $langs->trans('Delete')) + elseif (GETPOST('deletecurrency', 'alpha')) { $fk_multicurrency = GETPOST('fk_multicurrency', 'int'); $currency = new MultiCurrency($db); @@ -357,8 +355,8 @@ foreach ($TCurrency as &$currency) print ''; print '1 '.$conf->currency.' = '; print ' '.$currency->code.' '; - print ' '; - print ''; + print ' '; + print ''; print ''; print ''; From a75c6a81d16312580e2847002e606dc822631686 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 1 May 2019 17:15:42 +0200 Subject: [PATCH 104/132] FIX Follow rule to create a new page --- htdocs/core/class/html.formticket.class.php | 11 +- htdocs/core/lib/functions.lib.php | 2 +- htdocs/ticket/card.php | 24 ++- htdocs/ticket/class/ticket.class.php | 155 +------------------- 4 files changed, 22 insertions(+), 170 deletions(-) diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index 59996942cd3..f6cf1c33e9f 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -834,7 +834,7 @@ class FormTicket if ($user->rights->ticket->write && !$user->socid) { print ''; @@ -863,18 +863,19 @@ class FormTicket print ""; } + // Private message or not. TODO What does this means ? + /* if (! $user->socid) { print ''; - } + }*/ - - print ''; + print ''; $label_title = empty($conf->global->MAIN_APPLICATION_TITLE) ? $mysoc->name : $conf->global->MAIN_APPLICATION_TITLE; print ''; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 4c0b15c8d46..12b38068c87 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -307,7 +307,7 @@ function GETPOST($paramname, $check = 'none', $method = 0, $filter = null, $opti } if (! empty($conf->global->MAIN_ENABLE_DEFAULT_VALUES)) { - if (! empty($_GET['action']) && $_GET['action'] == 'create' && ! isset($_GET[$paramname]) && ! isset($_POST[$paramname])) + if (! empty($_GET['action']) && preg_match('/^create/', $_GET['action']) && ! isset($_GET[$paramname]) && ! isset($_POST[$paramname])) { // Now search in setup to overwrite default values if (! empty($user->default_values)) // $user->default_values defined from menu 'Setup - Default values' diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index 44abe008d34..299607c9cde 100644 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -75,7 +75,7 @@ if (empty($action) && empty($id) && empty($ref)) $action='view'; //Select mail models is same action as add_message if (GETPOST('modelselected', 'alpha')) { - $action = 'add_message'; + $action = 'create_message'; } // Load object @@ -369,9 +369,9 @@ if ($action == "assign_user" && GETPOST('btn_assign_user', 'aplha') && $user->ri $action = 'view'; } -if ($action == "new_message" && GETPOST('btn_add_message') && $user->rights->ticket->read) { - $ret = $object->newMessage($user, $action); - if ($ret) { +if ($action == "add_message" && GETPOST('btn_create_message') && $user->rights->ticket->read) { + $ret = $object->newMessage($user, $action, (GETPOST('private_message', 'alpha') == "on" ? 1 : 0)); + if ($ret > 0) { if (!empty($backtopage)) { $url = $backtopage; } else { @@ -382,14 +382,10 @@ if ($action == "new_message" && GETPOST('btn_add_message') && $user->rights->tic exit; } else { setEventMessages($object->error, null, 'errors'); - $action = 'add_message'; + $action = 'create_message'; } } -if ($action == "new_public_message" && GETPOST('btn_add_message')) { - $object->newMessagePublic($user, $action); -} - if ($action == "confirm_close" && GETPOST('confirm', 'alpha') == 'yes' && $user->rights->ticket->write) { $object->fetch(GETPOST('id', 'int'), '', GETPOST('track_id', 'alpha')); @@ -641,7 +637,7 @@ if ($action == 'create' || $action == 'presend') $formticket->showForm(1); } -if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'dellink' || $action == 'add_message' || $action == 'close' || $action == 'delete' || $action == 'editcustomer' || $action == 'progression' || $action == 'reopen' +if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'dellink' || $action == 'create_message' || $action == 'close' || $action == 'delete' || $action == 'editcustomer' || $action == 'progression' || $action == 'reopen' || $action == 'editsubject' || $action == 'edit_extras' || $action == 'update_extras' || $action == 'edit_extrafields' || $action == 'set_extrafields' || $action == 'classify' || $action == 'sel_contract' || $action == 'edit_message_init' || $action == 'set_status' || $action == 'dellink') { if ($res > 0) @@ -1173,8 +1169,8 @@ if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'd if (empty($reshook)) { // Show link to add a message (if read and not closed) - if ($object->fk_statut < Ticket::STATUS_CLOSED && $action != "add_message") { - print ''; + if ($object->fk_statut < Ticket::STATUS_CLOSED && $action != "create_message") { + print ''; } // Link to create an intervention @@ -1210,7 +1206,7 @@ if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'd $action = 'presend'; } - if ($action != 'add_message') + if ($action != 'create_message') { print '
'; print ''; // ancre @@ -1232,7 +1228,7 @@ if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'd } else { - $action='new_message'; + $action='add_message'; $modelmail='ticket_send'; print '
'; diff --git a/htdocs/ticket/class/ticket.class.php b/htdocs/ticket/class/ticket.class.php index cab2eab92ed..15dd77cf64f 100644 --- a/htdocs/ticket/class/ticket.class.php +++ b/htdocs/ticket/class/ticket.class.php @@ -2486,11 +2486,12 @@ class Ticket extends CommonObject /** * Add new message on a ticket (private area) * - * @param User $user User for action - * @param string $action Action string - * @return int + * @param User $user User for action + * @param string $action Action string + * @param int $private 1=Message is private. TODO Implement this. What does this means ? + * @return int */ - public function newMessage($user, &$action) + public function newMessage($user, &$action, $private = 1) { global $mysoc, $conf, $langs; @@ -2777,152 +2778,6 @@ class Ticket extends CommonObject setEventMessages($langs->trans('ErrorMailRecipientIsEmptyForSendTicketMessage'), null, 'warnings'); } } - - /** - * Add new message on a ticket (public area) - * - * @param User $user User for action - * @param string $action Action string - * @return void - */ - public function newMessagePublic($user, &$action) - { - global $mysoc, $conf, $langs; - - $object = new Ticket($this->db); - - $error = 0; - $ret = $object->fetch('', '', GETPOST('track_id', 'alpha')); - $object->socid = $object->fk_soc; - $object->fetch_thirdparty(); - if ($ret < 0) { - $error++; - array_push($this->errors, $langs->trans("ErrorTicketIsNotValid")); - $action = ''; - } - - if (!GETPOST("message")) { - $error++; - array_push($this->errors, $langs->trans("ErrorFieldRequired", $langs->transnoentities("message"))); - $action = 'add_message'; - } - - if (!$error) { - $object->message = (string) GETPOST("message"); - $id = $object->createTicketMessage($user); - if ($id <= 0) { - $error++; - $this->error = $object->error; - $this->errors = $object->errors; - $action = 'add_message'; - } - - if (!$error && $id > 0) { - setEventMessages($langs->trans('TicketMessageSuccessfullyAdded'), null, 'mesgs'); - - // Retrieve internal contact datas - $internal_contacts = $object->getInfosTicketInternalContact(); - $sendto = array(); - if (is_array($internal_contacts) && count($internal_contacts) > 0) { - $subject = '[' . $mysoc->name . '- ticket #' . $object->track_id . '] ' . $langs->trans('TicketNewMessage'); - - $message = $langs->trans('TicketMessageMailIntroAutoNewPublicMessage', $object->subject); - $message .= "\n"; - $message .= GETPOST('message'); - $message .= "\n"; - - // Coordonnées client - if ($object->thirdparty->id > 0) { - $message .= "\n\n"; - $message .= "==============================================\n"; - $message .= $langs->trans('Thirparty') . " : " . $object->thirdparty->name; - $message .= !empty($object->thirdparty->town) ? $langs->trans('Town') . " : " . $object->thirdparty->town : ''; - $message .= "\n"; - $message .= !empty($object->thirdparty->phone) ? $langs->trans('Phone') . " : " . $object->thirdparty->phone : ''; - $message .= "\n"; - } - - // Build array to display recipient list - foreach ($internal_contacts as $key => $info_sendto) { - if ($info_sendto['email'] != '') { - $sendto[] = trim($info_sendto['firstname'] . " " . $info_sendto['lastname']) . " <" . $info_sendto['email'] . ">"; - } - - // Contact type - $recipient = dolGetFirstLastname($info_sendto['firstname'], $info_sendto['lastname'], '-1') . ' (' . strtolower($info_sendto['libelle']) . ')'; - $message .= (!empty($recipient) ? $langs->trans('TicketNotificationRecipient') . ' : ' . $recipient . "\n" : ''); - $message .= "\n"; - } - - // URL ticket - $url_internal_ticket = dol_buildpath('/ticket/card.php', 2) . '?track_id=' . $object->track_id; - $message .= "\n" . $langs->trans('TicketNotificationEmailBodyInfosTrackUrlinternal') . ' : ' . $url_internal_ticket . "\n"; - - $message .= "\n\n"; - - $message_signature = GETPOST('mail_signature') ? GETPOST('mail_signature') : $conf->global->TICKET_MESSAGE_MAIL_SIGNATURE; - - // Add global email address reciepient - if ($conf->global->TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS && !in_array($conf->global->TICKET_NOTIFICATION_EMAIL_FROM, $sendto)) { - $sendto[] = $conf->global->TICKET_NOTIFICATION_EMAIL_FROM; - } - - $this->sendTicketMessageByEmail($subject, $message, '', $sendto); - } - - /* - * Email for externals users if not private - */ - - // Retrieve email of all contacts external - $external_contacts = $object->getInfosTicketExternalContact(); - $sendto = array(); - if (is_array($external_contacts) && count($external_contacts) > 0) { - $subject = '[' . $mysoc->name . '- ticket #' . $object->track_id . '] ' . $langs->trans('TicketNewMessage'); - - $message = $langs->trans('TicketMessageMailIntroAutoNewPublicMessage', $object->subject); - $message .= "\n"; - - $message .= GETPOST('message'); - $message .= "\n\n"; - - $message_signature = GETPOST('mail_signature') ? GETPOST('mail_signature') : $conf->global->TICKET_MESSAGE_MAIL_SIGNATURE; - foreach ($external_contacts as $key => $info_sendto) { - if ($info_sendto['email'] != '') { - $sendto[] = trim($info_sendto['firstname'] . " " . $info_sendto['lastname']) . " <" . $info_sendto['email'] . ">"; - } - $recipient = ''; - $recipient = dolGetFirstLastname($info_sendto['firstname'], $info_sendto['lastname'], '-1') . ' (' . strtolower($info_sendto['libelle']) . ')'; - $message .= (!empty($recipient) ? $langs->trans('TicketNotificationRecipient') . ' : ' . $recipient . "\n" : ''); - } - - $url_public_ticket = ($conf->global->TICKET_URL_PUBLIC_INTERFACE ? $conf->global->TICKET_URL_PUBLIC_INTERFACE . '/view.php' : dol_buildpath('/public/ticket/view.php', 2)) . '?track_id=' . $object->track_id; - $message .= "\n\n" . $langs->trans('TicketNewEmailBodyInfosTrackUrlCustomer') . ' : ' . $url_public_ticket . "\n"; - - // Add signature - $message .= '\n\n' . $message_signature; - - if (!empty($object->origin_email) && !in_array($object->origin_email, $sendto)) { - $sendto[] = $object->origin_email; - } - if ($object->fk_soc > 0 && !in_array($object->origin_email, $sendto)) { - $sendto[] = $object->thirdparty->email; - } - $this->sendTicketMessageByEmail($subject, $message, '', $sendto); - } - - $object->copyFilesForTicket(); - - $url = 'view.php?action=view_ticket&track_id=' . $object->track_id; - header("Location: " . $url); - exit; - } else { - setEventMessages($object->error, $object->errors, 'errors'); - } - } else { - setEventMessages($this->error, $this->errors, 'errors'); - } - } } From 9955af5194f2a90828a64cd638426d7db6e48935 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 1 May 2019 17:53:41 +0200 Subject: [PATCH 105/132] Debug ticket module --- htdocs/admin/defaultvalues.php | 1 + htdocs/core/class/html.formticket.class.php | 16 +----- htdocs/langs/en_US/admin.lang | 1 + htdocs/ticket/card.php | 64 ++++++++++++--------- htdocs/ticket/class/ticket.class.php | 20 ++----- 5 files changed, 45 insertions(+), 57 deletions(-) diff --git a/htdocs/admin/defaultvalues.php b/htdocs/admin/defaultvalues.php index 8e4334c6214..1f0ada4a6f3 100644 --- a/htdocs/admin/defaultvalues.php +++ b/htdocs/admin/defaultvalues.php @@ -251,6 +251,7 @@ print '
'; $texthelp=$langs->trans("PageUrlForDefaultValues"); if ($mode == 'createform') $texthelp.=$langs->trans("PageUrlForDefaultValuesCreate", 'societe/card.php', 'societe/card.php?abc=val1&def=val2'); else $texthelp.=$langs->trans("PageUrlForDefaultValuesList", 'societe/list.php', 'societe/list.php?abc=val1&def=val2'); +$texthelp.='

'.$langs->trans("AlsoDefaultValuesAreEffectiveForActionCreate"); $texturl=$form->textwithpicto($langs->trans("Url"), $texthelp); print_liste_field_titre($texturl, $_SERVER["PHP_SELF"], 'page,param', '', $param, '', $sortfield, $sortorder); // Field diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index f6cf1c33e9f..1d681d2672b 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -852,19 +852,7 @@ class FormTicket print ''; } - // Substitution array - if ($this->withsubstit) { - print '"; - } - - // Private message or not. TODO What does this means ? - /* + // Private message (not visible by customer/external user) if (! $user->socid) { print ''; - }*/ + } print ''; $label_title = empty($conf->global->MAIN_APPLICATION_TITLE) ? $mysoc->name : $conf->global->MAIN_APPLICATION_TITLE; diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 90abbe90fc6..daba22fe660 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -470,6 +470,7 @@ TheKeyIsTheNameOfHtmlField=This is the name of the HTML field. Technical knowled PageUrlForDefaultValues=You must enter the relative path of the page URL. If you include parameters in URL, the default values will be effective if all parameters are set to same value. PageUrlForDefaultValuesCreate=
Example:
For the form to create a new third party, it is %s.
For URL of external modules installed into custom directory, do not include the "custom/", so use path like mymodule/mypage.php and not custom/mymodule/mypage.php.
If you want default value only if url has some parameter, you can use %s PageUrlForDefaultValuesList=
Example:
For the page that lists third parties, it is %s.
For URL of external modules installed into custom directory, do not include the "custom/" so use a path like mymodule/mypagelist.php and not custom/mymodule/mypagelist.php.
If you want default value only if url has some parameter, you can use %s +AlsoDefaultValuesAreEffectiveForActionCreate=Also note that overwritting default values for form creation works only for pages that were correctly designed (so with parameter action=create...) EnableDefaultValues=Enable customization of default values EnableOverwriteTranslation=Enable usage of overwritten translation GoIntoTranslationMenuToChangeThis=A translation has been found for the key with this code. To change this value, you must edit it from Home-Setup-translation. diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index 299607c9cde..dab1b896a67 100644 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -369,8 +369,9 @@ if ($action == "assign_user" && GETPOST('btn_assign_user', 'aplha') && $user->ri $action = 'view'; } -if ($action == "add_message" && GETPOST('btn_create_message') && $user->rights->ticket->read) { +if ($action == "add_message" && GETPOST('btn_add_message') && $user->rights->ticket->read) { $ret = $object->newMessage($user, $action, (GETPOST('private_message', 'alpha') == "on" ? 1 : 0)); + if ($ret > 0) { if (!empty($backtopage)) { $url = $backtopage; @@ -1228,11 +1229,43 @@ if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'd } else { - $action='add_message'; + $action='add_message'; // action to use to post the message $modelmail='ticket_send'; + // Substitution array + $morehtmlright=''; + $help=""; + $substitutionarray=array(); + if ($object->fk_soc > 0) { + $object->fetch_thirdparty(); + $substitutionarray['__THIRDPARTY_NAME__'] = $object->thirdparty->name; + } + $substitutionarray['__SIGNATURE__'] = $user->signature; + $substitutionarray['__TICKETSUP_TRACKID__'] = $object->track_id; + $substitutionarray['__TICKETSUP_REF__'] = $object->ref; + $substitutionarray['__TICKETSUP_SUBJECT__'] = $object->subject; + $substitutionarray['__TICKETSUP_TYPE__'] = $object->type_code; + $substitutionarray['__TICKETSUP_SEVERITY__'] = $object->severity_code; + $substitutionarray['__TICKETSUP_CATEGORY__'] = $object->category_code; // For backward compatibility + $substitutionarray['__TICKETSUP_ANALYTIC_CODE__'] = $object->category_code; + $substitutionarray['__TICKETSUP_MESSAGE__'] = $object->message; + $substitutionarray['__TICKETSUP_PROGRESSION__'] = $object->progress; + if ($object->fk_user_assign > 0) { + $userstat->fetch($object->fk_user_assign); + $substitutionarray['__TICKETSUP_USER_ASSIGN__'] = dolGetFirstLastname($userstat->firstname, $userstat->lastname); + } + + if ($object->fk_user_create > 0) { + $userstat->fetch($object->fk_user_create); + $substitutionarray['__TICKETSUP_USER_CREATE__'] = dolGetFirstLastname($userstat->firstname, $userstat->lastname); + } + foreach ($substitutionarray as $key => $val) { + $help.=$key.' -> '.$langs->trans($val).'
'; + } + $morehtmlright.=$form->textwithpicto($langs->trans("TicketMessageSubstitutionReplacedByGenericValues"), $help); + print '
'; - print load_fiche_titre($langs->trans('TicketAddMessage'), '', 'messages@ticket'); + print load_fiche_titre($langs->trans('TicketAddMessage'), $morehtmlright, 'messages@ticket'); print '
'; @@ -1265,30 +1298,7 @@ if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'd $formticket->withsubstit = 1; - - if ($object->fk_soc > 0) { - $object->fetch_thirdparty(); - $formticket->substit['__THIRDPARTY_NAME__'] = $object->thirdparty->name; - } - $formticket->substit['__SIGNATURE__'] = $user->signature; - $formticket->substit['__TICKETSUP_TRACKID__'] = $object->track_id; - $formticket->substit['__TICKETSUP_REF__'] = $object->ref; - $formticket->substit['__TICKETSUP_SUBJECT__'] = $object->subject; - $formticket->substit['__TICKETSUP_TYPE__'] = $object->type_code; - $formticket->substit['__TICKETSUP_SEVERITY__'] = $object->severity_code; - $formticket->substit['__TICKETSUP_CATEGORY__'] = $object->category_code; // For backward compatibility - $formticket->substit['__TICKETSUP_ANALYTIC_CODE__'] = $object->category_code; - $formticket->substit['__TICKETSUP_MESSAGE__'] = $object->message; - $formticket->substit['__TICKETSUP_PROGRESSION__'] = $object->progress; - if ($object->fk_user_assign > 0) { - $userstat->fetch($object->fk_user_assign); - $formticket->substit['__TICKETSUP_USER_ASSIGN__'] = dolGetFirstLastname($userstat->firstname, $userstat->lastname); - } - - if ($object->fk_user_create > 0) { - $userstat->fetch($object->fk_user_create); - $formticket->substit['__TICKETSUP_USER_CREATE__'] = dolGetFirstLastname($userstat->firstname, $userstat->lastname); - } + $formticket->substit = $substitutionarray; $formticket->showMessageForm('100%'); print '
'; diff --git a/htdocs/ticket/class/ticket.class.php b/htdocs/ticket/class/ticket.class.php index 15dd77cf64f..b68628d0c9b 100644 --- a/htdocs/ticket/class/ticket.class.php +++ b/htdocs/ticket/class/ticket.class.php @@ -1654,21 +1654,9 @@ class Ticket extends CommonObject $this->message = trim($this->message); } - // Insert request - $sql = "INSERT INTO " . MAIN_DB_PREFIX . "ticket_msg("; + // Insert entry into agenda with code 'TICKET_MSG' + $sql.='...'; - $sql .= "fk_track_id,"; - $sql .= "fk_user_action,"; - $sql .= "datec,"; - $sql .= "message,"; - $sql .= "private"; - $sql .= ") VALUES ("; - $sql .= " " . (!isset($this->fk_track_id) ? "'" . $this->db->escape($this->track_id) . "'" : "'" . $this->db->escape($this->fk_track_id) . "'") . ","; - $sql .= " " . ($this->fk_user_action > 0 ? $this->fk_user_action : $user->id) . ","; - $sql .= " '" . $this->db->idate(dol_now()) . "',"; - $sql .= " " . (!isset($this->message) ? 'NULL' : "'" . $this->db->escape($this->message) . "'") . ","; - $sql .= " " . (empty($this->private) ? '0' : "'" . $this->db->escape($this->private) . "'") . ""; - $sql .= ")"; $this->db->begin(); @@ -2520,8 +2508,8 @@ class Ticket extends CommonObject } if (!$error) { - $object->message = GETPOST("message"); - $object->private = GETPOST("private_message"); + $object->message = GETPOST("message", "none"); + $object->private = GETPOST("private_message", "alpha"); $send_email = GETPOST('send_email', 'int'); $id = $object->createTicketMessage($user); From 90a1181dc52575c553045f24cdc111dadc4404eb Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 1 May 2019 20:41:03 +0200 Subject: [PATCH 106/132] Debug module Ticket --- htdocs/comm/action/class/actioncomm.class.php | 1 + htdocs/core/lib/functions.lib.php | 1 + htdocs/langs/en_US/ticket.lang | 3 +- htdocs/ticket/agenda.php | 157 ++++++++-------- htdocs/ticket/card.php | 10 +- htdocs/ticket/class/actions_ticket.class.php | 3 +- htdocs/ticket/class/ticket.class.php | 173 ++++++++---------- htdocs/ticket/img/statut0.png | Bin 329 -> 234 bytes htdocs/ticket/img/statut1.png | Bin 470 -> 380 bytes .../ticket/img/{statut4.png => statut2.png} | Bin htdocs/ticket/img/statut3.png | Bin 380 -> 363 bytes htdocs/ticket/img/statut5.png | Bin 363 -> 329 bytes htdocs/ticket/img/statut6.png | Bin 341 -> 470 bytes htdocs/ticket/img/statut8.png | Bin 272 -> 341 bytes htdocs/ticket/img/statut9.png | Bin 0 -> 272 bytes 15 files changed, 160 insertions(+), 188 deletions(-) rename htdocs/ticket/img/{statut4.png => statut2.png} (100%) create mode 100644 htdocs/ticket/img/statut9.png diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index b543d6790c6..ebe4e48f264 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -281,6 +281,7 @@ class ActionComm extends CommonObject if (! empty($this->datep) && ! empty($this->datef) && $this->datep > $this->datef) $this->datef=$this->datep; //if (! empty($this->date) && ! empty($this->dateend) && $this->date > $this->dateend) $this->dateend=$this->date; if (! isset($this->fk_project) || $this->fk_project < 0) $this->fk_project = 0; + // For backward compatibility if ($this->elementtype=='facture') $this->elementtype='invoice'; if ($this->elementtype=='commande') $this->elementtype='order'; if ($this->elementtype=='contrat') $this->elementtype='contract'; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 12b38068c87..3f5480ee455 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -1299,6 +1299,7 @@ function dol_banner_tab($object, $paramid, $morehtml = '', $shownav = 1, $fieldi if ($object->element == 'member') $modulepart='memberphoto'; if ($object->element == 'user') $modulepart='userphoto'; if ($object->element == 'product') $modulepart='product'; + if ($object->element == 'ticket') $modulepart='ticket'; if (class_exists("Imagick")) { diff --git a/htdocs/langs/en_US/ticket.lang b/htdocs/langs/en_US/ticket.lang index 8265df1b370..c84dc17f087 100644 --- a/htdocs/langs/en_US/ticket.lang +++ b/htdocs/langs/en_US/ticket.lang @@ -58,9 +58,10 @@ Notify_TICKET_SENTBYMAIL=Send ticket message by email # Status NotRead=Not read Read=Read -Answered=Answered Assigned=Assigned InProgress=In progress +NeedMoreInformation=Waiting more information +Answered=Answered Waiting=Waiting Closed=Closed Deleted=Deleted diff --git a/htdocs/ticket/agenda.php b/htdocs/ticket/agenda.php index eb863adbfbc..bad8e58497b 100644 --- a/htdocs/ticket/agenda.php +++ b/htdocs/ticket/agenda.php @@ -125,103 +125,102 @@ if (! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/ticketnameonly/', $c $help_url = 'FR:DocumentationModuleTicket'; llxHeader('', $title, $help_url); - if ($socid > 0) { - $object->fetch_thirdparty(); - $head = societe_prepare_head($object->thirdparty); +if ($socid > 0) { + $object->fetch_thirdparty(); + $head = societe_prepare_head($object->thirdparty); - dol_fiche_head($head, 'ticket', $langs->trans("ThirdParty"), 0, 'company'); + dol_fiche_head($head, 'ticket', $langs->trans("ThirdParty"), 0, 'company'); - dol_banner_tab($object->thirdparty, 'socid', '', ($user->societe_id ? 0 : 1), 'rowid', 'nom'); + dol_banner_tab($object->thirdparty, 'socid', '', ($user->societe_id ? 0 : 1), 'rowid', 'nom'); - dol_fiche_end(); - } + dol_fiche_end(); +} - if (!$user->societe_id && $conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY) { - $object->next_prev_filter = "te.fk_user_assign = '" . $user->id . "'"; - } elseif ($user->societe_id > 0) { - $object->next_prev_filter = "te.fk_soc = '" . $user->societe_id . "'"; - } - $head = ticket_prepare_head($object); +if (!$user->societe_id && $conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY) { + $object->next_prev_filter = "te.fk_user_assign = '" . $user->id . "'"; +} elseif ($user->societe_id > 0) { + $object->next_prev_filter = "te.fk_soc = '" . $user->societe_id . "'"; +} +$head = ticket_prepare_head($object); - dol_fiche_head($head, 'tabTicketLogs', $langs->trans("Ticket"), 0, 'ticket'); +dol_fiche_head($head, 'tabTicketLogs', $langs->trans("Ticket"), 0, 'ticket'); - $morehtmlref ='
'; - $morehtmlref.= $object->subject; - // Author - if ($object->fk_user_create > 0) { - $morehtmlref .= '
' . $langs->trans("CreatedBy") . ' '; +$morehtmlref ='
'; +$morehtmlref.= $object->subject; +// Author +if ($object->fk_user_create > 0) { + $morehtmlref .= '
' . $langs->trans("CreatedBy") . ' : '; - $langs->load("users"); - $fuser = new User($db); - $fuser->fetch($object->fk_user_create); - $morehtmlref .= $fuser->getNomUrl(0); - } - if (!empty($object->origin_email)) { - $morehtmlref .= '
' . $langs->trans("CreatedBy") . ' : '; - $morehtmlref .= $object->origin_email . ' (' . $langs->trans("TicketEmailOriginIssuer") . ')'; - } + $langs->load("users"); + $fuser = new User($db); + $fuser->fetch($object->fk_user_create); + $morehtmlref .= $fuser->getNomUrl(0); +} +if (!empty($object->origin_email)) { + $morehtmlref .= '
' . $langs->trans("CreatedBy") . ' : '; + $morehtmlref .= $object->origin_email . ' (' . $langs->trans("TicketEmailOriginIssuer") . ')'; +} - // Thirdparty - if (! empty($conf->societe->enabled)) - { - $morehtmlref.='
'.$langs->trans('ThirdParty'); - /*if ($action != 'editcustomer' && $object->fk_statut < 8 && !$user->societe_id && $user->rights->ticket->write) { - $morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('Edit'), 1) . ''; - }*/ - $morehtmlref.=' : '; - if ($action == 'editcustomer') { - $morehtmlref.=$form->form_thirdparty($url_page_current . '?track_id=' . $object->track_id, $object->socid, 'editcustomer', '', 1, 0, 0, array(), 1); - } else { - $morehtmlref.=$form->form_thirdparty($url_page_current . '?track_id=' . $object->track_id, $object->socid, 'none', '', 1, 0, 0, array(), 1); - } - } +// Thirdparty +if (! empty($conf->societe->enabled)) +{ + $morehtmlref.='
'.$langs->trans('ThirdParty'); + /*if ($action != 'editcustomer' && $object->fk_statut < 8 && !$user->societe_id && $user->rights->ticket->write) { + $morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('Edit'), 1) . ''; + }*/ + $morehtmlref.=' : '; + if ($action == 'editcustomer') { + $morehtmlref.=$form->form_thirdparty($url_page_current . '?track_id=' . $object->track_id, $object->socid, 'editcustomer', '', 1, 0, 0, array(), 1); + } else { + $morehtmlref.=$form->form_thirdparty($url_page_current . '?track_id=' . $object->track_id, $object->socid, 'none', '', 1, 0, 0, array(), 1); + } +} - // Project - if (! empty($conf->projet->enabled)) - { - $langs->load("projects"); - $morehtmlref.='
'.$langs->trans('Project'); - if ($user->rights->ticket->write) - { - if ($action != 'classify') - //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ''; - $morehtmlref.=' : '; - if ($action == 'classify') { - //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); - $morehtmlref.='
'; - $morehtmlref.=''; - $morehtmlref.=''; - $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', 0, 0, 1, 0, 1, 0, 0, '', 1); - $morehtmlref.=''; - $morehtmlref.=''; - } else { - $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); - } - } else { - if (! empty($object->fk_project)) { - $proj = new Project($db); - $proj->fetch($object->fk_project); - $morehtmlref.=$proj->getNomUrl(1); - } else { - $morehtmlref.=''; - } - } - } +// Project +if (! empty($conf->projet->enabled)) +{ + $langs->load("projects"); + $morehtmlref.='
'.$langs->trans('Project'); + if ($user->rights->ticket->write) + { + if ($action != 'classify') + //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ''; + $morehtmlref.=' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref.='
'; + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', 0, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=''; + $morehtmlref.=''; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref.=$proj->getNomUrl(1); + } else { + $morehtmlref.=''; + } + } +} - $morehtmlref.='
'; +$morehtmlref.='
'; - $linkback = '' . $langs->trans("BackToList") . ' '; +$linkback = '' . $langs->trans("BackToList") . ' '; - dol_banner_tab($object, 'ref', $linkback, ($user->societe_id ? 0 : 1), 'ref', 'ref', $morehtmlref, '', 0, '', '', 1); +dol_banner_tab($object, 'ref', $linkback, ($user->societe_id ? 0 : 1), 'ref', 'ref', $morehtmlref, '', 0, '', '', 1); - dol_fiche_end(); +dol_fiche_end(); - print '
'; +print '
'; if (!empty($object->id)) { - print '
'; $param='&id='.$object->id; if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.$contextpage; if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.$limit; diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index dab1b896a67..26fec804370 100644 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -818,7 +818,7 @@ if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'd $morehtmlref.=''; - $linkback = '' . $langs->trans("BackToList") . ' '; + $linkback = '' . $langs->trans("BackToList") . ' '; dol_banner_tab($object, 'ref', $linkback, ($user->societe_id ? 0 : 1), 'ref', 'ref', $morehtmlref); @@ -1218,10 +1218,10 @@ if (empty($action) || $action == 'view' || $action == 'addlink' || $action == 'd print '
'; - // Message list - print load_fiche_titre($langs->trans('TicketMessagesList'), '', 'messages@ticket'); - $show_private_message = ($user->societe_id ? 0 : 1); - $actionobject->viewTicketTimelineMessages($show_private_message, true, $object); + // List of actions on element + include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php'; + $formactions = new FormActions($db); + $somethingshown = $formactions->showactions($object, 'ticket', $socid, 1); print '
'; print ''; diff --git a/htdocs/ticket/class/actions_ticket.class.php b/htdocs/ticket/class/actions_ticket.class.php index 76049a18a4e..b10f8ebe7da 100644 --- a/htdocs/ticket/class/actions_ticket.class.php +++ b/htdocs/ticket/class/actions_ticket.class.php @@ -443,8 +443,7 @@ class ActionsTicket // Sort results to be similar to status object list //sort($exclude_status); - //print '
'; - foreach ($object->statuts_short as $status => $statut_label) { + foreach ($object->statuts_short as $status => $status_label) { if (!in_array($status, $exclude_status)) { print '
'; diff --git a/htdocs/ticket/class/ticket.class.php b/htdocs/ticket/class/ticket.class.php index b68628d0c9b..750354e3356 100644 --- a/htdocs/ticket/class/ticket.class.php +++ b/htdocs/ticket/class/ticket.class.php @@ -207,10 +207,10 @@ class Ticket extends CommonObject */ const STATUS_NOT_READ = 0; const STATUS_READ = 1; - const STATUS_ANSWERED = 3; - const STATUS_ASSIGNED = 4; - const STATUS_IN_PROGRESS = 5; - const STATUS_WAITING = 6; + const STATUS_ASSIGNED = 2; + const STATUS_IN_PROGRESS = 3; + const STATUS_NEED_MORE_INFO = 5; + const STATUS_WAITING = 7; const STATUS_CLOSED = 8; const STATUS_CANCELED = 9; @@ -224,8 +224,8 @@ class Ticket extends CommonObject { $this->db = $db; - $this->statuts_short = array(0 => 'Unread', 1 => 'Read', 3 => 'Answered', 4 => 'Assigned', 5 => 'InProgress', 6 => 'Waiting', 8 => 'Closed', 9 => 'Deleted'); - $this->statuts = array(0 => 'Unread', 1 => 'Read', 3 => 'Answered', 4 => 'Assigned', 5 => 'InProgress', 6 => 'Waiting', 8 => 'Closed', 9 => 'Deleted'); + $this->statuts_short = array(self::STATUS_NOT_READ => 'Unread', self::STATUS_READ => 'Read', self::STATUS_ASSIGNED => 'Assigned', self::STATUS_IN_PROGRESS => 'InProgress', self::STATUS_NEED_MORE_INFO => 'NeedMoreInformation', self::STATUS_WAITING => 'Waiting', self::STATUS_CLOSED => 'Closed', self::STATUS_CANCELED => 'Canceled'); + $this->statuts = array(self::STATUS_NOT_READ => 'Unread', self::STATUS_READ => 'Read', self::STATUS_ASSIGNED => 'Assigned', self::STATUS_IN_PROGRESS => 'InProgress', self::STATUS_NEED_MORE_INFO => 'NeedMoreInformation', self::STATUS_WAITING => 'Waiting', self::STATUS_CLOSED => 'Closed', self::STATUS_CANCELED => 'Canceled'); } /** @@ -1176,7 +1176,7 @@ class Ticket extends CommonObject * Return status label of object * * @param string $statut 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 + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto * @return string Label */ public function LibStatut($statut, $mode = 0) @@ -1191,134 +1191,106 @@ class Ticket extends CommonObject return $langs->trans($this->statuts_short[$statut]); } elseif ($mode == 2) { - if ($statut == 0) { + if ($statut == self::STATUS_NOT_READ) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut0.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 1) { + elseif ($statut == self::STATUS_READ) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut1.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 3) { + elseif ($statut == self::STATUS_ASSIGNED) { + return img_picto($langs->trans($this->statuts_short[$statut]), 'statut2.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); + } + elseif ($statut == self::STATUS_IN_PROGRESS) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut3.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 4) { - return img_picto($langs->trans($this->statuts_short[$statut]), 'statut4.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); - } - - elseif ($statut == 5) { + elseif ($statut == self::STATUS_NEED_MORE_INFO) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut5.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 6) { + elseif ($statut == self::STATUS_WAITING) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut6.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 8) { + elseif ($statut == self::STATUS_CLOSED) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut8.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 9) { + elseif ($statut == self::STATUS_CANCELED) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut9.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } } elseif ($mode == 3) { - if ($statut == 0) { + if ($statut == self::STATUS_NOT_READ) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut0.png@ticket'); } - - elseif ($statut == 1) { + elseif ($statut == self::STATUS_READ) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut1.png@ticket'); } - - elseif ($statut == 3) { + elseif ($statut == self::STATUS_ASSIGNED) { + return img_picto($langs->trans($this->statuts_short[$statut]), 'statut2.png@ticket'); + } + elseif ($statut == self::STATUS_IN_PROGRESS) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut3.png@ticket'); } - - elseif ($statut == 4) { - return img_picto($langs->trans($this->statuts_short[$statut]), 'statut4.png@ticket'); - } - - elseif ($statut == 5) { + elseif ($statut == self::STATUS_NEED_MORE_INFO) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut5.png@ticket'); } - - elseif ($statut == 6) { + elseif ($statut == self::STATUS_WAITING) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut6.png@ticket'); } - - elseif ($statut == 8) { + elseif ($statut == self::STATUS_CLOSED) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut8.png@ticket'); } - - elseif ($statut == 9) { + elseif ($statut == self::STATUS_CANCELED) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut9.png@ticket'); } } elseif ($mode == 4) { - if ($statut == 0) { + if ($statut == self::STATUS_NOT_READ) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut0.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 1) { + elseif ($statut == self::STATUS_READ) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut1.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 3) { + elseif ($statut == self::STATUS_ASSIGNED) { + return img_picto($langs->trans($this->statuts_short[$statut]), 'statut2.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); + } + elseif ($statut == self::STATUS_IN_PROGRESS) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut3.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 4) { - return img_picto($langs->trans($this->statuts_short[$statut]), 'statut4.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); - } - - elseif ($statut == 5) { + elseif ($statut == self::STATUS_NEED_MORE_INFO) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut5.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 6) { + elseif ($statut == self::STATUS_WAITING) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut6.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 8) { + elseif ($statut == self::STATUS_CLOSED) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut8.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } - - elseif ($statut == 9) { + elseif ($statut == self::STATUS_CANCELED) { return img_picto($langs->trans($this->statuts_short[$statut]), 'statut9.png@ticket') . ' ' . $langs->trans($this->statuts_short[$statut]); } } - elseif ($mode == 5) { - if ($statut == 0) { + elseif ($mode == 5 || $mode == 6) { + if ($statut == self::STATUS_NOT_READ) { return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut0.png@ticket'); } - - elseif ($statut == 1) { + elseif ($statut == self::STATUS_READ) { return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut1.png@ticket'); } - - elseif ($statut == 3) { + elseif ($statut == self::STATUS_ASSIGNED) { + return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut2.png@ticket'); + } + elseif ($statut == self::STATUS_IN_PROGRESS) { return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut3.png@ticket'); } - - elseif ($statut == 4) { - return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut4.png@ticket'); - } - - elseif ($statut == 5) { + elseif ($statut == self::STATUS_NEED_MORE_INFO) { return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut5.png@ticket'); } - - elseif ($statut == 6) { + elseif ($statut == self::STATUS_WAITING) { return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut6.png@ticket'); } - - elseif ($statut == 8) { + elseif ($statut == self::STATUS_CLOSED) { return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut8.png@ticket'); } - - elseif ($statut == 9) { + elseif ($statut == self::STATUS_CANCELED) { return $langs->trans($this->statuts_short[$statut]) . ' ' . img_picto($langs->trans($this->statuts_short[$statut]), 'statut9.png@ticket'); } } @@ -1645,6 +1617,8 @@ class Ticket extends CommonObject global $conf, $langs; $error = 0; + $now = dol_now(); + // Clean parameters if (isset($this->fk_track_id)) { $this->fk_track_id = trim($this->fk_track_id); @@ -1654,38 +1628,33 @@ class Ticket extends CommonObject $this->message = trim($this->message); } - // Insert entry into agenda with code 'TICKET_MSG' - $sql.='...'; - - $this->db->begin(); - dol_syslog(get_class($this) . "::create_ticket_message sql=" . $sql, LOG_DEBUG); - $resql = $this->db->query($sql); - if (!$resql) { - $error++; - $this->errors[] = "Error " . $this->db->lasterror(); - } + // Insert entry into agenda with code 'TICKET_MSG' + include_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; + $actioncomm=new ActionComm($this->db); + $actioncomm->type_code = 'AC_OTH_AUTO'; + $actioncomm->code = 'TICKET_MSG'; + $actioncomm->socid = $this->socid; + $actioncomm->label = $this->subject; + $actioncomm->note = $this->message; + $actioncomm->userassigned = array($user->id); + $actioncomm->userownerid = $user->id; + $actioncomm->datep = $now; + $actioncomm->percentage = 100; + $actioncomm->elementtype = 'ticket'; + $actioncomm->fk_element = $this->id; - if (!$error) { - if (!$notrigger) { - // Uncomment this and change MYOBJECT to your own tag if you - // want this action calls a trigger. - //// Call triggers - //include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php'; - //$interface=new Interfaces($this->db); - //$result=$interface->run_triggers('MYOBJECT_CREATE',$this,$user,$langs,$conf); - //if ($result < 0) { $error++; $this->errors=$interface->errors; } - //// End call triggers - } + $actionid = $actioncomm->create($user); + if ($actionid <= 0) + { + $error++; + $this->error = $actioncomm->error; + $this->errors = $actioncomm->errors; } // Commit or rollback if ($error) { - foreach ($this->errors as $errmsg) { - dol_syslog(get_class($this) . "::create_ticket_message " . $errmsg, LOG_ERR); - $this->error .= ($this->error ? ', ' . $errmsg : $errmsg); - } $this->db->rollback(); return -1 * $error; } else { @@ -2493,6 +2462,7 @@ class Ticket extends CommonObject $error = 0; $ret = $object->fetch('', '', GETPOST('track_id', 'alpha')); + $object->socid = $object->fk_soc; $object->fetch_thirdparty(); if ($ret < 0) { @@ -2508,6 +2478,7 @@ class Ticket extends CommonObject } if (!$error) { + $object->subject = GETPOST('subject', 'alphanohtml'); $object->message = GETPOST("message", "none"); $object->private = GETPOST("private_message", "alpha"); $send_email = GETPOST('send_email', 'int'); diff --git a/htdocs/ticket/img/statut0.png b/htdocs/ticket/img/statut0.png index 6e631dc0086a9fae78a8486c3a55b4b0096b1488..b1cf5df0e7580226f61d129d2ebbd93506c0ee75 100644 GIT binary patch delta 186 zcmX@f^ontU3O`$tx4R1i82ohJT|d!KqMp6P)7O>#5eq-3ksiyLBYi;0a!(h>5R21y zCvW6pHso=h-~4~Itka43*mvtqQZoLnR+-D^^|E!F`*h(7ffH^_HyMh~HNOv3S-a2B z^V`cbuS`xw1_6r>VVMu0002% zNklWKfsLT5s#`N# zU*K-t{R6;_yCZ~fT}pZVroi1N56L7V2URryCL)Iz zs{Jqwt5VAIq9+`*ZF>Z;2e3ckKMK+>zH~i;PhsSD8U4JLTmS$707*qoM6N<$g8OHJ A*8l(j diff --git a/htdocs/ticket/img/statut1.png b/htdocs/ticket/img/statut1.png index 5bff8090beba27faa75233b12e1e80934a310434..4e72abd23cc2732ed9bd6cee69f81afc0a70481d 100644 GIT binary patch delta 316 zcmV-C0mJ^*1N;JzNq-(mL_t(Ijir;ZPQx$|hCf?TrMv|X!oXyE0}0-MiLD)w7?9cy zY)IrGy0S4OX@}-LI(B4ah$?!=lAt71Nh*HHlFxVd-+w;aIOpcp+68AKO;ZC9RrVrH z)8*LY5Q5fwdv4_}{!I`y4d>jvFIYsjo6V*G@ZNi1-y+EKe1G&k03Ux8gb;ca0Ncai zumdp0M5>y!2t=eeTSS;lCMy6{U1eD|>utd~cdM%Ldc9s%3h#j{fU+zf23t_oXKQWb zy}t(bz!dlfqM|6ipfg4hX)Rz^xh{c=iuARaGc<*z_x{ZoGX-u`^|LI?mpG1}>VUzA zlx5khu4;@)YBlMj2`Z9D5xF}ak4e`Tok}=`JkQ@xo&WyE5W-?CSrb31xqSEexw`29 O0000tvxr!3`(Wm+J6S#`_}+QAt!mJs_)k_ zu-5L0$PW>z7w}M3`v728!EqedMC5aT0esK0>}}{jT4fML(Gb9PG5I>nvR;~|e?xzE zgI25cbRPEJKL>CeauGRA({xhSm;hHQm7mVJ7opMZb|aD>O4_R=Nj}XFF#u4lRxd>4 z34m{%PG=tgrhn7vfr#t|VV>vxMJtN;ev9NpL>?D=-igQ?l4l~)ENWj=_0=K+lO)L> zW6VpEx5b`y0HXjG(=QjnKNFI@#6f1rGpTW{-x7!VC?a3Q z0el01QflJsYrk0F3;=>4m}sp>B<}%?hZMX60Le>|5RngG?0-EWNsZKDa*2>t}w9liO#u4lA9j&*%tjvFIYsjo6V*G@ZNi1-y+EKe1G&k03Ux8gb;ca0Ncai zumdp0M5>y!2t=eeTSS;lCMy6{U1eD|>utd~cdM%Ldc9s%3h#j{fU+zf23t_oXKQWb zy}t(bz!dlfqM|6ipfg4hX)Rz^xh{c=iuARaGc<*z_x{ZoGX-u`^|LI?mpG1}>VUzA zlx5khu4;@)YBlMj2`Z9D5xF}ak4e`Tok}=`JkQ@xo&WyE5W-?CSrb31xqSEexw`29 O0000s{Jqwt5VAIq8zksdjzltus`8H3eqpWbUlJkVdQri{k)c3 Q00000NkvXXt^-0~f)S*9zyJUM delta 300 zcmV+{0n`4;0_y^hNPhthNkl@we z$N_uubMQ;0yqQAed;aMqpmQp^oh>7N0OT!_1PB&ex9%n;6z030D$Dy ypaPOAP16Svc_nVB`Kp3eSZim-n8QDXhhhPiGEh8V3-TiX0000F>4z^5QX3DMRFm5QUubbFt{ldZpB$hk>sg% zX5RN^hh5+S5yx>YoMltkIrk30A<03b(HL%IV68nj#tcfO-hbK#-uu@8Mj&7R>5%`*F@xVfB}5Zvg~c>KU!rFMbQwzb}{)n%d%dYrhh|! zc7s-{^>iNg-aiL$9C8skP1AHz)|dcSDwUtkxfh|)?RF!QA4=M*BuPHa4>15xtyV8Y z_>4Avs24SA({Y5K^_kN4yL_{7Jd)|r28c1U@I=hL z{J?w21_lN)yMYZC`hW`!&AntBp-pB7h2z{*D;cJ!>T0TiKMzh3HBDpt_!uMolmRiu z927!$Ah`gr0RVp}A>ls8xCDT@uCGZh%xt5or+L8lge1Im&VQ}acbh^k0IbbytEy)r zvIF*X5JETx@Jw=MX6vr&ZmOy}ch0o{-cHp2rzQ526P=VrE3)vKxIyus8n c{!@GbXT59qCl6lXMgRZ+07*qoM6N<$f^JiR1ONa4 diff --git a/htdocs/ticket/img/statut8.png b/htdocs/ticket/img/statut8.png index 84f3c5e7fc505eac2b593d7005623dd6294e53cb..af7f6d433dc839f6d416e67af74dd2fd2ec9cf74 100644 GIT binary patch delta 277 zcmV+w0qXvc0@VVLNq_fAL_t(Ijonc(N(4a=teTzh9&kVK5n{0H&Vqp$ilHy?M9jVX zzfC~-Hy<{7qO=bs$#pl=s;WA7&b0vERP{te-bX!uGbjEdaZhIUI_mqrU*;0avOEIN zlAHl(RrM~XkgN29{JAtov-kdm$w^!vjE36ptk5X0}t+tEuL^!PGPU bQ+xquy=(X&zG2Cj4#ST8ZBK7ZJ^67LftKyV-z< z=IyQWEuPh29LI-qZfG?u*d;KtQzA1%MB-*OnAy)@S(X*RdPpQLLS{~<39c%bS>3BD z<^Jhbg@O=51W=Q-Rsev*bUhC#?WVh*Nkn3<(Vbui*OLO98ecuVI9;WzMpys<002ov JPDHLkV1hEeUi1I} diff --git a/htdocs/ticket/img/statut9.png b/htdocs/ticket/img/statut9.png new file mode 100644 index 0000000000000000000000000000000000000000..84f3c5e7fc505eac2b593d7005623dd6294e53cb GIT binary patch literal 272 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf4nJ z@RfovbtYqx$@+i%8#?A8yk<&yERH^7WrTH!AT&Fc7 z^6qM_r~h7twKfSju>?%s62{PQxWtxU^X;1D+r1XCOV_wX Q0A0`E>FVdQ&MBb@052G5fdBvi literal 0 HcmV?d00001 From 3a8d645fb9c25b3cd89173d208bb15e0a5d679e2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 1 May 2019 20:55:46 +0200 Subject: [PATCH 107/132] Debug module ticket --- .../install/mysql/migration/9.0.0-10.0.0.sql | 3 +++ .../install/mysql/tables/llx_actioncomm.sql | 3 ++- .../mysql/tables/llx_ticket_msg.key.sql | 17 ------------ .../install/mysql/tables/llx_ticket_msg.sql | 26 ------------------- htdocs/ticket/class/api_tickets.class.php | 7 +---- htdocs/ticket/class/ticket.class.php | 18 +++++-------- 6 files changed, 13 insertions(+), 61 deletions(-) delete mode 100755 htdocs/install/mysql/tables/llx_ticket_msg.key.sql delete mode 100755 htdocs/install/mysql/tables/llx_ticket_msg.sql diff --git a/htdocs/install/mysql/migration/9.0.0-10.0.0.sql b/htdocs/install/mysql/migration/9.0.0-10.0.0.sql index 9aa395c22d6..e5b925b0d83 100644 --- a/htdocs/install/mysql/migration/9.0.0-10.0.0.sql +++ b/htdocs/install/mysql/migration/9.0.0-10.0.0.sql @@ -94,6 +94,9 @@ ALTER TABLE llx_bank_url DROP INDEX uk_bank_url; ALTER TABLE llx_bank_url ADD UNIQUE INDEX uk_bank_url (fk_bank, url_id, type); ALTER TABLE llx_actioncomm ADD COLUMN calling_duration integer; +ALTER TABLE llx_actioncomm ADD COLUMN visibility varchar(12) DEFAULT 'default'; + +DROP TABLE llx_ticket_msg; ALTER TABLE llx_don ADD COLUMN fk_soc integer NULL; diff --git a/htdocs/install/mysql/tables/llx_actioncomm.sql b/htdocs/install/mysql/tables/llx_actioncomm.sql index 046b8c155bd..ad6ea20115c 100644 --- a/htdocs/install/mysql/tables/llx_actioncomm.sql +++ b/htdocs/install/mysql/tables/llx_actioncomm.sql @@ -46,7 +46,8 @@ create table llx_actioncomm transparency integer, -- transparency (ical standard). used to say if user assigned to event are busy or not by event. This field may be deprecated if we want to store transparency for each assigned user, moved into table llx_actioncomm_resources. priority smallint, -- priority (ical standard) - fulldayevent smallint NOT NULL default 0, -- priority (ical standard) + visibility varchar(12) DEFAULT 'default', -- visibility (ical standard) - 'default', 'public', 'private', 'confidential' + fulldayevent smallint NOT NULL default 0, -- full day (ical standard) punctual smallint NOT NULL default 1, -- deprecated. milestone is event with date start (datep) = date end (datep2) percent smallint NOT NULL default 0, location varchar(128), diff --git a/htdocs/install/mysql/tables/llx_ticket_msg.key.sql b/htdocs/install/mysql/tables/llx_ticket_msg.key.sql deleted file mode 100755 index f6ff6fc5e88..00000000000 --- a/htdocs/install/mysql/tables/llx_ticket_msg.key.sql +++ /dev/null @@ -1,17 +0,0 @@ --- SQL definition for module ticket --- Copyright (C) 2013 Jean-François FERRY --- --- This program is free software: you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- 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 . - ---ALTER TABLE llx_ticket_msg ADD CONSTRAINT fk_ticket_msg_fk_track_id FOREIGN KEY (fk_track_id) REFERENCES llx_ticket (track_id); diff --git a/htdocs/install/mysql/tables/llx_ticket_msg.sql b/htdocs/install/mysql/tables/llx_ticket_msg.sql deleted file mode 100755 index 7ff3297b0cc..00000000000 --- a/htdocs/install/mysql/tables/llx_ticket_msg.sql +++ /dev/null @@ -1,26 +0,0 @@ --- SQL definition for module ticket --- Copyright (C) 2013 Jean-François FERRY --- --- This program is free software: you can redistribute it and/or modify --- it under the terms of the GNU General Public License as published by --- 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_ticket_msg -( - rowid integer AUTO_INCREMENT PRIMARY KEY, - entity integer DEFAULT 1, - fk_track_id varchar(128), - fk_user_action integer, - datec datetime, - message text, - private integer DEFAULT 0 -)ENGINE=innodb; diff --git a/htdocs/ticket/class/api_tickets.class.php b/htdocs/ticket/class/api_tickets.class.php index fedadd2c96e..818514868c2 100644 --- a/htdocs/ticket/class/api_tickets.class.php +++ b/htdocs/ticket/class/api_tickets.class.php @@ -123,19 +123,14 @@ class Tickets extends DolibarrApi /** * Get properties of a Ticket object - * * Return an array with ticket informations * * @param int $id ID of ticket * @param string $track_id Tracking ID of ticket * @param string $ref Reference for ticket * @return array|mixed Data without useless information - * - * @throws 401 - * @throws 403 - * @throws 404 */ - public function getCommon($id = 0, $track_id = '', $ref = '') + private function getCommon($id = 0, $track_id = '', $ref = '') { if (! DolibarrApiAccess::$user->rights->ticket->read) { throw new RestException(403); diff --git a/htdocs/ticket/class/ticket.class.php b/htdocs/ticket/class/ticket.class.php index 750354e3356..bae523b1819 100644 --- a/htdocs/ticket/class/ticket.class.php +++ b/htdocs/ticket/class/ticket.class.php @@ -906,12 +906,6 @@ class Ticket extends CommonObject if ($res < 0) $error++; } - if (!$error) { - $sql = "DELETE FROM " . MAIN_DB_PREFIX . "ticket_msg"; - $sql .= " WHERE fk_track_id = '" . $this->db->escape($this->track_id) . "'"; - $resql = $this->db->query($sql); - } - // Removed extrafields if (!$error) { $result = $this->deleteExtraFields(); @@ -1677,12 +1671,13 @@ class Ticket extends CommonObject } // Cache deja charge - $sql = "SELECT rowid, fk_user_action, datec, message, private"; - $sql .= " FROM " . MAIN_DB_PREFIX . "ticket_msg"; - $sql .= " WHERE fk_track_id ='" . $this->db->escape($this->track_id) . "'"; + $sql = "SELECT rowid, fk_user_author, datec, label, message, visibility"; + $sql .= " FROM " . MAIN_DB_PREFIX . "actioncomm"; + $sql .= " WHERE fk_element = " . (int) $this->id; + $sql .= " AND elementtype = 'ticket'"; $sql .= " ORDER BY datec DESC"; - dol_syslog(get_class($this) . "::load_cache_actions_ticket sql=" . $sql, LOG_DEBUG); + dol_syslog(get_class($this) . "::load_cache_actions_ticket sql=" . $sql, LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { $num = $this->db->num_rows($resql); @@ -1692,8 +1687,9 @@ class Ticket extends CommonObject $this->cache_msgs_ticket[$i]['id'] = $obj->rowid; $this->cache_msgs_ticket[$i]['fk_user_action'] = $obj->fk_user_action; $this->cache_msgs_ticket[$i]['datec'] = $this->db->jdate($obj->datec); + $this->cache_msgs_ticket[$i]['subject'] = $obj->label; $this->cache_msgs_ticket[$i]['message'] = $obj->message; - $this->cache_msgs_ticket[$i]['private'] = $obj->private; + $this->cache_msgs_ticket[$i]['private'] = ($obj->visibility == 'private' ? 1 : 0); $i++; } return $num; From 4756499a81da5598d3dae3fbfc4addc2ecb04ed8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 2 May 2019 12:03:14 +0200 Subject: [PATCH 108/132] Debug module builder for generation of APIs --- htdocs/api/class/api.class.php | 2 +- htdocs/langs/en_US/main.lang | 2 +- htdocs/langs/en_US/modulebuilder.lang | 24 ++- htdocs/modulebuilder/index.php | 195 +++++++++++++----- .../template/class/api_mymodule.class.php | 59 +++--- .../core/modules/modMyModule.class.php | 32 ++- ..._99_modMyModule_MyModuleTriggers.class.php | 6 +- 7 files changed, 219 insertions(+), 101 deletions(-) diff --git a/htdocs/api/class/api.class.php b/htdocs/api/class/api.class.php index df7054ca162..de5a1e75d0a 100644 --- a/htdocs/api/class/api.class.php +++ b/htdocs/api/class/api.class.php @@ -216,7 +216,7 @@ class DolibarrApi * * @param string $resource element to check * @param int $resource_id Object ID if we want to check a particular record (optional) is linked to a owned thirdparty (optional). - * @param type $dbtablename 'TableName&SharedElement' with Tablename is table where object is stored. SharedElement is an optional key to define where to check entity. Not used if objectid is null (optional) + * @param string $dbtablename 'TableName&SharedElement' with Tablename is table where object is stored. SharedElement is an optional key to define where to check entity. Not used if objectid is null (optional) * @param string $feature2 Feature to check, second level of permission (optional). Can be or check with 'level1|level2'. * @param string $dbt_keyfield Field name for socid foreign key if not fk_soc. Not used if objectid is null (optional) * @param string $dbt_select Field name for select if not rowid. Not used if objectid is null (optional) diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 3aec931714b..463cf828b29 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -855,7 +855,7 @@ Download=Download DownloadDocument=Download document ActualizeCurrency=Update currency rate Fiscalyear=Fiscal year -ModuleBuilder=Module Builder +ModuleBuilder=Module and Application Builder SetMultiCurrencyCode=Set currency BulkActions=Bulk actions ClickToShowHelp=Click to show tooltip help diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang index 8e2d57a03fc..5cb927dc8b7 100644 --- a/htdocs/langs/en_US/modulebuilder.lang +++ b/htdocs/langs/en_US/modulebuilder.lang @@ -1,5 +1,5 @@ # Dolibarr language file - Source file is en_US - loan -ModuleBuilderDesc=This tool must be used only by experienced users or developers. It provides utilities to build or edit your own module.
Documentation for alternative manual development is here. +ModuleBuilderDesc=This tool must be used only by experienced users or developers. It provides utilities to build or edit your own module. Documentation for alternative manual development is here. EnterNameOfModuleDesc=Enter name of the module/application to create with no spaces. Use uppercase to separate words (For example: MyModule, EcommerceForShop, SyncWithMySystem...) EnterNameOfObjectDesc=Enter name of the object to create with no spaces. Use uppercase to separate words (For example: MyObject, Student, Teacher...). The CRUD class file, but also API file, pages to list/add/edit/delete object and SQL files will be generated. ModuleBuilderDesc2=Path where modules are generated/edited (first directory for external modules defined into %s): %s @@ -21,13 +21,14 @@ ModuleBuilderDesctriggers=This is the view of triggers provided by your module. ModuleBuilderDeschooks=This tab is dedicated to hooks. ModuleBuilderDescwidgets=This tab is dedicated to manage/build widgets. ModuleBuilderDescbuildpackage=You can generate here a "ready to distribute" package file (a normalized .zip file) of your module and a "ready to distribute" documentation file. Just click on button to build the package or documentation file. -EnterNameOfModuleToDeleteDesc=You can delete your module. WARNING: ALL files of module AND structured data and documentation will be deleted! -EnterNameOfObjectToDeleteDesc=You can delete an object. WARNING: All files related to object will be deleted! +EnterNameOfModuleToDeleteDesc=You can delete your module. WARNING: All coding files of module (generated or created manually) AND structured data and documentation will be deleted! +EnterNameOfObjectToDeleteDesc=You can delete an object. WARNING: All coding files (generated or created manually) related to object will be deleted! DangerZone=Danger zone BuildPackage=Build package +BuildPackageDesc=You can generate a zip package or your application so your are ready to distribute it on any Dolibarr. You can also distribute it or sell it on marketplace like DoliStore.com. BuildDocumentation=Build documentation ModuleIsNotActive=This module is not activated yet. Go to %s to make it live or click here: -ModuleIsLive=This module has been activated. Any change on it may break a current active feature. +ModuleIsLive=This module has been activated. Any change may break a current live feature. DescriptionLong=Long description EditorName=Name of editor EditorUrl=URL of editor @@ -43,10 +44,11 @@ PathToModulePackage=Path to zip of module/application package PathToModuleDocumentation=Path to file of module/application documentation (%s) SpaceOrSpecialCharAreNotAllowed=Spaces or special characters are not allowed. FileNotYetGenerated=File not yet generated -RegenerateClassAndSql=Erase and regenerate class and sql files +RegenerateClassAndSql=Force update of .class and .sql files RegenerateMissingFiles=Generate missing files SpecificationFile=File of documentation LanguageFile=File for language +ObjectProperties=Object Properties ConfirmDeleteProperty=Are you sure you want to delete the property %s? This will change code in PHP class but also remove column from table definition of object. NotNull=Not NULL NotNullDesc=1=Set database to NOT NULL. -1=Allow null values and force value to NULL if empty ('' or 0). @@ -62,7 +64,8 @@ ReadmeFile=Readme file ChangeLog=ChangeLog file TestClassFile=File for PHP Unit Test class SqlFile=Sql file -PageForLib=File for PHP libraries +PageForLib=File for PHP library +PageForObjLib=File for PHP library dedicated to object SqlFileExtraFields=Sql file for complementary attributes SqlFileKey=Sql file for keys AnObjectAlreadyExistWithThisNameAndDiffCase=An object already exists with this name and a different case @@ -81,8 +84,10 @@ IsAMeasureDesc=Can the value of field be cumulated to get a total into list? (Ex SearchAllDesc=Is the field used to make a search from the quick search tool? (Examples: 1 or 0) SpecDefDesc=Enter here all documentation you want to provide with your module that is not already defined by other tabs. You can use .md or better, the rich .asciidoc syntax. LanguageDefDesc=Enter in this files, all the key and the translation for each language file. -MenusDefDesc=Define here the menus provided by your module (once defined, they are visible into the menu editor %s) -PermissionsDefDesc=Define here the new permissions provided by your module (once defined, they are visible into the default permissions setup %s) +MenusDefDesc=Define here the menus provided by your module +PermissionsDefDesc=Define here the new permissions provided by your module +MenusDefDescTooltip=The menus provided by your module/application are defined into the array $this->menus into the module descriptor file. You can edit manually this file or use the embedded editor.

Note: Once defined (and module re-activated), menus are also visible into the menu editor available to administrator users on %s. +PermissionsDefDescTooltip=The permissions provided by your module/application are defined into the array $this->rights into the module descriptor file. You can edit manually this file or use the embedded editor.

Note: Once defined (and module re-activated), permissions are visible into the default permissions setup %s. HooksDefDesc=Define in the module_parts['hooks'] property, in the module descriptor, the context of hooks you want to manage (list of contexts can be found by a search on 'initHooks(' in core code).
Edit the hook file to add code of your hooked functions (hookable functions can be found by a search on 'executeHooks' in core code). TriggerDefDesc=Define in the trigger file the code you want to execute for each business event executed. SeeIDsInUse=See IDs in use in your installation @@ -109,4 +114,5 @@ UseSpecificEditorName = Use a specific editor name UseSpecificEditorURL = Use a specific editor URL UseSpecificFamily = Use a specific family UseSpecificAuthor = Use a specific author -UseSpecificVersion = Use a specific initial version \ No newline at end of file +UseSpecificVersion = Use a specific initial version +ModuleMustBeEnabled=The module/application must be enabled first \ No newline at end of file diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 0e80c0ba4ac..0ad297221be 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -156,8 +156,7 @@ if ($dirins && $action == 'initmodule' && $modulename) dol_delete_file($destdir.'/scripts/'.strtolower($modulename).'.php'); dol_delete_dir($destdir.'/scripts'); - - // Delete some files related to Object (because the dolCopyDir has copied everything) + // Delete some files related to Object (because the previous dolCopyDir has copied everything) dol_delete_file($destdir.'/myobject_card.php'); dol_delete_file($destdir.'/myobject_note.php'); dol_delete_file($destdir.'/myobject_document.php'); @@ -222,6 +221,39 @@ if ($dirins && $action == 'initmodule' && $modulename) } } +if ($dirins && $action == 'initapi' && !empty($module)) +{ + dol_mkdir($dirins.'/'.strtolower($module).'/class'); + $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; + $srcfile = $srcdir.'/class/api_mymodule.class.php'; + $destfile = $dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php'; + //var_dump($srcfile);var_dump($destfile); + $result = dol_copy($srcfile, $destfile, 0, 0); + + if ($result > 0) + { + $modulename = ucfirst($module); // Force first letter in uppercase + $objectname = $tabobj; + + //var_dump($phpfileval['fullname']); + $arrayreplacement=array( + 'mymodule'=>strtolower($modulename), + 'MyModule'=>$modulename, + 'MYMODULE'=>strtoupper($modulename), + 'My module'=>$modulename, + 'my module'=>$modulename, + 'Mon module'=>$modulename, + 'mon module'=>$modulename, + 'htdocs/modulebuilder/template'=>strtolower($modulename), + 'myobject'=>strtolower($objectname), + 'MyObject'=>$objectname, + 'MYOBJECT'=>strtoupper($objectname), + '---Put here your own copyright and developer email---'=>dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email?' <'.$user->email.'>':'') + ); + + dolReplaceInFile($destfile, $arrayreplacement); + } +} if ($dirins && $action == 'inithook' && !empty($module)) { dol_mkdir($dirins.'/'.strtolower($module).'/class'); @@ -230,6 +262,26 @@ if ($dirins && $action == 'inithook' && !empty($module)) $destfile = $dirins.'/'.strtolower($module).'/class/actions_'.strtolower($module).'.class.php'; //var_dump($srcfile);var_dump($destfile); $result = dol_copy($srcfile, $destfile, 0, 0); + + if ($result > 0) + { + $modulename = ucfirst($module); // Force first letter in uppercase + + //var_dump($phpfileval['fullname']); + $arrayreplacement=array( + 'mymodule'=>strtolower($modulename), + 'MyModule'=>$modulename, + 'MYMODULE'=>strtoupper($modulename), + 'My module'=>$modulename, + 'my module'=>$modulename, + 'Mon module'=>$modulename, + 'mon module'=>$modulename, + 'htdocs/modulebuilder/template'=>strtolower($modulename), + '---Put here your own copyright and developer email---'=>dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email?' <'.$user->email.'>':'') + ); + + dolReplaceInFile($destfile, $arrayreplacement); + } } if ($dirins && $action == 'inittrigger' && !empty($module)) { @@ -500,10 +552,10 @@ if ($dirins && $action == 'initobject' && $module && $objectname) 'sql/llx_mymodule_myobject.sql'=>'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.sql', 'sql/llx_mymodule_myobject_extrafields.sql'=>'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'_extrafields.sql', 'sql/llx_mymodule_myobject.key.sql'=>'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.key.sql', - 'scripts/myobject.php'=>'scripts/'.strtolower($objectname).'.php', + //'scripts/mymodule.php'=>'scripts/'.strtolower($objectname).'.php', 'img/object_myobject.png'=>'img/object_'.strtolower($objectname).'.png', 'class/myobject.class.php'=>'class/'.strtolower($objectname).'.class.php', - 'class/api_mymodule.class.php'=>'class/api_'.strtolower($module).'.class.php' + //'class/api_mymodule.class.php'=>'class/api_'.strtolower($module).'.class.php' ); foreach($filetogenerate as $srcfile => $destfile) @@ -524,8 +576,8 @@ if ($dirins && $action == 'initobject' && $module && $objectname) } } - if (! $error) - { + //if (! $error) // If there is error copying 1 file, we still have to make the replacement + //{ // Scan for object class files $listofobject = dol_dir_list($destdir.'/class', 'files', 0, '\.class\.php$'); @@ -536,6 +588,7 @@ if ($dirins && $action == 'initobject' && $module && $objectname) if (preg_match('/^actions_/', $fileobj['name'])) continue; $tmpcontent=file_get_contents($fileobj['fullname']); + $reg=array(); if (preg_match('/class\s+([^\s]*)\s+extends\s+CommonObject/ims', $tmpcontent, $reg)) { $objectnameloop = $reg[1]; @@ -587,7 +640,7 @@ if ($dirins && $action == 'initobject' && $module && $objectname) // TODO } - } + //} } if (! $error) @@ -730,11 +783,11 @@ if ($dirins && $action == 'addproperty' && !empty($module) && ! empty($tabobj)) } } - if (GETPOST('regeneratemissing')) + /*if (GETPOST('regeneratemissing')) { setEventMessages($langs->trans("FeatureNotYetAvailable"), null, 'warnings'); $error++; - } + }*/ // Edit the class file to write properties if (! $error) @@ -760,7 +813,7 @@ if ($dirins && $action == 'addproperty' && !empty($module) && ! empty($tabobj)) clearstatcache(true); // Make a redirect to reload all data - header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.'&tabobj='.$objectname.'&nocache='.time()); + header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.($forceddirread?'@'.$dirread:'').'&tabobj='.$objectname.'&nocache='.time()); exit; } @@ -795,7 +848,7 @@ if ($dirins && $action == 'confirm_deleteproperty' && $propertykey) clearstatcache(true); // Make a redirect to reload all data - header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.'&tabobj='.$objectname); + header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.($forceddirread?'@'.$dirread:'').'&tabobj='.$objectname); exit; } @@ -1030,9 +1083,9 @@ if ($action == 'savefile' && empty($cancel)) if ($action == 'set' && $user->admin) { $param=''; - if ($module) $param.='&module='.$module; - if ($tab) $param.='&tab='.$tab; - if ($tabobj) $param.='&tabobj='.$tabobj; + if ($module) $param.='&module='.urlencode($module); + if ($tab) $param.='&tab='.urlencode($tab); + if ($tabobj) $param.='&tabobj='.urlencode($tabobj); $value = GETPOST('value', 'alpha'); $resarray = activateModule($value); @@ -1065,9 +1118,9 @@ if ($action == 'set' && $user->admin) if ($action == 'reset' && $user->admin) { $param=''; - if ($module) $param.='&module='.$module; - if ($tab) $param.='&tab='.$tab; - if ($tabobj) $param.='&tabobj='.$tabobj; + if ($module) $param.='&module='.urlencode($module); + if ($tab) $param.='&tab='.urlencode($tab); + if ($tabobj) $param.='&tabobj='.urlencode($tabobj); $value = GETPOST('value', 'alpha'); $result=unActivateModule($value); @@ -1105,7 +1158,7 @@ $text=$langs->trans("ModuleBuilder"); print load_fiche_titre($text, '', 'title_setup'); -print $langs->trans("ModuleBuilderDesc", 'https://wiki.dolibarr.org/index.php/Module_development#Create_your_module').'
'; +print ''.$langs->trans("ModuleBuilderDesc", 'https://wiki.dolibarr.org/index.php/Module_development#Create_your_module').'
'; $dirsrootforscan=array($dirread); if ($dirread != DOL_DOCUMENT_ROOT && $conf->global->MAIN_FEATURES_LEVEL >=2) { $dirsrootforscan[]=DOL_DOCUMENT_ROOT; } @@ -1310,9 +1363,9 @@ elseif (! empty($module)) $const_name = 'MAIN_MODULE_'.strtoupper($module); $param=''; - if ($tab) $param.= '&tab='.$tab; - if ($module) $param.='&module='.$module; - if ($tabobj) $param.='&tabobj='.$tabobj; + if ($tab) $param.='&tab='.urlencode($tab); + if ($module) $param.='&module='.urlencode($module); + if ($tabobj) $param.='&tabobj='.urlencode($tabobj); $urltomodulesetup=''.$langs->trans('Home').'-'.$langs->trans("Setup").'-'.$langs->trans("Modules").''; $linktoenabledisable=''; @@ -1595,8 +1648,8 @@ elseif (! empty($module)) { $pathtofile = $modulelowercase.'/langs/'.$langfile['relativename']; print '
'; } print '
'.$langs->trans("AccountParameter").''.$langs->trans("Value").''.$langs->trans("Status").'
'; $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); print $form->selectarray("STRIPE_LIVE", $arrval, $conf->global->STRIPE_LIVE); } -print '
'; print ''.$langs->trans("STRIPE_TEST_WEBHOOK_KEY").''; - print ''; - print '   '.$langs->trans("Example").': we_xxxxxxxxxxxxxxxxxxxxxxxx
'; + if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { + print ''; + print '   '.$langs->trans("Example").': we_xxxxxxxxxxxxxxxxxxxxxxxx
'; + } print ''; print '   '.$langs->trans("Example").': whsec_xxxxxxxxxxxxxxxxxxxxxxxx'; $out = img_picto('', 'object_globe.png').' '.$langs->trans("ToOfferALinkForTestWebhook").' '; - $url = dol_buildpath('/public/stripe/ipn.php?test', 3); + $url = dol_buildpath('/public/stripe/ipn.php?test', 3); $out.= ''; $out.= ajax_autoselect("onlinetestwebhookurl", 0); - print '
'.$out; + print '
'.$out; print '
'; -if ( !empty($conf->global->STRIPE_TEST_WEBHOOK_KEY) && !empty($conf->global->STRIPE_TEST_SECRET_KEY) && !empty($conf->global->STRIPE_TEST_WEBHOOK_ID) ) { -\Stripe\Stripe::setApiKey($conf->global->STRIPE_TEST_SECRET_KEY); -$endpoint = \Stripe\WebhookEndpoint::retrieve($conf->global->STRIPE_TEST_WEBHOOK_ID); -$endpoint->enabled_events = $stripearrayofwebhookevents; -if ( GETPOST('webhook', 'alpha') == $conf->global->STRIPE_TEST_WEBHOOK_ID ) { -if ( empty(GETPOST('status', 'alpha')) ) { - $endpoint->disabled = true; -} else { - $endpoint->disabled = false; -}} -$endpoint->url = dol_buildpath('/public/stripe/ipn.php?test', 3); -$endpoint->save(); -if ($endpoint->status == 'enabled') -{ - print ''; - print img_picto($langs->trans("Activated"), 'switch_on'); -} -else -{ - print ''; - print img_picto($langs->trans("Disabled"), 'switch_off'); -} -//print $endpoint; -} else print img_picto($langs->trans("inactive"), 'statut5'); - print'
'.$langs->trans("StripeConnect").''.$langs->trans("StripeConnect_Mode").'
'; @@ -238,7 +249,7 @@ else print '% + '; print price($conf->global->STRIPE_APPLICATION_FEE); print ' '.$langs->getCurrencySymbol($conf->currency).' '.$langs->trans("minimum").' '.price($conf->global->STRIPE_APPLICATION_FEE_MINIMAL).' '.$langs->getCurrencySymbol($conf->currency).'
'; - print ''; - print '   '.$langs->trans("Example").': we_xxxxxxxxxxxxxxxxxxxxxxxx
'; print ''.$langs->trans("STRIPE_LIVE_WEBHOOK_KEY").'
'; + if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { + print ''; + print '   '.$langs->trans("Example").': we_xxxxxxxxxxxxxxxxxxxxxxxx
'; + } print ''; print '   '.$langs->trans("Example").': whsec_xxxxxxxxxxxxxxxxxxxxxxxx'; $out = img_picto('', 'object_globe.png').' '.$langs->trans("ToOfferALinkForLiveWebhook").' '; $url = dol_buildpath('/public/stripe/ipn.php', 3); $out.= ''; $out.= ajax_autoselect("onlinelivewebhookurl", 0); - print '
'.$out; + print '
'.$out; print '
'; - if ( !empty($conf->global->STRIPE_LIVE_WEBHOOK_KEY) && !empty($conf->global->STRIPE_LIVE_SECRET_KEY) && !empty($conf->global->STRIPE_LIVE_WEBHOOK_ID) ) { - \Stripe\Stripe::setApiKey($conf->global->STRIPE_LIVE_SECRET_KEY); - $endpoint = \Stripe\WebhookEndpoint::retrieve($conf->global->STRIPE_LIVE_WEBHOOK_ID); - $endpoint->enabled_events = $stripearrayofwebhookevents; - if ( GETPOST('webhook', 'alpha') == $conf->global->STRIPE_LIVE_WEBHOOK_ID ) { - if ( empty(GETPOST('status', 'alpha')) ) { - $endpoint->disabled = true; - } else { - $endpoint->disabled = false; - }} - $endpoint->url = dol_buildpath('/public/stripe/ipn.php', 3); - $endpoint->save(); - if ($endpoint->status == 'enabled') - { - print ''; - print img_picto($langs->trans("Activated"), 'switch_on'); - } - else - { - print ''; - print img_picto($langs->trans("Disabled"), 'switch_off'); - } - //print $endpoint; - } else print img_picto($langs->trans("inactive"), 'statut5'); + if ($conf->global->MAIN_FEATURES_LEVEL >= 2) + { + if (!empty($conf->global->STRIPE_LIVE_WEBHOOK_KEY) && !empty($conf->global->STRIPE_LIVE_SECRET_KEY) && !empty($conf->global->STRIPE_LIVE_WEBHOOK_ID)) + { + \Stripe\Stripe::setApiKey($conf->global->STRIPE_LIVE_SECRET_KEY); + $endpoint = \Stripe\WebhookEndpoint::retrieve($conf->global->STRIPE_LIVE_WEBHOOK_ID); + $endpoint->enabled_events = $stripearrayofwebhookevents; + if ( GETPOST('webhook', 'alpha') == $conf->global->STRIPE_LIVE_WEBHOOK_ID ) { + if ( empty(GETPOST('status', 'alpha')) ) { + $endpoint->disabled = true; + } else { + $endpoint->disabled = false; + } + } + $endpoint->url = dol_buildpath('/public/stripe/ipn.php', 3); + $endpoint->save(); + if ($endpoint->status == 'enabled') + { + print ''; + print img_picto($langs->trans("Activated"), 'switch_on'); + } + else + { + print ''; + print img_picto($langs->trans("Disabled"), 'switch_off'); + } + //print $endpoint; + } + else + { + print img_picto($langs->trans("inactive"), 'statut5'); + } + } print '
'.$langs->trans("StripeConnect").''.$langs->trans("StripeConnect_Mode").'
'.$langs->trans("StripeConnect_Mode").'
'.$langs->trans("Duration").''; - print ''; + print ''; print $formproduct->selectMeasuringUnits("duration_unit", "time", GETPOST('duration_value', 'alpha'), 0, 1); print '
'.$langs->trans("Duration").''; - print ' '; + print ' '; print $formproduct->selectMeasuringUnits("duration_unit", "time", $object->duration_unit, 0, 1); print '
'; print '
'.$langs->trans("ProductAccountancySellIntraCode").''; - print '
'.$langs->trans("ProductAccountancySellExportCode").''; + print '
'.$langs->trans("ProductAccountancySellIntraCode").''; print '
'.$langs->trans("ProductAccountancySellExportCode").''; + print '
'.$langs->trans("ProductAccountancyBuyCode").''; @@ -1514,24 +1512,21 @@ else print $formaccounting->select_account($object->accountancy_code_sell, 'accountancy_code_sell', 1, '', 1, 1); print '
'.$langs->trans("ProductAccountancySellIntraCode").''; - print $formaccounting->select_account($object->accountancy_code_sell_intra, 'accountancy_code_sell_intra', 1, '', 1, 1); - print '
'.$langs->trans("ProductAccountancySellExportCode").'
'.$langs->trans("ProductAccountancySellIntraCode").''; - print $formaccounting->select_account($object->accountancy_code_sell_export, 'accountancy_code_sell_export', 1, '', 1, 1); + print $formaccounting->select_account($object->accountancy_code_sell_intra, 'accountancy_code_sell_intra', 1, '', 1, 1); print '
'.$langs->trans("ProductAccountancySellExportCode").''; + print $formaccounting->select_account($object->accountancy_code_sell_export, 'accountancy_code_sell_export', 1, '', 1, 1); + print '
'.$langs->trans("ProductAccountancyBuyCode").''; @@ -1545,22 +1540,19 @@ else print ''; print '
'.$langs->trans("ProductAccountancySellIntraCode").''; - print '
'.$langs->trans("ProductAccountancySellExportCode").''; + print '
'.$langs->trans("ProductAccountancySellIntraCode").''; print '
'.$langs->trans("ProductAccountancySellExportCode").''; + print '
'.$langs->trans("ProductAccountancyBuyCode").''; @@ -1687,48 +1679,45 @@ else } print '
'; - print $langs->trans("ProductAccountancySellIntraCode"); - print ''; - if (! empty($conf->accounting->enabled)) - { - if (! empty($object->accountancy_code_sell_intra)) - { - $accountingaccount2 = new AccountingAccount($db); - $accountingaccount2->fetch('', $object->accountancy_code_sell_intra, 1); - - print $accountingaccount2->getNomUrl(0, 1, 1, '', 1); - } - } else { - print $object->accountancy_code_sell_intra; - } - print '
'; - print $langs->trans("ProductAccountancySellExportCode"); + print $langs->trans("ProductAccountancySellIntraCode"); print ''; if (! empty($conf->accounting->enabled)) { - if (! empty($object->accountancy_code_sell_export)) + if (! empty($object->accountancy_code_sell_intra)) { - $accountingaccount3 = new AccountingAccount($db); - $accountingaccount3->fetch('', $object->accountancy_code_sell_export, 1); + $accountingaccount2 = new AccountingAccount($db); + $accountingaccount2->fetch('', $object->accountancy_code_sell_intra, 1); - print $accountingaccount3->getNomUrl(0, 1, 1, '', 1); + print $accountingaccount2->getNomUrl(0, 1, 1, '', 1); } } else { - print $object->accountancy_code_sell_export; + print $object->accountancy_code_sell_intra; } print '
'; + print $langs->trans("ProductAccountancySellExportCode"); + print ''; + if (! empty($conf->accounting->enabled)) + { + if (! empty($object->accountancy_code_sell_export)) + { + $accountingaccount3 = new AccountingAccount($db); + $accountingaccount3->fetch('', $object->accountancy_code_sell_export, 1); + + print $accountingaccount3->getNomUrl(0, 1, 1, '', 1); + } + } else { + print $object->accountancy_code_sell_export; + } + print '
'; print $langs->trans("ProductAccountancyBuyCode"); diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 56d8b0bc504..39e98730365 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -62,6 +62,8 @@ $fourn_id = GETPOST("fourn_id", 'int'); $catid = GETPOST('catid', 'int'); $search_tobatch = GETPOST("search_tobatch", 'int'); $search_accountancy_code_sell = GETPOST("search_accountancy_code_sell", 'alpha'); +$search_accountancy_code_sell_intra = GETPOST("search_accountancy_code_sell_intra", 'alpha'); +$search_accountancy_code_sell_export = GETPOST("search_accountancy_code_sell_export", 'alpha'); $search_accountancy_code_buy = GETPOST("search_accountancy_code_buy", 'alpha'); $optioncss = GETPOST('optioncss', 'alpha'); $type=GETPOST("type", "int"); @@ -154,6 +156,8 @@ if (empty($conf->global->PRODUIT_MULTIPRICES)) } } +$isInEEC=isInEEC($mysoc); + // Definition of fields for lists $arrayfields=array( 'p.ref'=>array('label'=>$langs->trans("Ref"), 'checked'=>1), @@ -175,8 +179,10 @@ $arrayfields=array( 'p.stock'=>array('label'=>$langs->trans("PhysicalStock"), 'checked'=>1, 'enabled'=>(! empty($conf->stock->enabled) && $user->rights->stock->lire && $contextpage != 'service')), 'stock_virtual'=>array('label'=>$langs->trans("VirtualStock"), 'checked'=>1, 'enabled'=>(! empty($conf->stock->enabled) && $user->rights->stock->lire && $contextpage != 'service' && $virtualdiffersfromphysical)), 'p.tobatch'=>array('label'=>$langs->trans("ManageLotSerial"), 'checked'=>0, 'enabled'=>(! empty($conf->productbatch->enabled))), - 'p.accountancy_code_sell'=>array('label'=>$langs->trans("ProductAccountancySellCode"), 'checked'=>0), - 'p.accountancy_code_buy'=>array('label'=>$langs->trans("ProductAccountancyBuyCode"), 'checked'=>0), + 'p.accountancy_code_sell'=>array('label'=>$langs->trans("ProductAccountancySellCode"), 'checked'=>0, 'position'=>400), + 'p.accountancy_code_sell_intra'=>array('label'=>$langs->trans("ProductAccountancySellIntraCode"), 'checked'=>0, 'enabled'=>$isInEEC, 'position'=>401), + 'p.accountancy_code_sell_export'=>array('label'=>$langs->trans("ProductAccountancySellExportCode"), 'checked'=>0, 'position'=>402), + 'p.accountancy_code_buy'=>array('label'=>$langs->trans("ProductAccountancyBuyCode"), 'checked'=>0, 'position'=>403), 'p.datec'=>array('label'=>$langs->trans("DateCreation"), 'checked'=>0, 'position'=>500), 'p.tms'=>array('label'=>$langs->trans("DateModificationShort"), 'checked'=>0, 'position'=>500), 'p.tosell'=>array('label'=>$langs->trans("Status").' ('.$langs->trans("Sell").')', 'checked'=>1, 'position'=>1000), @@ -227,6 +233,8 @@ if (empty($reshook)) $show_childproducts = ''; $search_accountancy_code_sell=''; + $search_accountancy_code_sell_intra=''; + $search_accountancy_code_sell_export=''; $search_accountancy_code_buy=''; $search_array_options=array(); } @@ -321,8 +329,10 @@ if ($search_categ > 0) $sql.= " AND cp.fk_categorie = ".$db->escape($search_ca if ($search_categ == -2) $sql.= " AND cp.fk_categorie IS NULL"; if ($fourn_id > 0) $sql.= " AND pfp.fk_soc = ".$fourn_id; if ($search_tobatch != '' && $search_tobatch >= 0) $sql.= " AND p.tobatch = ".$db->escape($search_tobatch); -if ($search_accountancy_code_sell) $sql.= natural_search('p.accountancy_code_sell', $search_accountancy_code_sell); -if ($search_accountancy_code_buy) $sql.= natural_search('p.accountancy_code_buy', $search_accountancy_code_buy); +if ($search_accountancy_code_sell) $sql.= natural_search('p.accountancy_code_sell', $search_accountancy_code_sell); +if ($search_accountancy_code_sell_intra) $sql.= natural_search('p.accountancy_code_sell_intra', $search_accountancy_code_sell_intra); +if ($search_accountancy_code_sell_export) $sql.= natural_search('p.accountancy_code_sell_export', $search_accountancy_code_sell_export); +if ($search_accountancy_code_buy) $sql.= natural_search('p.accountancy_code_buy', $search_accountancy_code_buy); // Add where from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; @@ -418,6 +428,8 @@ if ($resql) if ($optioncss != '') $param.='&optioncss='.urlencode($optioncss); if ($search_tobatch) $param="&search_ref_supplier=".urlencode($search_ref_supplier); if ($search_accountancy_code_sell) $param="&search_accountancy_code_sell=".urlencode($search_accountancy_code_sell); + if ($search_accountancy_code_sell_intra) $param="&search_accountancy_code_sell_intra=".urlencode($search_accountancy_code_sell_intra); + if ($search_accountancy_code_sell_export) $param="&search_accountancy_code_sell_export=".urlencode($search_accountancy_code_sell_export); if ($search_accountancy_code_buy) $param="&search_accountancy_code_buy=".urlencode($search_accountancy_code_buy); // Add $param from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; @@ -630,8 +642,10 @@ if ($resql) // To batch if (! empty($arrayfields['p.tobatch']['checked'])) print ''.$form->selectyesno($search_tobatch, '', '', '', 1).''.$obj->accountancy_code_sell.''.$obj->accountancy_code_sell_intra.''.$obj->accountancy_code_sell_export.''.$obj->accountancy_code_buy.''; + print ''; if ($showlineingray) { print ''.img_object('','projecttask').' '.$lines[$i]->ref.''; From becf096bf86742b9cb2ffc3358fc0367061b526b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 25 Apr 2019 01:37:08 +0200 Subject: [PATCH 023/132] FIX ref for table without ref manager are set to NULL. --- htdocs/install/mysql/tables/llx_payment_salary.sql | 2 +- htdocs/install/mysql/tables/llx_payment_various.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/install/mysql/tables/llx_payment_salary.sql b/htdocs/install/mysql/tables/llx_payment_salary.sql index c56e6459aa0..0c19ee93915 100644 --- a/htdocs/install/mysql/tables/llx_payment_salary.sql +++ b/htdocs/install/mysql/tables/llx_payment_salary.sql @@ -19,7 +19,7 @@ create table llx_payment_salary ( rowid integer AUTO_INCREMENT PRIMARY KEY, - ref varchar(30) NOT NULL, -- payment reference number + ref varchar(30) NULL, -- payment reference number (currently NULL because there is no numbering manager yet) tms timestamp, datec datetime, -- Create date fk_user integer NOT NULL, diff --git a/htdocs/install/mysql/tables/llx_payment_various.sql b/htdocs/install/mysql/tables/llx_payment_various.sql index d3351287e58..023d6d018a7 100644 --- a/htdocs/install/mysql/tables/llx_payment_various.sql +++ b/htdocs/install/mysql/tables/llx_payment_various.sql @@ -19,7 +19,7 @@ create table llx_payment_various ( rowid integer AUTO_INCREMENT PRIMARY KEY, - ref varchar(30) NOT NULL, -- payment reference number + ref varchar(30) NULL, -- payment reference number (currently NULL because there is no numbering manager yet) num_payment varchar(50), -- num cheque or other label varchar(255), tms timestamp, From 2c411310bc0464311a3a0c1eab7a01feedbdc264 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Thu, 25 Apr 2019 08:29:43 +0200 Subject: [PATCH 024/132] FIX Menu Accountancy (Simple) not accessible without module Accountancy (Double entries) --- htdocs/core/menus/standard/eldy.lib.php | 74 ++++++++++++------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index 02727acf36c..dcee245f257 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -1302,42 +1302,6 @@ function print_left_eldy_menu($db, $menu_array_before, $menu_array_after, &$tabM } } - // Accountancy (simple) - if (! empty($conf->comptabilite->enabled)) - { - $langs->load("compta"); - - // Bilan, resultats - $newmenu->add("/compta/resultat/index.php?leftmenu=report&mainmenu=accountancy", $langs->trans("Reportings"), 0, $user->rights->compta->resultat->lire, '', $mainmenu, 'ca'); - - if ($usemenuhider || empty($leftmenu) || preg_match('/report/', $leftmenu)) { - $newmenu->add("/compta/resultat/index.php?leftmenu=report", $langs->trans("MenuReportInOut"), 1, $user->rights->compta->resultat->lire); - $newmenu->add("/compta/resultat/clientfourn.php?leftmenu=report", $langs->trans("ByCompanies"), 2, $user->rights->compta->resultat->lire); - /* On verra ca avec module compabilite expert - $newmenu->add("/compta/resultat/compteres.php?leftmenu=report","Compte de resultat",2,$user->rights->compta->resultat->lire); - $newmenu->add("/compta/resultat/bilan.php?leftmenu=report","Bilan",2,$user->rights->compta->resultat->lire); - */ - $newmenu->add("/compta/stats/index.php?leftmenu=report", $langs->trans("ReportTurnover"), 1, $user->rights->compta->resultat->lire); - - /* - $newmenu->add("/compta/stats/cumul.php?leftmenu=report","Cumule",2,$user->rights->compta->resultat->lire); - if (! empty($conf->propal->enabled)) { - $newmenu->add("/compta/stats/prev.php?leftmenu=report","Previsionnel",2,$user->rights->compta->resultat->lire); - $newmenu->add("/compta/stats/comp.php?leftmenu=report","Transforme",2,$user->rights->compta->resultat->lire); - } - */ - $newmenu->add("/compta/stats/casoc.php?leftmenu=report", $langs->trans("ByCompanies"), 2, $user->rights->compta->resultat->lire); - $newmenu->add("/compta/stats/cabyuser.php?leftmenu=report", $langs->trans("ByUsers"), 2, $user->rights->compta->resultat->lire); - $newmenu->add("/compta/stats/cabyprodserv.php?leftmenu=report", $langs->trans("ByProductsAndServices"), 2, $user->rights->compta->resultat->lire); - $newmenu->add("/compta/stats/byratecountry.php?leftmenu=report", $langs->trans("ByVatRate"), 2, $user->rights->compta->resultat->lire); - - // Journaux - $newmenu->add("/compta/journal/sellsjournal.php?leftmenu=report", $langs->trans("SellsJournal"), 1, $user->rights->compta->resultat->lire, '', '', '', 50); - $newmenu->add("/compta/journal/purchasesjournal.php?leftmenu=report", $langs->trans("PurchasesJournal"), 1, $user->rights->compta->resultat->lire, '', '', '', 51); - } - //if ($leftmenu=="ca") $newmenu->add("/compta/journaux/index.php?leftmenu=ca",$langs->trans("Journaux"),1,$user->rights->compta->resultat->lire||$user->rights->accounting->comptarapport->lire); - } - // Configuration $newmenu->add("/accountancy/index.php?leftmenu=accountancy_admin", $langs->trans("Setup"), 0, $user->rights->accounting->chartofaccount, '', $mainmenu, 'accountancy_admin', 1); if ($usemenuhider || empty($leftmenu) || preg_match('/accountancy_admin/', $leftmenu)) { @@ -1369,8 +1333,44 @@ function print_left_eldy_menu($db, $menu_array_before, $menu_array_after, &$tabM $newmenu->add("/accountancy/admin/closure.php?mainmenu=accountancy&leftmenu=accountancy_admin", $langs->trans("MenuClosureAccounts"), 1, $user->rights->accounting->chartofaccount, '', $mainmenu, 'accountancy_admin_closure', 120); $newmenu->add("/accountancy/admin/export.php?mainmenu=accountancy&leftmenu=accountancy_admin", $langs->trans("ExportOptions"), 1, $user->rights->accounting->chartofaccount, '', $mainmenu, 'accountancy_admin_export', 130); } - } + } + // Accountancy (simple) + if (! empty($conf->comptabilite->enabled)) + { + $langs->load("compta"); + + // Bilan, resultats + $newmenu->add("/compta/resultat/index.php?leftmenu=report&mainmenu=accountancy", $langs->trans("Reportings"), 0, $user->rights->compta->resultat->lire, '', $mainmenu, 'ca'); + + if ($usemenuhider || empty($leftmenu) || preg_match('/report/', $leftmenu)) { + $newmenu->add("/compta/resultat/index.php?leftmenu=report", $langs->trans("MenuReportInOut"), 1, $user->rights->compta->resultat->lire); + $newmenu->add("/compta/resultat/clientfourn.php?leftmenu=report", $langs->trans("ByCompanies"), 2, $user->rights->compta->resultat->lire); + /* On verra ca avec module compabilite expert + $newmenu->add("/compta/resultat/compteres.php?leftmenu=report","Compte de resultat",2,$user->rights->compta->resultat->lire); + $newmenu->add("/compta/resultat/bilan.php?leftmenu=report","Bilan",2,$user->rights->compta->resultat->lire); + */ + $newmenu->add("/compta/stats/index.php?leftmenu=report", $langs->trans("ReportTurnover"), 1, $user->rights->compta->resultat->lire); + + /* + $newmenu->add("/compta/stats/cumul.php?leftmenu=report","Cumule",2,$user->rights->compta->resultat->lire); + if (! empty($conf->propal->enabled)) { + $newmenu->add("/compta/stats/prev.php?leftmenu=report","Previsionnel",2,$user->rights->compta->resultat->lire); + $newmenu->add("/compta/stats/comp.php?leftmenu=report","Transforme",2,$user->rights->compta->resultat->lire); + } + */ + $newmenu->add("/compta/stats/casoc.php?leftmenu=report", $langs->trans("ByCompanies"), 2, $user->rights->compta->resultat->lire); + $newmenu->add("/compta/stats/cabyuser.php?leftmenu=report", $langs->trans("ByUsers"), 2, $user->rights->compta->resultat->lire); + $newmenu->add("/compta/stats/cabyprodserv.php?leftmenu=report", $langs->trans("ByProductsAndServices"), 2, $user->rights->compta->resultat->lire); + $newmenu->add("/compta/stats/byratecountry.php?leftmenu=report", $langs->trans("ByVatRate"), 2, $user->rights->compta->resultat->lire); + + // Journaux + $newmenu->add("/compta/journal/sellsjournal.php?leftmenu=report", $langs->trans("SellsJournal"), 1, $user->rights->compta->resultat->lire, '', '', '', 50); + $newmenu->add("/compta/journal/purchasesjournal.php?leftmenu=report", $langs->trans("PurchasesJournal"), 1, $user->rights->compta->resultat->lire, '', '', '', 51); + } + //if ($leftmenu=="ca") $newmenu->add("/compta/journaux/index.php?leftmenu=ca",$langs->trans("Journaux"),1,$user->rights->compta->resultat->lire||$user->rights->accounting->comptarapport->lire); + } + // Assets if (! empty($conf->asset->enabled)) { From 6190e7813e6a435fe68f074ffd68b3ac1272103d Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Thu, 25 Apr 2019 09:14:51 +0200 Subject: [PATCH 025/132] Fix get morphy adherent type --- htdocs/adherents/class/adherent_type.class.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/htdocs/adherents/class/adherent_type.class.php b/htdocs/adherents/class/adherent_type.class.php index 936c33d6c0c..9c7d34ed569 100644 --- a/htdocs/adherents/class/adherent_type.class.php +++ b/htdocs/adherents/class/adherent_type.class.php @@ -410,6 +410,21 @@ class AdherentType extends CommonObject return -1; } } + + /** + * Return translated label by the nature of a adherent (physical or moral) + * + * @param string $morphy Nature of the adherent (physical or moral) + * @return string Label + */ + function getmorphylib($morphy='') + { + global $langs; + if ($morphy == 'phy') { return $langs->trans("Physical"); } + elseif ($morphy == 'mor') { return $langs->trans("Moral"); } + else return $langs->trans("Physical & Morale"); + //return $morphy; + } /** * Return clicable name (with picto eventually) From 65bb7d90318dd19b2eaa7b409f7ac888ec7c87d3 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Thu, 25 Apr 2019 09:37:07 +0200 Subject: [PATCH 026/132] Update adherent_type.class.php --- htdocs/adherents/class/adherent_type.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/adherents/class/adherent_type.class.php b/htdocs/adherents/class/adherent_type.class.php index 9c7d34ed569..c310bb18627 100644 --- a/htdocs/adherents/class/adherent_type.class.php +++ b/htdocs/adherents/class/adherent_type.class.php @@ -417,14 +417,14 @@ class AdherentType extends CommonObject * @param string $morphy Nature of the adherent (physical or moral) * @return string Label */ - function getmorphylib($morphy='') + public function getmorphylib($morphy = '') { global $langs; if ($morphy == 'phy') { return $langs->trans("Physical"); } - elseif ($morphy == 'mor') { return $langs->trans("Moral"); } + elseif ($morphy == 'mor') { return $langs->trans("Moral"); } else return $langs->trans("Physical & Morale"); //return $morphy; - } + } /** * Return clicable name (with picto eventually) From 6fe84a79622ce222ad2ad3fc8883f9a3930d6b92 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 25 Apr 2019 11:18:25 +0200 Subject: [PATCH 027/132] Fix phpcs --- htdocs/core/lib/payments.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/payments.lib.php b/htdocs/core/lib/payments.lib.php index b73d59c6cfd..5d88f3e26ea 100644 --- a/htdocs/core/lib/payments.lib.php +++ b/htdocs/core/lib/payments.lib.php @@ -150,7 +150,7 @@ function showOnlinePaymentUrl($type, $ref) * @param string $localorexternal 0=Url for browser, 1=Url for external access * @return string Url string */ -function getOnlinePaymentUrl($mode, $type, $ref = '', $amount = '9.99', $freetag = 'your_free_tag', $localorexternal=0) +function getOnlinePaymentUrl($mode, $type, $ref = '', $amount = '9.99', $freetag = 'your_free_tag', $localorexternal = 0) { global $conf, $dolibarr_main_url_root; From cb658dda8cc007ceac78c721812d95ad444a7670 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Thu, 25 Apr 2019 12:04:26 +0200 Subject: [PATCH 028/132] Fix morphy type adherent --- htdocs/adherents/type.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/adherents/type.php b/htdocs/adherents/type.php index 9a241c027ab..089d817ac94 100644 --- a/htdocs/adherents/type.php +++ b/htdocs/adherents/type.php @@ -431,7 +431,7 @@ if ($rowid > 0) print '
'.$langs->trans("Nature").''.$object->getmorphylib().'
'.$langs->trans("Nature").''.$object->getmorphylib($object->morphy).'
'.$langs->trans("SubscriptionRequired").''; From 091132de2fedcee1d8bf9f58f50fcdb6344bc8e7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 25 Apr 2019 12:11:32 +0200 Subject: [PATCH 029/132] Signatures of methods createFromClone() has been standardized. All methods requires the object User as first parameter. --- ChangeLog | 1 + .../accountancy/class/bookkeeping.class.php | 10 +++---- htdocs/admin/emailcollector_card.php | 9 ++++-- htdocs/comm/action/card.php | 2 +- htdocs/comm/action/class/actioncomm.class.php | 28 +++++-------------- htdocs/comm/mailing/card.php | 2 +- htdocs/comm/mailing/class/mailing.class.php | 5 ++-- htdocs/comm/propal/card.php | 2 +- htdocs/comm/propal/class/propal.class.php | 13 +++++---- htdocs/commande/card.php | 2 +- htdocs/commande/class/commande.class.php | 7 +++-- htdocs/compta/bank/class/bankcateg.class.php | 9 +++--- .../facture/class/paymentterm.class.php | 5 ++-- .../sociales/class/cchargesociales.class.php | 9 +++--- .../class/paymentsocialcontribution.class.php | 5 ++-- htdocs/contrat/card.php | 2 +- htdocs/contrat/class/contrat.class.php | 11 ++++---- htdocs/core/actions_addupdatedelete.inc.php | 17 ----------- htdocs/core/class/ctyperesource.class.php | 9 +++--- .../core/modules/modEmailCollector.class.php | 2 +- htdocs/cron/class/cronjob.class.php | 5 ++-- htdocs/don/class/paymentdonation.class.php | 5 ++-- htdocs/ecm/class/ecmfiles.class.php | 9 +++--- htdocs/expensereport/card.php | 2 +- .../class/expensereport.class.php | 9 +++--- .../class/paymentexpensereport.class.php | 5 ++-- htdocs/fichinter/card.php | 2 +- htdocs/fichinter/class/fichinter.class.php | 9 +++--- .../class/fournisseur.commande.class.php | 7 +++-- .../fournisseur.commande.dispatch.class.php | 7 ++--- htdocs/fourn/commande/card.php | 2 +- htdocs/langs/en_US/admin.lang | 1 + htdocs/product/class/productbatch.class.php | 5 ++-- .../class/productcustomerprice.class.php | 10 +++---- .../class/propalmergepdfproduct.class.php | 5 ++-- .../product/stock/class/productlot.class.php | 9 +++--- .../class/productstockentrepot.class.php | 9 +++--- htdocs/projet/card.php | 2 +- htdocs/projet/class/project.class.php | 27 +++++++++--------- htdocs/projet/class/task.class.php | 5 ++-- htdocs/supplier_proposal/card.php | 2 +- .../class/supplier_proposal.class.php | 13 +++++---- htdocs/ticket/class/ticket.class.php | 9 +++--- htdocs/website/class/website.class.php | 2 +- 44 files changed, 138 insertions(+), 173 deletions(-) diff --git a/ChangeLog b/ChangeLog index b870df3e802..bbd12d6325c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -28,6 +28,7 @@ Following changes may create regressions for some external modules, but were nec * Files for variables of themes were renamed from graph-color.php into theme_vars.inc.php to match naming convention of extension .inc.php for files to be included. * All methods set_draft() were renamed into setDraft(). +* Signatures of methods createFromClone() has been standardized. All methods requires the object User as first parameter. * Removed deprecated function function test_sql_and_script_inject that was replaced with testSqlAndScriptInject. * Method load_measuring_units were renamed into selectMeasuringUnits and select_measuring_units was deprecated. * Hidden option CHANGE_ORDER_CONCAT_DESCRIPTION were renamed into MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION. diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index 03552557f86..3c985d325bc 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -1409,16 +1409,14 @@ class BookKeeping extends CommonObject /** * Load an object from its id and create a new one in database * - * @param int $fromid Id of object to clone - * - * @return int New id of clone + * @param User $user User making the clone + * @param int $fromid Id of object to clone + * @return int New id of clone */ - public function createFromClone($fromid) + public function createFromClone(User $user, $fromid) { dol_syslog(__METHOD__, LOG_DEBUG); - global $user; - $error = 0; $object = new BookKeeping($this->db); diff --git a/htdocs/admin/emailcollector_card.php b/htdocs/admin/emailcollector_card.php index f05bf937169..3d14d8fee2f 100644 --- a/htdocs/admin/emailcollector_card.php +++ b/htdocs/admin/emailcollector_card.php @@ -604,11 +604,14 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea if (empty($reshook)) { - print '' . $langs->trans("Edit") . '' . "\n"; + print ''; - print '' . $langs->trans("CollectNow") . '' . "\n"; + // Clone + print ''; - print '' . $langs->trans('Delete') . '' . "\n"; + print ''; + + print ''; } print '' . "\n"; } diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index 5654b3cb37f..61608b29f09 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -164,7 +164,7 @@ if ($action == 'confirm_clone' && $confirm == 'yes') reset($object->socpeopleassigned); $object->contactid = key($object->socpeopleassigned); } - $result = $object->createFromClone(GETPOST('fk_userowner'), GETPOST('socid')); + $result = $object->createFromClone($user, GETPOST('fk_userowner'), GETPOST('socid')); if ($result > 0) { header("Location: " . $_SERVER['PHP_SELF'] . '?id=' . $result); exit(); diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index 96aaa17fdd2..b543d6790c6 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -87,14 +87,14 @@ class ActionComm extends CommonObject * @var string Agenda event label */ public $label; - + /** * Date creation record (datec) * * @var integer */ public $datec; - + /** * Date modification record (tms) * @@ -129,14 +129,14 @@ class ActionComm extends CommonObject * @var int */ public $usermodid; - + /** * Date action start (datep) * * @var integer */ public $datep; - + /** * Date action end (datep2) * @@ -504,13 +504,13 @@ class ActionComm extends CommonObject /** * Load an object from its id and create a new one in database * - * @param user $fuser Object user making action + * @param User $fuser Object user making action * @param int $socid Id of thirdparty * @return int New id of clone */ - public function createFromClone($fuser, $socid) + public function createFromClone(User $fuser, $socid) { - global $db, $user, $langs, $conf, $hookmanager; + global $db, $conf, $hookmanager; $error=0; $now=dol_now(); @@ -529,20 +529,6 @@ class ActionComm extends CommonObject $this->id=0; - if (!is_object($fuser)) - { - if ($fuser > 0) - { - $u = new User($db); - $u->fetch($fuser); - $fuser = $u; - } - else - { - $fuser = $user; - } - } - // Create clone $this->context['createfromclone']='createfromclone'; $result=$this->create($fuser); diff --git a/htdocs/comm/mailing/card.php b/htdocs/comm/mailing/card.php index b710ba4656b..34ed7708e9e 100644 --- a/htdocs/comm/mailing/card.php +++ b/htdocs/comm/mailing/card.php @@ -97,7 +97,7 @@ if (empty($reshook)) } else { - $result=$object->createFromClone($object->id, $_REQUEST["clone_content"], $_REQUEST["clone_receivers"]); + $result=$object->createFromClone($user, $object->id, $_REQUEST["clone_content"], $_REQUEST["clone_receivers"]); if ($result > 0) { header("Location: ".$_SERVER['PHP_SELF'].'?id='.$result); diff --git a/htdocs/comm/mailing/class/mailing.class.php b/htdocs/comm/mailing/class/mailing.class.php index 0fd41c9dc02..d82ec07612d 100644 --- a/htdocs/comm/mailing/class/mailing.class.php +++ b/htdocs/comm/mailing/class/mailing.class.php @@ -266,14 +266,15 @@ class Mailing extends CommonObject /** * Load an object from its id and create a new one in database * + * @param User $user User making the clone * @param int $fromid Id of object to clone * @param int $option1 1=Copy content, 0=Forget content * @param int $option2 Not used * @return int New id of clone */ - public function createFromClone($fromid, $option1, $option2) + public function createFromClone(User $user, $fromid, $option1, $option2) { - global $user,$langs; + global $langs; $error=0; diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 419c8cf05dd..abed072bc2c 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -192,7 +192,7 @@ if (empty($reshook)) } } - $result = $object->createFromClone($socid); + $result = $object->createFromClone($user, $socid); if ($result > 0) { header("Location: " . $_SERVER['PHP_SELF'] . '?id=' . $result); exit(); diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index 388433222e0..0b9863f287b 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -473,7 +473,7 @@ class Propal extends CommonObject // Check parameters if ($type < 0) return -1; - + if ($date_start && $date_end && $date_start > $date_end) { $langs->load("errors"); $this->error=$langs->trans('ErrorStartDateGreaterEnd'); @@ -690,7 +690,7 @@ class Propal extends CommonObject if (empty($qty) && empty($special_code)) $special_code=3; // Set option tag if (! empty($qty) && $special_code == 3) $special_code=0; // Remove option tag if (empty($type)) $type=0; - + if ($date_start && $date_end && $date_start > $date_end) { $langs->load("errors"); $this->error=$langs->trans('ErrorStartDateGreaterEnd'); @@ -1226,12 +1226,13 @@ class Propal extends CommonObject /** * Load an object from its id and create a new one in database * - * @param int $socid Id of thirdparty - * @return int New id of clone + * @param User $user User making the clone + * @param int $socid Id of thirdparty + * @return int New id of clone */ - public function createFromClone($socid = 0) + public function createFromClone(User $user, $socid = 0) { - global $user,$conf,$hookmanager; + global $conf,$hookmanager; dol_include_once('/projet/class/project.class.php'); diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 9e48fd2303a..05d02c487c0 100755 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -142,7 +142,7 @@ if (empty($reshook)) // Because createFromClone modifies the object, we must clone it so that we can restore it later $orig = clone $object; - $result=$object->createFromClone($socid); + $result=$object->createFromClone($user, $socid); if ($result > 0) { header("Location: ".$_SERVER['PHP_SELF'].'?id='.$result); diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 5506d8a4770..35cb8335232 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -1070,10 +1070,11 @@ class Commande extends CommonOrder /** * Load an object from its id and create a new one in database * - * @param int $socid Id of thirdparty - * @return int New id of clone + * @param User $user User making the clone + * @param int $socid Id of thirdparty + * @return int New id of clone */ - public function createFromClone($socid = 0) + public function createFromClone(User $user, $socid = 0) { global $conf, $user,$hookmanager; diff --git a/htdocs/compta/bank/class/bankcateg.class.php b/htdocs/compta/bank/class/bankcateg.class.php index dc9c1d242e8..cb74bf54ca8 100644 --- a/htdocs/compta/bank/class/bankcateg.class.php +++ b/htdocs/compta/bank/class/bankcateg.class.php @@ -269,13 +269,12 @@ class BankCateg // extends CommonObject /** * Load an object from its id and create a new one in database * - * @param int $fromid Id of object to clone - * @return int New id of clone + * @param User $user User making the clone + * @param int $fromid Id of object to clone + * @return int New id of clone */ - public function createFromClone($fromid) + public function createFromClone(User $user, $fromid) { - global $user; - $error = 0; $object = new BankCateg($this->db); diff --git a/htdocs/compta/facture/class/paymentterm.class.php b/htdocs/compta/facture/class/paymentterm.class.php index 707b6586b83..d3b4bd83743 100644 --- a/htdocs/compta/facture/class/paymentterm.class.php +++ b/htdocs/compta/facture/class/paymentterm.class.php @@ -393,13 +393,12 @@ class PaymentTerm // extends CommonObject /** * Load an object from its id and create a new one in database * + * @param User $user User making the clone * @param int $fromid Id of object to clone * @return int New id of clone */ - public function createFromClone($fromid) + public function createFromClone(User $user, $fromid) { - global $user,$langs; - $error=0; $object=new PaymentTerm($this->db); diff --git a/htdocs/compta/sociales/class/cchargesociales.class.php b/htdocs/compta/sociales/class/cchargesociales.class.php index 1cb304fe519..3c2efbd6141 100644 --- a/htdocs/compta/sociales/class/cchargesociales.class.php +++ b/htdocs/compta/sociales/class/cchargesociales.class.php @@ -346,15 +346,14 @@ class Cchargesociales /** * Load an object from its id and create a new one in database * - * @param int $fromid Id of object to clone - * - * @return int New id of clone + * @param User $user User making the clone + * @param int $fromid Id of object to clone + * @return int New id of clone */ - public function createFromClone($fromid) + public function createFromClone(User $user, $fromid) { dol_syslog(__METHOD__, LOG_DEBUG); - global $user; $error = 0; $object = new Cchargesociales($this->db); diff --git a/htdocs/compta/sociales/class/paymentsocialcontribution.class.php b/htdocs/compta/sociales/class/paymentsocialcontribution.class.php index a2a6009cd6a..86dda559061 100644 --- a/htdocs/compta/sociales/class/paymentsocialcontribution.class.php +++ b/htdocs/compta/sociales/class/paymentsocialcontribution.class.php @@ -448,13 +448,12 @@ class PaymentSocialContribution extends CommonObject /** * Load an object from its id and create a new one in database * + * @param User $user User making the clone * @param int $fromid Id of object to clone * @return int New id of clone */ - public function createFromClone($fromid) + public function createFromClone(User $user, $fromid) { - global $user,$langs; - $error=0; $object=new PaymentSocialContribution($this->db); diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 443cf984f79..687dc2c7f2f 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -1072,7 +1072,7 @@ if (empty($reshook)) else { if ($object->id > 0) { - $result = $object->createFromClone($socid); + $result = $object->createFromClone($user, $socid); if ($result > 0) { header("Location: " . $_SERVER['PHP_SELF'] . '?id=' . $result); exit(); diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 2cd4f472f95..87830593714 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -2388,13 +2388,14 @@ class Contrat extends CommonObject /** * Load an object from its id and create a new one in database * - * @param int $socid Id of thirdparty - * @param int $notrigger 1=Does not execute triggers, 0= execute triggers - * @return int New id of clone + * @param User $user User making the clone + * @param int $socid Id of thirdparty + * @param int $notrigger 1=Does not execute triggers, 0= execute triggers + * @return int New id of clone */ - public function createFromClone($socid = 0, $notrigger = 0) + public function createFromClone(User $user, $socid = 0, $notrigger = 0) { - global $db, $user, $langs, $conf, $hookmanager, $extrafields; + global $db, $langs, $conf, $hookmanager, $extrafields; dol_include_once('/projet/class/project.class.php'); diff --git a/htdocs/core/actions_addupdatedelete.inc.php b/htdocs/core/actions_addupdatedelete.inc.php index 5c5e7752b49..3bd33c94c15 100644 --- a/htdocs/core/actions_addupdatedelete.inc.php +++ b/htdocs/core/actions_addupdatedelete.inc.php @@ -195,23 +195,6 @@ if ($action == 'confirm_delete' && ! empty($permissiontodelete)) } } -// Action clone object -if ($action == 'confirm_clone' && $confirm == 'yes' && $permissiontoadd) -{ - $objectutil = dol_clone($object); // To avoid to denaturate loaded object when setting some properties for clone - //$objectutil->date = dol_mktime(12, 0, 0, GETPOST('newdatemonth', 'int'), GETPOST('newdateday', 'int'), GETPOST('newdateyear', 'int')); - - $result = $objectutil->createFromClone($id); - if ($result > 0) { - header("Location: " . $_SERVER['PHP_SELF'] . '?facid=' . $result); - exit(); - } else { - $langs->load("errors"); - setEventMessages($objectutil->error, $objectutil->errors, 'errors'); - $action = ''; - } -} - // Action clone object if ($action == 'confirm_clone' && $confirm == 'yes' && $permissiontoadd) { diff --git a/htdocs/core/class/ctyperesource.class.php b/htdocs/core/class/ctyperesource.class.php index a4eed8f8b66..0571af1d5fa 100644 --- a/htdocs/core/class/ctyperesource.class.php +++ b/htdocs/core/class/ctyperesource.class.php @@ -404,15 +404,14 @@ class Ctyperesource /** * Load an object from its id and create a new one in database * - * @param int $fromid Id of object to clone - * - * @return int New id of clone + * @param User $user User making the clone + * @param int $fromid Id of object to clone + * @return int New id of clone */ - public function createFromClone($fromid) + public function createFromClone(User $user, $fromid) { dol_syslog(__METHOD__, LOG_DEBUG); - global $user; $error = 0; $object = new Ctyperesource($this->db); diff --git a/htdocs/core/modules/modEmailCollector.class.php b/htdocs/core/modules/modEmailCollector.class.php index 2ca7ac73f08..b3daf4ade09 100644 --- a/htdocs/core/modules/modEmailCollector.class.php +++ b/htdocs/core/modules/modEmailCollector.class.php @@ -64,7 +64,7 @@ class modEmailCollector extends DolibarrModules $this->descriptionlong = "EmailCollectorDescription"; // Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated' or a version string like 'x.y.z' - $this->version = 'experimental'; + $this->version = 'dolibarr'; // Key used in llx_const table to save module status enabled/disabled (where DAV is value of property name of module in uppercase) $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); // Name of image file used for this module. diff --git a/htdocs/cron/class/cronjob.class.php b/htdocs/cron/class/cronjob.class.php index 2caba932e40..4345385f16d 100644 --- a/htdocs/cron/class/cronjob.class.php +++ b/htdocs/cron/class/cronjob.class.php @@ -736,13 +736,12 @@ class Cronjob extends CommonObject /** * Load an object from its id and create a new one in database * + * @param User $user User making the clone * @param int $fromid Id of object to clone * @return int New id of clone */ - public function createFromClone($fromid) + public function createFromClone(User $user, $fromid) { - global $user,$langs; - $error=0; $object=new Cronjob($this->db); diff --git a/htdocs/don/class/paymentdonation.class.php b/htdocs/don/class/paymentdonation.class.php index 4ec7c4aa874..b96719e01aa 100644 --- a/htdocs/don/class/paymentdonation.class.php +++ b/htdocs/don/class/paymentdonation.class.php @@ -408,13 +408,12 @@ class PaymentDonation extends CommonObject /** * Load an object from its id and create a new one in database * + * @param User $user User making the clone * @param int $fromid Id of object to clone * @return int New id of clone */ - public function createFromClone($fromid) + public function createFromClone(User $user, $fromid) { - global $user,$langs; - $error=0; $object=new PaymentDonation($this->db); diff --git a/htdocs/ecm/class/ecmfiles.class.php b/htdocs/ecm/class/ecmfiles.class.php index 4f4c8dfea61..57a18f5c339 100644 --- a/htdocs/ecm/class/ecmfiles.class.php +++ b/htdocs/ecm/class/ecmfiles.class.php @@ -707,15 +707,14 @@ class EcmFiles extends CommonObject /** * Load an object from its id and create a new one in database * - * @param int $fromid Id of object to clone - * - * @return int New id of clone + * @param User $user User making the clone + * @param int $fromid Id of object to clone + * @return int New id of clone */ - public function createFromClone($fromid) + public function createFromClone(User $user, $fromid) { dol_syslog(__METHOD__, LOG_DEBUG); - global $user; $error = 0; $object = new Ecmfiles($this->db); diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index 48535ba8f48..e6354c01105 100644 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -171,7 +171,7 @@ if (empty($reshook)) // Because createFromClone modifies the object, we must clone it so that we can restore it later if it fails $orig = clone $object; - $result=$object->createFromClone(GETPOST('fk_user_author', 'int')); + $result=$object->createFromClone($user, GETPOST('fk_user_author', 'int')); if ($result > 0) { header("Location: ".$_SERVER['PHP_SELF'].'?id='.$result); diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php index 55a411cf1c7..c09d2897980 100644 --- a/htdocs/expensereport/class/expensereport.class.php +++ b/htdocs/expensereport/class/expensereport.class.php @@ -314,12 +314,13 @@ class ExpenseReport extends CommonObject /** * Load an object from its id and create a new one in database * - * @param int $fk_user_author Id of new user - * @return int New id of clone + * @param User $user User making the clone + * @param int $fk_user_author Id of new user + * @return int New id of clone */ - public function createFromClone($fk_user_author) + public function createFromClone(User $user, $fk_user_author) { - global $user,$hookmanager; + global $hookmanager; $error=0; diff --git a/htdocs/expensereport/class/paymentexpensereport.class.php b/htdocs/expensereport/class/paymentexpensereport.class.php index f731638ea1d..deec87887d7 100644 --- a/htdocs/expensereport/class/paymentexpensereport.class.php +++ b/htdocs/expensereport/class/paymentexpensereport.class.php @@ -414,13 +414,12 @@ class PaymentExpenseReport extends CommonObject /** * Load an object from its id and create a new one in database * + * @param User $user User making the clone * @param int $fromid Id of object to clone * @return int New id of clone */ - public function createFromClone($fromid) + public function createFromClone(User $user, $fromid) { - global $user,$langs; - $error=0; $object=new PaymentExpenseReport($this->db); diff --git a/htdocs/fichinter/card.php b/htdocs/fichinter/card.php index 47e7dd48589..20d9d786354 100644 --- a/htdocs/fichinter/card.php +++ b/htdocs/fichinter/card.php @@ -134,7 +134,7 @@ if (empty($reshook)) // Because createFromClone modifies the object, we must clone it so that we can restore it later $orig = clone $object; - $result=$object->createFromClone($socid); + $result=$object->createFromClone($user, $socid); if ($result > 0) { header("Location: ".$_SERVER['PHP_SELF'].'?id='.$result); diff --git a/htdocs/fichinter/class/fichinter.class.php b/htdocs/fichinter/class/fichinter.class.php index db0ae47f7d2..807b547a4bc 100644 --- a/htdocs/fichinter/class/fichinter.class.php +++ b/htdocs/fichinter/class/fichinter.class.php @@ -1144,12 +1144,13 @@ class Fichinter extends CommonObject /** * Load an object from its id and create a new one in database * - * @param int $socid Id of thirdparty - * @return int New id of clone + * @param User $user User making the clone + * @param int $socid Id of thirdparty + * @return int New id of clone */ - public function createFromClone($socid = 0) + public function createFromClone(User $user, $socid = 0) { - global $user,$hookmanager; + global $hookmanager; $error=0; diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index f29fab91e45..f1910c5ab38 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -1409,11 +1409,12 @@ class CommandeFournisseur extends CommonOrder /** * Load an object from its id and create a new one in database * - * @return int New id of clone + * @param User $user User making the clone + * @return int New id of clone */ - public function createFromClone() + public function createFromClone(User $user) { - global $conf,$user,$langs,$hookmanager; + global $hookmanager; $error=0; diff --git a/htdocs/fourn/class/fournisseur.commande.dispatch.class.php b/htdocs/fourn/class/fournisseur.commande.dispatch.class.php index 6db4607573c..14c114efdbf 100644 --- a/htdocs/fourn/class/fournisseur.commande.dispatch.class.php +++ b/htdocs/fourn/class/fournisseur.commande.dispatch.class.php @@ -472,13 +472,12 @@ class CommandeFournisseurDispatch extends CommonObject /** * Load an object from its id and create a new one in database * - * @param int $fromid Id of object to clone + * @param User $user User making the clone + * @param int $fromid Id of object to clone * @return int New id of clone */ - public function createFromClone($fromid) + public function createFromClone(User $user, $fromid) { - global $user,$langs; - $error=0; $object=new Commandefournisseurdispatch($this->db); diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index 7ce9a57f92b..876265d8dcb 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -955,7 +955,7 @@ $result = $object->updateline( { if ($object->id > 0) { - $result=$object->createFromClone(); + $result=$object->createFromClone($user); if ($result > 0) { header("Location: ".$_SERVER['PHP_SELF'].'?id='.$result); diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index d884278028f..24453159a23 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1829,6 +1829,7 @@ MailboxSourceDirectory=Mailbox source directory MailboxTargetDirectory=Mailbox target directory EmailcollectorOperations=Operations to do by collector CollectNow=Collect now +ConfirmCloneEmailCollector=Are you sure you want to clone the Email collector %s ? DateLastCollectResult=Date latest collect tried DateLastcollectResultOk=Date latest collect successfull LastResult=Latest result diff --git a/htdocs/product/class/productbatch.class.php b/htdocs/product/class/productbatch.class.php index aac30bce813..4b1e5232abb 100644 --- a/htdocs/product/class/productbatch.class.php +++ b/htdocs/product/class/productbatch.class.php @@ -327,13 +327,12 @@ class Productbatch extends CommonObject /** * Load an object from its id and create a new one in database * + * @param User $user User making the clone * @param int $fromid Id of object to clone * @return int New id of clone */ - public function createFromClone($fromid) + public function createFromClone(User $user, $fromid) { - global $user,$langs; - $error=0; $object=new Productbatch($this->db); diff --git a/htdocs/product/class/productcustomerprice.class.php b/htdocs/product/class/productcustomerprice.class.php index 424cb8ce39b..8405120ddef 100644 --- a/htdocs/product/class/productcustomerprice.class.php +++ b/htdocs/product/class/productcustomerprice.class.php @@ -895,14 +895,12 @@ class Productcustomerprice extends CommonObject /** * Load an object from its id and create a new one in database * - * @param int $fromid of object to clone - * @return int id of clone + * @param User $user User making the clone + * @param int $fromid ID of object to clone + * @return int id of clone */ - public function createFromClone($fromid) + public function createFromClone(User $user, $fromid) { - - global $user, $langs; - $error = 0; $object = new Productcustomerprice($this->db); diff --git a/htdocs/product/class/propalmergepdfproduct.class.php b/htdocs/product/class/propalmergepdfproduct.class.php index 0882490446d..2d350eb0c77 100644 --- a/htdocs/product/class/propalmergepdfproduct.class.php +++ b/htdocs/product/class/propalmergepdfproduct.class.php @@ -560,13 +560,12 @@ class Propalmergepdfproduct extends CommonObject /** * Load an object from its id and create a new one in database * + * @param User $user User making the clone * @param int $fromid Id of object to clone * @return int New id of clone */ - public function createFromClone($fromid) + public function createFromClone(User $user, $fromid) { - global $user,$langs; - $error=0; $object=new Propalmergepdfproduct($this->db); diff --git a/htdocs/product/stock/class/productlot.class.php b/htdocs/product/stock/class/productlot.class.php index 9dc1856c64e..f3cec8f9a98 100644 --- a/htdocs/product/stock/class/productlot.class.php +++ b/htdocs/product/stock/class/productlot.class.php @@ -426,15 +426,14 @@ class Productlot extends CommonObject /** * Load an object from its id and create a new one in database * - * @param int $fromid Id of object to clone - * - * @return int New id of clone + * @param User $user User making the clone + * @param int $fromid Id of object to clone + * @return int New id of clone */ - public function createFromClone($fromid) + public function createFromClone(User $user, $fromid) { dol_syslog(__METHOD__, LOG_DEBUG); - global $user; $error = 0; $object = new Productlot($this->db); diff --git a/htdocs/product/stock/class/productstockentrepot.class.php b/htdocs/product/stock/class/productstockentrepot.class.php index 36e302bf661..0cbedb6d347 100644 --- a/htdocs/product/stock/class/productstockentrepot.class.php +++ b/htdocs/product/stock/class/productstockentrepot.class.php @@ -420,15 +420,14 @@ class ProductStockEntrepot extends CommonObject /** * Load an object from its id and create a new one in database * - * @param int $fromid Id of object to clone - * - * @return int New id of clone + * @param User $user User making the clone + * @param int $fromid Id of object to clone + * @return int New id of clone */ - public function createFromClone($fromid) + public function createFromClone(User $user, $fromid) { dol_syslog(__METHOD__, LOG_DEBUG); - global $user; $error = 0; $object = new ProductStockEntrepot($this->db); diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index 7023f2d871e..c1e40b9ffec 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -429,7 +429,7 @@ if (empty($reshook)) $move_date=GETPOST('move_date')?1:0; $clone_thirdparty=GETPOST('socid', 'int')?GETPOST('socid', 'int'):0; - $result=$object->createFromClone($object->id, $clone_contacts, $clone_tasks, $clone_project_files, $clone_task_files, $clone_notes, $move_date, 0, $clone_thirdparty); + $result=$object->createFromClone($user, $object->id, $clone_contacts, $clone_tasks, $clone_project_files, $clone_task_files, $clone_notes, $move_date, 0, $clone_thirdparty); if ($result <= 0) { setEventMessages($object->error, $object->errors, 'errors'); diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index 59d24e5eb3d..09eadbbc8ea 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -1274,20 +1274,21 @@ class Project extends CommonObject /** * Load an object from its id and create a new one in database * - * @param int $fromid Id of object to clone - * @param bool $clone_contact Clone contact of project - * @param bool $clone_task Clone task of project - * @param bool $clone_project_file Clone file of project - * @param bool $clone_task_file Clone file of task (if task are copied) - * @param bool $clone_note Clone note of project - * @param bool $move_date Move task date on clone - * @param integer $notrigger No trigger flag - * @param int $newthirdpartyid New thirdparty id - * @return int New id of clone + * @param User $user User making the clone + * @param int $fromid Id of object to clone + * @param bool $clone_contact Clone contact of project + * @param bool $clone_task Clone task of project + * @param bool $clone_project_file Clone file of project + * @param bool $clone_task_file Clone file of task (if task are copied) + * @param bool $clone_note Clone note of project + * @param bool $move_date Move task date on clone + * @param integer $notrigger No trigger flag + * @param int $newthirdpartyid New thirdparty id + * @return int New id of clone */ - public function createFromClone($fromid, $clone_contact = false, $clone_task = true, $clone_project_file = false, $clone_task_file = false, $clone_note = true, $move_date = true, $notrigger = 0, $newthirdpartyid = 0) + public function createFromClone(User $user, $fromid, $clone_contact = false, $clone_task = true, $clone_project_file = false, $clone_task_file = false, $clone_note = true, $move_date = true, $notrigger = 0, $newthirdpartyid = 0) { - global $user,$langs,$conf; + global $langs,$conf; $error=0; @@ -1477,7 +1478,7 @@ class Project extends CommonObject // Loop on each task, to clone it foreach ($tasksarray as $tasktoclone) { - $result_clone = $taskstatic->createFromClone($tasktoclone->id, $clone_project_id, $tasktoclone->fk_parent, $move_date, true, false, $clone_task_file, true, false); + $result_clone = $taskstatic->createFromClone($user, $tasktoclone->id, $clone_project_id, $tasktoclone->fk_parent, $move_date, true, false, $clone_task_file, true, false); if ($result_clone <= 0) { $this->error.=$result_clone->error; diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php index 8c12131ce50..a5f63e32826 100644 --- a/htdocs/projet/class/task.class.php +++ b/htdocs/projet/class/task.class.php @@ -1587,6 +1587,7 @@ class Task extends CommonObject /** Load an object from its id and create a new one in database * + * @param User $user User making the clone * @param int $fromid Id of object to clone * @param int $project_id Id of project to attach clone task * @param int $parent_task_id Id of task to attach clone task @@ -1598,9 +1599,9 @@ class Task extends CommonObject * @param bool $clone_prog clone progress of project * @return int New id of clone */ - public function createFromClone($fromid, $project_id, $parent_task_id, $clone_change_dt = false, $clone_affectation = false, $clone_time = false, $clone_file = false, $clone_note = false, $clone_prog = false) + public function createFromClone(User $user, $fromid, $project_id, $parent_task_id, $clone_change_dt = false, $clone_affectation = false, $clone_time = false, $clone_file = false, $clone_note = false, $clone_prog = false) { - global $user,$langs,$conf; + global $langs,$conf; $error=0; diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index 1701a95af73..59df170c9ef 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -136,7 +136,7 @@ if (empty($reshook)) else { if ($object->id > 0) { - $result = $object->createFromClone($socid); + $result = $object->createFromClone($user, $socid); if ($result > 0) { header("Location: " . $_SERVER['PHP_SELF'] . '?id=' . $result); exit(); diff --git a/htdocs/supplier_proposal/class/supplier_proposal.class.php b/htdocs/supplier_proposal/class/supplier_proposal.class.php index 0b72b7daf2c..ca16348dcd6 100644 --- a/htdocs/supplier_proposal/class/supplier_proposal.class.php +++ b/htdocs/supplier_proposal/class/supplier_proposal.class.php @@ -1117,12 +1117,13 @@ class SupplierProposal extends CommonObject /** * Load an object from its id and create a new one in database * - * @param int $socid Id of thirdparty - * @return int New id of clone + * @param User $user User making the clone + * @param int $fromid Id of thirdparty + * @return int New id of clone */ - public function createFromClone($socid = 0) + public function createFromClone(User $user, $fromid = 0) { - global $user,$langs,$conf,$hookmanager; + global $conf,$hookmanager; $error=0; $now=dol_now(); @@ -1139,9 +1140,9 @@ class SupplierProposal extends CommonObject $objsoc=new Societe($this->db); // Change socid if needed - if (! empty($socid) && $socid != $this->socid) + if (! empty($fromid) && $fromid != $this->socid) { - if ($objsoc->fetch($socid) > 0) + if ($objsoc->fetch($fromid) > 0) { $this->socid = $objsoc->id; $this->cond_reglement_id = (! empty($objsoc->cond_reglement_id) ? $objsoc->cond_reglement_id : 0); diff --git a/htdocs/ticket/class/ticket.class.php b/htdocs/ticket/class/ticket.class.php index 0c2cc91dea4..cab2eab92ed 100644 --- a/htdocs/ticket/class/ticket.class.php +++ b/htdocs/ticket/class/ticket.class.php @@ -950,13 +950,12 @@ class Ticket extends CommonObject /** * Load an object from its id and create a new one in database * - * @param int $fromid Id of object to clone - * @return int New id of clone + * @param User $user User that clone + * @param int $fromid Id of object to clone + * @return int New id of clone */ - public function createFromClone($fromid) + public function createFromClone(User $user, $fromid) { - global $user, $langs; - $error = 0; $object = new Ticket($this->db); diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index 6bbfb6ac472..a12bb2ebf11 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -519,7 +519,7 @@ class Website extends CommonObject */ public function createFromClone($user, $fromid, $newref, $newlang = '') { - global $conf, $hookmanager, $langs; + global $conf, $hookmanager; global $dolibarr_main_data_root; $now = dol_now(); From 31897f54ac24b267924f5ced5cc3ce0037daecd1 Mon Sep 17 00:00:00 2001 From: gauthier Date: Thu, 25 Apr 2019 12:37:05 +0200 Subject: [PATCH 030/132] Fix prev situation invoice selection (backport fix 8.0) --- 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 4efedc2544e..92a999463f8 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -3242,7 +3242,7 @@ class Form if ($obj->situation_final != 1) { //Not prov? if (substr($obj->facnumber, 1, 4) != 'PROV') { - if ($selected == $obj->situation_final) { + if ($selected == $obj->rowid) { $opt .= ''; } else { $opt .= ''; From 2968921f877a7eb6fb2c64b6f1f1b288b017191b Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Thu, 25 Apr 2019 13:12:33 +0200 Subject: [PATCH 031/132] Fix display type in subscription --- htdocs/adherents/subscription.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/htdocs/adherents/subscription.php b/htdocs/adherents/subscription.php index 39466e8ae8a..9961471fdd6 100644 --- a/htdocs/adherents/subscription.php +++ b/htdocs/adherents/subscription.php @@ -5,6 +5,7 @@ * Copyright (C) 2012-2017 Regis Houssin * Copyright (C) 2015-2016 Alexandre Spangaro * Copyright (C) 2018 Frédéric France + * Copyright (C) 2019 Thibault FOUCART * * 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 @@ -668,7 +669,7 @@ if ($rowid > 0) { $sql = "SELECT d.rowid, d.firstname, d.lastname, d.societe,"; $sql.= " c.rowid as crowid, c.subscription,"; - $sql.= " c.datec,"; + $sql.= " c.datec, c.fk_type as cfk_type,"; $sql.= " c.dateadh as dateh,"; $sql.= " c.datef,"; $sql.= " c.fk_bank,"; @@ -693,6 +694,7 @@ if ($rowid > 0) print '
'.$langs->trans("DateCreation").''.$langs->trans("Type").''.$langs->trans("DateStart").''.$langs->trans("DateEnd").''.$langs->trans("Amount").'
'.$subscriptionstatic->getNomUrl(1).''.dol_print_date($db->jdate($objp->datec), 'dayhour')."'; + if ( ! empty($objp->cfk_type) ) print $adht->getNomUrl(1); + print ''.dol_print_date($db->jdate($objp->dateh), 'day')."'.dol_print_date($db->jdate($objp->datef), 'day')."'.price($objp->subscription).'
'.$subscriptionstatic->getNomUrl(1).''.dol_print_date($db->jdate($objp->datec), 'dayhour')."'; - if ( ! empty($objp->cfk_type) ) print $adht->getNomUrl(1); + if ($objp->cfk_type > 0) + { + print $adht->getNomUrl(1); + } print ''.dol_print_date($db->jdate($objp->dateh), 'day')."'.dol_print_date($db->jdate($objp->datef), 'day')."
'; $arrayoftypes=array( - 'from'=>array('label'=>'MailFrom', 'data-placeholder'=>'SearchString'), - 'to'=>array('label'=>'MailTo', 'data-placeholder'=>'SearchString'), - 'cc'=>array('label'=>'Cc', 'data-placeholder'=>'SearchString'), - 'bcc'=>array('label'=>'Bcc', 'data-placeholder'=>'SearchString'), - 'subject'=>array('label'=>'Subject', 'data-placeholder'=>'SearchString'), - 'body'=>array('label'=>'Body', 'data-placeholder'=>'SearchString'), - 'header'=>array('label'=>'Header', 'data-placeholder'=>'HeaderKey SearchString'), // HEADER key value - 'X1'=>'---', + 'from'=>array('label'=>'MailFrom', 'data-placeholder'=>$langs->trans('SearchString')), + 'to'=>array('label'=>'MailTo', 'data-placeholder'=>$langs->trans('SearchString')), + 'cc'=>array('label'=>'Cc', 'data-placeholder'=>$langs->trans('SearchString')), + 'bcc'=>array('label'=>'Bcc', 'data-placeholder'=>$langs->trans('SearchString')), + 'subject'=>array('label'=>'Subject', 'data-placeholder'=>$langs->trans('SearchString')), + 'body'=>array('label'=>'Body', 'data-placeholder'=>$langs->trans('SearchString')), + // disabled because PHP imap_search is not compatible IMAPv4, only IMAPv2 + //'header'=>array('label'=>'Header', 'data-placeholder'=>'HeaderKey SearchString'), // HEADER key value + //'X1'=>'---', + //'notinsubject'=>array('label'=>'SubjectNotIn', 'data-placeholder'=>'SearchString'), + //'notinbody'=>array('label'=>'BodyNotIn', 'data-placeholder'=>'SearchString'), + 'X2'=>'---', 'seen'=>array('label'=>'AlreadyRead', 'data-noparam'=>1), 'unseen'=>array('label'=>'NotRead', 'data-noparam'=>1), - 'smaller'=>array('label'=>'SmallerThan', 'data-placeholder'=>'NumberOfBytes'), - 'larger'=>array('label'=>'LargerThan', 'data-placeholder'=>'NumberOfBytes'), - 'X2'=>'---', + 'unanswered'=>array('label'=>'Unanswered', 'data-noparam'=>1), + 'answered'=>array('label'=>'Answered', 'data-noparam'=>1), + 'smaller'=>array('label'=>'SmallerThan', 'data-placeholder'=>$langs->trans('NumberOfBytes')), + 'larger'=>array('label'=>'LargerThan', 'data-placeholder'=>$langs->trans('NumberOfBytes')), + 'X3'=>'---', 'withtrackingid'=>array('label'=>'WithDolTrackingID', 'data-noparam'=>1), 'withouttrackingid'=>array('label'=>'WithoutDolTrackingID', 'data-noparam'=>1) ); @@ -530,7 +536,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea 'recordevent'=>'RecordEvent'); if ($conf->projet->enabled) $arrayoftypes['project']='CreateLeadAndThirdParty'; if ($conf->ticket->enabled) $arrayoftypes['ticket']='CreateTicketAndThirdParty'; - print $form->selectarray('operationtype', $arrayoftypes, '', 1, 0, 0, '', 1); + print $form->selectarray('operationtype', $arrayoftypes, '', 1, 0, 0, '', 1, 0, 0, '', 'maxwidth300'); print ''; print ''; $htmltext=$langs->transnoentitiesnoconv("OperationParamDesc"); diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 16532cfd76f..4c0b15c8d46 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -6107,6 +6107,7 @@ $substitutionarray=array_merge($substitutionarray, array( { $substitutionarray['__DOL_MAIN_URL_ROOT__']=DOL_MAIN_URL_ROOT; $substitutionarray['__(AnyTranslationKey)__']=$outputlangs->trans('TranslationOfKey'); + $substitutionarray['__(AnyTranslationKey|langfile)__']=$outputlangs->trans('TranslationOfKey').' (load also language file before)'; $substitutionarray['__[AnyConstantKey]__']=$outputlangs->trans('ValueOfConstantKey'); } @@ -6135,7 +6136,7 @@ function make_substitutions($text, $substitutionarray, $outputlangs = null) if (empty($outputlangs)) $outputlangs=$langs; - // Make substitution for language keys + // Make substitution for language keys: __(AnyTranslationKey)__ or __(AnyTranslationKey|langfile)__ if (is_object($outputlangs)) { while (preg_match('/__\(([^\)]+)\)__/', $text, $reg)) @@ -6151,8 +6152,8 @@ function make_substitutions($text, $substitutionarray, $outputlangs = null) } } - // Make substitution for constant keys. Must be after the substitution of translation, so if text of translation contains a constant, - // it is also converted. + // Make substitution for constant keys. + // Must be after the substitution of translation, so if the text of translation contains a string __[xxx]__, it is also converted. while (preg_match('/__\[([^\]]+)\]__/', $text, $reg)) { $msgishtml = 0; diff --git a/htdocs/core/tpl/commonfields_view.tpl.php b/htdocs/core/tpl/commonfields_view.tpl.php index 8e04f22166b..129c1a70575 100644 --- a/htdocs/core/tpl/commonfields_view.tpl.php +++ b/htdocs/core/tpl/commonfields_view.tpl.php @@ -49,7 +49,7 @@ foreach($object->fields as $key => $val) print '
'.$subscriptionstatic->getNomUrl(1).''.dol_print_date($db->jdate($objp->datec), 'dayhour')."'; - if ($objp->cfk_type > 0) + if ($objp->cfk_type > 0) { print $adht->getNomUrl(1); } diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 536e40fb3c6..04f64a78280 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -1820,7 +1820,8 @@ class EmailCollector extends CommonObject * @param string $mid prefix * @return array Array with number and object */ - function getmsg($mbox, $mid) { + private function getmsg($mbox, $mid) + { // input $mbox = IMAP stream, $mid = message id // output all the following: global $charset,$htmlmsg,$plainmsg,$attachments; @@ -1832,10 +1833,10 @@ class EmailCollector extends CommonObject // add code here to get date, from, to, cc, subject... // BODY - $s = imap_fetchstructure($mbox,$mid); + $s = imap_fetchstructure($mbox, $mid); if (!$s->parts) // simple - $this->getpart($mbox,$mid,$s,0); // pass 0 as part-number + $this->getpart($mbox, $mid, $s, 0); // pass 0 as part-number else { // multipart: cycle through each part foreach ($s->parts as $partno0=>$p) { @@ -1868,14 +1869,15 @@ class EmailCollector extends CommonObject * @param string $partno Partno * @return void */ - private function getpart($mbox, $mid, $p, $partno) { + private function getpart($mbox, $mid, $p, $partno) + { // $partno = '1', '2', '2.1', '2.1.3', etc for multipart, 0 if simple global $htmlmsg,$plainmsg,$charset,$attachments; // DECODE DATA $data = ($partno)? - imap_fetchbody($mbox,$mid,$partno): // multipart - imap_body($mbox,$mid); // simple + imap_fetchbody($mbox, $mid, $partno): // multipart + imap_body($mbox, $mid); // simple // Any part may be encoded, even plain text messages, so check everything. if ($p->encoding==4) $data = quoted_printable_decode($data); @@ -1934,7 +1936,7 @@ class EmailCollector extends CommonObject if ($p->parts) { foreach ($p->parts as $partno0=>$p2) { - $this->getpart($mbox,$mid,$p2,$partno.'.'.($partno0+1)); // 1.2, 1.2.1, etc. + $this->getpart($mbox, $mid, $p2, $partno.'.'.($partno0+1)); // 1.2, 1.2.1, etc. } } } From 01075081cbcd9130a72115cdb50ee61fc394edc1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 25 Apr 2019 22:25:19 +0200 Subject: [PATCH 038/132] FIX CVE-2019-11200 --- htdocs/admin/tools/dolibarr_export.php | 2 +- htdocs/admin/tools/export.php | 3 +- htdocs/core/class/utils.class.php | 38 ++++++++++++++------------ 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/htdocs/admin/tools/dolibarr_export.php b/htdocs/admin/tools/dolibarr_export.php index 55be556afb9..231699dc636 100644 --- a/htdocs/admin/tools/dolibarr_export.php +++ b/htdocs/admin/tools/dolibarr_export.php @@ -50,7 +50,7 @@ if (! $user->admin) if ($action == 'delete') { - $file=$conf->admin->dir_output.'/'.GETPOST('urlfile'); + $file=$conf->admin->dir_output.'/backup/'.basename(GETPOST('urlfile', 'alpha')); $ret=dol_delete_file($file, 1); if ($ret) setEventMessages($langs->trans("FileWasRemoved", GETPOST('urlfile')), null, 'mesgs'); else setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), null, 'errors'); diff --git a/htdocs/admin/tools/export.php b/htdocs/admin/tools/export.php index 5bfacc6c4f0..5697e48e07f 100644 --- a/htdocs/admin/tools/export.php +++ b/htdocs/admin/tools/export.php @@ -133,7 +133,8 @@ if ($what == 'mysql') dol_syslog("Command are restricted to ".$dolibarr_main_restrict_os_commands.". We check that one of this command is inside ".$cmddump); foreach($arrayofallowedcommand as $allowedcommand) { - if (preg_match('/'.preg_quote($allowedcommand,'/').'/', $cmddump)) + $basenamecmddump=basename($cmddump); + if (preg_match('/^'.preg_quote($allowedcommand,'/').'$/', $basenamecmddump)) // the provided command $cmddump must be an allowed command { $ok=1; break; diff --git a/htdocs/core/class/utils.class.php b/htdocs/core/class/utils.class.php index 8c051c85b33..3d43a319e51 100644 --- a/htdocs/core/class/utils.class.php +++ b/htdocs/core/class/utils.class.php @@ -239,36 +239,37 @@ class Utils dol_mkdir($conf->admin->dir_output.'/backup'); // Parameteres execution - $command=$cmddump; - if (preg_match("/\s/",$command)) $command=escapeshellarg($command); // Use quotes on command + $command = $cmddump; + $command = preg_replace('/(\$|%)/', '', $command); // We removed chars that can be used to inject vars that contains space inside path of command without seeing there is a space to bypass the escapeshellarg. + if (preg_match("/\s/",$command)) $command=escapeshellarg($command); // If there is spaces, we add quotes on command to be sure $command is only a program and not a program+parameters //$param=escapeshellarg($dolibarr_main_db_name)." -h ".escapeshellarg($dolibarr_main_db_host)." -u ".escapeshellarg($dolibarr_main_db_user)." -p".escapeshellarg($dolibarr_main_db_pass); $param=$dolibarr_main_db_name." -h ".$dolibarr_main_db_host; $param.=" -u ".$dolibarr_main_db_user; if (! empty($dolibarr_main_db_port)) $param.=" -P ".$dolibarr_main_db_port; - if (! GETPOST("use_transaction")) $param.=" -l --single-transaction"; - if (GETPOST("disable_fk") || $usedefault) $param.=" -K"; - if (GETPOST("sql_compat") && GETPOST("sql_compat") != 'NONE') $param.=" --compatible=".escapeshellarg(GETPOST("sql_compat","alpha")); - if (GETPOST("drop_database")) $param.=" --add-drop-database"; - if (GETPOST("sql_structure") || $usedefault) + if (! GETPOST("use_transaction", "alpha")) $param.=" -l --single-transaction"; + if (GETPOST("disable_fk", "alpha") || $usedefault) $param.=" -K"; + if (GETPOST("sql_compat", "alpha") && GETPOST("sql_compat", "alpha") != 'NONE') $param.=" --compatible=".escapeshellarg(GETPOST("sql_compat", "alpha")); + if (GETPOST("drop_database", "alpha")) $param.=" --add-drop-database"; + if (GETPOST("sql_structure", "alpha") || $usedefault) { - if (GETPOST("drop") || $usedefault) $param.=" --add-drop-table=TRUE"; - else $param.=" --add-drop-table=FALSE"; + if (GETPOST("drop", "alpha") || $usedefault) $param.=" --add-drop-table=TRUE"; + else $param.=" --add-drop-table=FALSE"; } else { $param.=" -t"; } - if (GETPOST("disable-add-locks")) $param.=" --add-locks=FALSE"; - if (GETPOST("sql_data") || $usedefault) + if (GETPOST("disable-add-locks", "alpha")) $param.=" --add-locks=FALSE"; + if (GETPOST("sql_data", "alpha") || $usedefault) { $param.=" --tables"; - if (GETPOST("showcolumns") || $usedefault) $param.=" -c"; - if (GETPOST("extended_ins") || $usedefault) $param.=" -e"; + if (GETPOST("showcolumns", "alpha") || $usedefault) $param.=" -c"; + if (GETPOST("extended_ins", "alpha") || $usedefault) $param.=" -e"; else $param.=" --skip-extended-insert"; - if (GETPOST("delayed")) $param.=" --delayed-insert"; - if (GETPOST("sql_ignore")) $param.=" --insert-ignore"; - if (GETPOST("hexforbinary") || $usedefault) $param.=" --hex-blob"; + if (GETPOST("delayed", "alpha")) $param.=" --delayed-insert"; + if (GETPOST("sql_ignore", "alpha")) $param.=" --insert-ignore"; + if (GETPOST("hexforbinary", "alpha") || $usedefault) $param.=" --hex-blob"; } else { @@ -436,8 +437,9 @@ class Utils dol_mkdir($conf->admin->dir_output.'/backup'); // Parameteres execution - $command=$cmddump; - if (preg_match("/\s/",$command)) $command=escapeshellarg($command); // Use quotes on command + $command = $cmddump; + $command = preg_replace('/(\$|%)/', '', $command); // We removed chars that can be used to inject vars that contains space inside path of command without seeing there is a space to bypass the escapeshellarg. + if (preg_match("/\s/",$command)) $command=escapeshellarg($command); // If there is spaces, we add quotes on command to be sure $command is only a program and not a program+parameters //$param=escapeshellarg($dolibarr_main_db_name)." -h ".escapeshellarg($dolibarr_main_db_host)." -u ".escapeshellarg($dolibarr_main_db_user)." -p".escapeshellarg($dolibarr_main_db_pass); //$param="-F c"; From 63c0ab93fb21f86c1b736061af9fa1eee90148fd Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 25 Apr 2019 23:21:25 +0200 Subject: [PATCH 039/132] FIX CVE-2019-11201 --- htdocs/core/lib/website.lib.php | 43 +++++++++++++++++++++++++++++++-- htdocs/langs/en_US/website.lang | 3 ++- htdocs/website/index.php | 22 +++++++++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/htdocs/core/lib/website.lib.php b/htdocs/core/lib/website.lib.php index 6f1057936d8..090a0f908dd 100644 --- a/htdocs/core/lib/website.lib.php +++ b/htdocs/core/lib/website.lib.php @@ -31,7 +31,7 @@ * @param string $content Content to replace * @param int $removephppart 0=Replace PHP sections with a PHP badge. 1=Remove completely PHP sections. * @return boolean True if OK - * @see dolWebsiteOutput for function used to replace content in a web server context + * @see dolWebsiteOutput() for function used to replace content in a web server context */ function dolWebsiteReplacementOfLinks($website, $content, $removephppart=0) { @@ -101,6 +101,7 @@ function dolWebsiteReplacementOfLinks($website, $content, $removephppart=0) * @param string $str String to clean * @param string $replacewith String to use as replacement * @return string Result string without php code + * @see dolKeepOnlyPhpCode() */ function dolStripPhpCode($str, $replacewith='') { @@ -133,6 +134,44 @@ function dolStripPhpCode($str, $replacewith='') return $newstr; } +/** + * Keep only PHP code part from a HTML string page. + * + * @param string $str String to clean + * @return string Result string with php code only + * @see dolStripPhpCode() + */ +function dolKeepOnlyPhpCode($str) +{ + $newstr = ''; + + //split on each opening tag + $parts = explode('', $part, 2); + if (!empty($partlings)) + { + $newstr .= $partlings[0].'?>'; + } + else + { + $newstr .= $part.'?>'; + } + } + } + return $newstr; +} /** * Render a string of an HTML content and output it. @@ -140,7 +179,7 @@ function dolStripPhpCode($str, $replacewith='') * * @param string $content Content string * @return void - * @see dolWebsiteReplacementOfLinks for function used to replace content in the backoffice context when USEDOLIBARREDITOR is not on + * @see dolWebsiteReplacementOfLinks() for function used to replace content in the backoffice context when USEDOLIBARREDITOR is not on */ function dolWebsiteOutput($content) { diff --git a/htdocs/langs/en_US/website.lang b/htdocs/langs/en_US/website.lang index 99f0133f175..4de381b0658 100644 --- a/htdocs/langs/en_US/website.lang +++ b/htdocs/langs/en_US/website.lang @@ -95,4 +95,5 @@ InternalURLOfPage=Internal URL of page ThisPageIsTranslationOf=This page/container is translation of ThisPageHasTranslationPages=This page/container has translation NoWebSiteCreateOneFirst=No website created yet. Create on first. -GoTo=Go to \ No newline at end of file +GoTo=Go to +DynamicPHPCodeContainsAForbiddenInstruction=You add dynamic PHP code that contains the PHP instruction '%s' that is forbidden by default as dynamic content (see hidden options WEBSITE_PHP_ALLOW_xxx to increase list of allowed commands). diff --git a/htdocs/website/index.php b/htdocs/website/index.php index 1ec9c2c65c4..592c3cd4234 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -1453,6 +1453,26 @@ if (($action == 'updatesource' || $action == 'updatecontent' || $action == 'conf $objectpage->content = GETPOST('PAGE_CONTENT','none'); + // Security analysis + $phpfullcodestring = dolKeepOnlyPhpCode($objectpage->content); + //print dol_escape_htmltag($phpfullcodestring);exit; + $forbiddenphpcommands=array("exec", "passthru", "system", "shell_exec", "proc_open"); + if (empty($conf->global->WEBSITE_PHP_ALLOW_WRITE)) // If option is not on, we disallow functions to write files + { + $forbiddenphpcommands=array_merge($forbiddenphpcommands, array("fopen", "file_put_contents", "fputs", "fputscsv", "fwrite", "fpassthru", "unlink", "mkdir", "rmdir", "symlink", "touch", "umask")); + } + foreach($forbiddenphpcommands as $forbiddenphpcommand) + { + if (preg_match('/'.$forbiddenphpcommand.'\s*\(/ms', $phpfullcodestring)) + { + $error++; + setEventMessages($langs->trans("DynamicPHPCodeContainsAForbiddenInstruction", $forbiddenphpcommand), null, 'errors'); + if ($action == 'updatesource') $action = 'editsource'; + if ($action == 'updatecontent') $action = 'editcontent'; + } + } + + // Clean data. We remove all the head section. $objectpage->content = preg_replace('/.*<\/head>/ims', '', $objectpage->content); /* $objectpage->content = preg_replace('//s', '', $objectpage->content); */ @@ -1463,6 +1483,8 @@ if (($action == 'updatesource' || $action == 'updatecontent' || $action == 'conf { $error++; setEventMessages($objectpage->error, $objectpage->errors, 'errors'); + if ($action == 'updatesource') $action = 'editsource'; + if ($action == 'updatecontent') $action = 'editcontent'; } if (! $error) From 9760ed5c8d04f4de446c9e76bb1543371e695fcf Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 25 Apr 2019 23:36:19 +0200 Subject: [PATCH 040/132] FIX CVE-2019-11199 --- htdocs/viewimage.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/htdocs/viewimage.php b/htdocs/viewimage.php index 2385a558307..073aaa9fb24 100644 --- a/htdocs/viewimage.php +++ b/htdocs/viewimage.php @@ -169,6 +169,9 @@ $type = 'application/octet-stream'; if (GETPOST('type','alpha')) $type=GETPOST('type','alpha'); else $type=dol_mimetype($original_file); +// Security: This wrapper is for images. We do not allow type/html +if (preg_match('/html/', $type)) accessforbidden('Error: Using the image wrapper to output a file with a mime type HTML is not possible.', 1, 1, 1); + // Security: Delete string ../ into $original_file $original_file = str_replace("../","/", $original_file); @@ -176,7 +179,7 @@ $original_file = str_replace("../","/", $original_file); $refname=basename(dirname($original_file)."/"); // Security check -if (empty($modulepart)) accessforbidden('Bad value for parameter modulepart'); +if (empty($modulepart)) accessforbidden('Bad value for parameter modulepart', 1, 1, 1); $check_access = dol_check_secure_access_document($modulepart, $original_file, $entity, $refname); $accessallowed = $check_access['accessallowed']; From 85059eeedb0c3e2dc956d3cf5114fa90b65cefc4 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 26 Apr 2019 02:05:57 +0200 Subject: [PATCH 041/132] Debug method getPaymentIntent --- htdocs/stripe/class/stripe.class.php | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index 0ebef813429..fd28cd94b8a 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -265,14 +265,14 @@ class Stripe extends CommonObject $paymentintent = null; - $sql = "SELECT pi.ext_payment_id, pi.entity, pi.fk_facture, pi.sourcetype, pi.ext_payment_site"; // key_account is cus_.... + $sql = "SELECT pi.ext_payment_id, pi.entity, pi.fk_facture, pi.sourcetype, pi.ext_payment_site"; $sql.= " FROM " . MAIN_DB_PREFIX . "prelevement_facture_demande as pi"; $sql.= " WHERE pi.fk_facture = " . $object->id; $sql.= " AND pi.sourcetype = '" . $object->element . "'"; $sql.= " AND pi.entity IN (".getEntity('societe').")"; $sql.= " AND pi.ext_payment_site = '" . $service . "'"; - dol_syslog(get_class($this) . "::customerStripe search stripe customer id for thirdparty id=".$object->id, LOG_DEBUG); + dol_syslog(get_class($this) . "::getPaymentIntent search stripe customer id for thirdparty id=".$object->id, LOG_DEBUG); $resql = $this->db->query($sql); if ($resql) { $num = $this->db->num_rows($resql); @@ -281,7 +281,7 @@ class Stripe extends CommonObject $obj = $this->db->fetch_object($resql); $intent = $obj->ext_payment_id; - dol_syslog(get_class($this) . "::customerStripe found record"); + dol_syslog(get_class($this) . "::getPaymentIntent found existing payment intent record"); // Force to use the correct API key global $stripearrayofkeysbyenv; @@ -312,7 +312,10 @@ class Stripe extends CommonObject $fee = round($conf->global->STRIPE_APPLICATION_FEE_MINIMAL * 100); } - $description=$object->element.$object->ref; + $ipaddress=getUserRemoteIP(); + // Not enough space for a ref so we store id. Also with multicompany we can have same ref for 2 different + // object and we need a unique (this is used later as idempotency_key) + $description=$object->element.$object->id; $dataforintent = array( "amount" => $stripeamount, @@ -320,7 +323,7 @@ class Stripe extends CommonObject "customer" => $customer, "allowed_source_types" => ["card"], "statement_descriptor" => dol_trunc($description, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description) - "metadata" => array('dol_type'=>$object->element, 'dol_id'=>$object->id, 'dol_version'=>DOL_VERSION, 'dol_entity'=>$conf->entity, 'ipaddress'=>(empty($_SERVER['REMOTE_ADDR'])?'':$_SERVER['REMOTE_ADDR'])) + "metadata" => array('dol_type'=>$object->element, 'dol_id'=>$object->id, 'dol_version'=>DOL_VERSION, 'dol_entity'=>$conf->entity, 'ipaddress'=>$ipaddress) ); if ($conf->entity!=$conf->global->STRIPECONNECT_PRINCIPAL && $fee>0) @@ -344,12 +347,12 @@ class Stripe extends CommonObject } $now=dol_now(); $sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement_facture_demande (fk_soc, date_demande, fk_user_demande, ext_payment_id, fk_facture, sourcetype, entity, ext_payment_site)"; - $sql .= " VALUES ('".$object->socid."','".$this->db->idate($now)."', '0', '".$this->db->escape($paymentintent->id)."', ".$object->id.", '".$object->element."', " . $conf->entity . ", '" . $service . "')"; + $sql .= " VALUES ('".$object->socid."','".$this->db->idate($now)."', '0', '".$this->db->escape($paymentintent->id)."', ".$object->id.", '".$this->db->escape($object->element)."', " . $conf->entity . ", '" . $service . "')"; $resql = $this->db->query($sql); if (! $resql) { $this->error = $this->db->lasterror(); - dol_syslog(get_class($this) . "::PaymentIntent not insert with id=".$paymentintent->id); + dol_syslog(get_class($this) . "::PaymentIntent failed to insert paymentintent with id=".$paymentintent->id." into database."); } } catch(Exception $e) From 653790fb5d0303236828f691eaaa13a1b27814c8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 26 Apr 2019 03:11:46 +0200 Subject: [PATCH 042/132] Clean code --- htdocs/public/payment/newpayment.php | 3 ++- htdocs/public/stripe/ipn.php | 1 - htdocs/stripe/class/stripe.class.php | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index 2d579329274..69f2d96c8c2 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -395,7 +395,8 @@ if ($action == 'dopayment') } -// Called when choosing Stripe mode, after clicking the 'dopayment' +// Called when choosing Stripe mode, after clicking the 'dopayment' with the Charge API architecture. +// When using the PaymentItent architecture, we dont need this, the Stripe customer is created when creating PaymentItent when showing payment page. if ($action == 'charge' && ! empty($conf->stripe->enabled)) { $amountstripe = $amount; diff --git a/htdocs/public/stripe/ipn.php b/htdocs/public/stripe/ipn.php index d889041be60..17de701ac29 100644 --- a/htdocs/public/stripe/ipn.php +++ b/htdocs/public/stripe/ipn.php @@ -309,7 +309,6 @@ elseif (($event->type == 'source.chargeable') && ($event->data->object->type == // Save into $tmptag all metadata $tmptag=dolExplodeIntoArray($fulltag, '.', '='); - // TODO: Set $_POST var from $event->data and call newpayment.php with $action = 'charge' $stripe=new Stripe($db); /* $stripeacc = $stripe->getStripeAccount($service); // Stripe OAuth connect account of dolibarr user (no network access here) diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index fd28cd94b8a..6a393e20b7a 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -238,7 +238,7 @@ class Stripe extends CommonObject } /** - * Get the Stripe payment intent + * Get the Stripe payment intent. Create it with confirm=false * * @param Societe $object Object to pay with Stripe * @param string $customer Stripe customer ref 'cus_xxxxxxxxxxxxx' via customerStripe() @@ -318,7 +318,9 @@ class Stripe extends CommonObject $description=$object->element.$object->id; $dataforintent = array( - "amount" => $stripeamount, + "confirm" => false, // Do not confirm immediatly during creation of intent + "confirmation_method" => $mode, + "amount" => $stripeamount, "currency" => $object->multicurrency_code, "customer" => $customer, "allowed_source_types" => ["card"], From f81a1a3e85dae8eb03488c980e0bb09c4f1caab8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 26 Apr 2019 03:50:05 +0200 Subject: [PATCH 043/132] Complete examples --- htdocs/stripe/admin/stripe.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/stripe/admin/stripe.php b/htdocs/stripe/admin/stripe.php index 134030687df..1895c2e95ba 100644 --- a/htdocs/stripe/admin/stripe.php +++ b/htdocs/stripe/admin/stripe.php @@ -457,7 +457,7 @@ $token=''; include DOL_DOCUMENT_ROOT.'/core/tpl/onlinepaymentlinks.tpl.php'; -print info_admin($langs->trans("ExampleOfTestCreditCard", '4242424242424242', '4000000000000101', '4000000000000069', '4000000000000341')); +print info_admin($langs->trans("ExampleOfTestCreditCard", '4242424242424242 (no 3DSecure) or 4000000000003063 (3DSecure required)', '4000000000000101', '4000000000000069', '4000000000000341')); if (! empty($conf->use_javascript_ajax)) { From bb3f1c04f6733871e2e016809f6646adc5a15b57 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 26 Apr 2019 05:05:10 +0200 Subject: [PATCH 044/132] Prepare intent --- htdocs/public/stripe/ipn.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/htdocs/public/stripe/ipn.php b/htdocs/public/stripe/ipn.php index 17de701ac29..caab7114744 100644 --- a/htdocs/public/stripe/ipn.php +++ b/htdocs/public/stripe/ipn.php @@ -295,6 +295,12 @@ elseif ($event->type == 'customer.deleted') { $db->query($sql); $db->commit(); } +elseif ($event->type == 'payment_intent.succeeded') { + // TODO: Redirect to paymentok.php +} +elseif ($event->type == 'payment_intent.payment_failed') { + // TODO: Redirect to paymentko.php +} elseif ($event->type == 'charge.succeeded') { // TODO: create fees // TODO: Redirect to paymentok.php From a7362ca05564a7346a7f39d9c7e2f031e47d9acc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 26 Apr 2019 05:05:33 +0200 Subject: [PATCH 045/132] More examples --- htdocs/stripe/admin/stripe.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/stripe/admin/stripe.php b/htdocs/stripe/admin/stripe.php index 1895c2e95ba..91254e540a4 100644 --- a/htdocs/stripe/admin/stripe.php +++ b/htdocs/stripe/admin/stripe.php @@ -457,7 +457,7 @@ $token=''; include DOL_DOCUMENT_ROOT.'/core/tpl/onlinepaymentlinks.tpl.php'; -print info_admin($langs->trans("ExampleOfTestCreditCard", '4242424242424242 (no 3DSecure) or 4000000000003063 (3DSecure required)', '4000000000000101', '4000000000000069', '4000000000000341')); +print info_admin($langs->trans("ExampleOfTestCreditCard", '4242424242424242 (no 3DSecure) or 4000000000003063 (3DSecure required) or 4000000000003220 (3DSecure2 required)', '4000000000000101', '4000000000000069', '4000000000000341')); if (! empty($conf->use_javascript_ajax)) { From 22b8a67e559f894a94b3178b15d67f7dc493dfa5 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 26 Apr 2019 05:19:11 +0200 Subject: [PATCH 046/132] A more complete function --- htdocs/stripe/class/stripe.class.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index 6a393e20b7a..5ad35d82008 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -238,17 +238,18 @@ class Stripe extends CommonObject } /** - * Get the Stripe payment intent. Create it with confirm=false + * Get the Stripe payment intent. Create it with confirm=false * * @param Societe $object Object to pay with Stripe * @param string $customer Stripe customer ref 'cus_xxxxxxxxxxxxx' via customerStripe() * @param string $key ''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect * @param int $status Status (0=test, 1=live) * @param int $usethirdpartyemailforreceiptemail 1=use thirdparty email for receipt - * @param int $mode automatic=automatic payment, manual=need confirmation + * @param int $mode automatic=automatic confirmation/payment when conditions are ok, manual=need to call confirm() on intent + * @param boolean $confirmnow false=default, true=try to confirm immediatly after create (if conditions are ok) * @return \Stripe\PaymentIntent|null Stripe PaymentIntent or null if not found */ - public function getPaymentIntent($object, $customer, $key = null, $status = 0, $usethirdpartyemailforreceiptemail = 0, $mode = 'automatic') + public function getPaymentIntent($object, $customer, $key = null, $status = 0, $usethirdpartyemailforreceiptemail = 0, $mode = 'automatic', $confirmnow = false) { global $conf, $user, $mysoc; @@ -318,7 +319,7 @@ class Stripe extends CommonObject $description=$object->element.$object->id; $dataforintent = array( - "confirm" => false, // Do not confirm immediatly during creation of intent + "confirm" => $confirmnow, // Do not confirm immediatly during creation of intent "confirmation_method" => $mode, "amount" => $stripeamount, "currency" => $object->multicurrency_code, From 9380254f76c1a40bcb86b215561a48425f43c4fe Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 26 Apr 2019 10:48:38 +0200 Subject: [PATCH 047/132] Prepare for Manual confirmation quickstart --- htdocs/public/stripe/confirm_payment.php | 152 +++++++++++++++++++++++ htdocs/public/stripe/ipn.php | 8 +- htdocs/stripe/class/stripe.class.php | 3 + 3 files changed, 160 insertions(+), 3 deletions(-) create mode 100644 htdocs/public/stripe/confirm_payment.php diff --git a/htdocs/public/stripe/confirm_payment.php b/htdocs/public/stripe/confirm_payment.php new file mode 100644 index 00000000000..90f21da6b6b --- /dev/null +++ b/htdocs/public/stripe/confirm_payment.php @@ -0,0 +1,152 @@ + + * + * 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 . + */ + +define("NOLOGIN", 1); // This means this output page does not require to be logged. +define("NOCSRFCHECK", 1); // We accept to go on this page from external web site. + +$entity=(! empty($_GET['entity']) ? (int) $_GET['entity'] : (! empty($_POST['entity']) ? (int) $_POST['entity'] : 1)); +if (is_numeric($entity)) define("DOLENTITY", $entity); + +require '../../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/ccountry.class.php'; +require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; +require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php'; +require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; +require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; +require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; + +require_once DOL_DOCUMENT_ROOT.'/includes/stripe/init.php'; +require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; + +if (empty($conf->stripe->enabled)) accessforbidden('', 0, 0, 1); + + +// You can find your endpoint's secret in your webhook settings +if (isset($_GET['connect'])) +{ + if (isset($_GET['test'])) + { + $endpoint_secret = $conf->global->STRIPE_TEST_WEBHOOK_CONNECT_KEY; + $service = 'StripeTest'; + $servicestatus = 0; + } + else + { + $endpoint_secret = $conf->global->STRIPE_LIVE_WEBHOOK_CONNECT_KEY; + $service = 'StripeLive'; + $servicestatus = 1; + } +} +else { + if (isset($_GET['test'])) + { + $endpoint_secret = $conf->global->STRIPE_TEST_WEBHOOK_KEY; + $service = 'StripeTest'; + $servicestatus = 0; + } + else + { + $endpoint_secret = $conf->global->STRIPE_LIVE_WEBHOOK_KEY; + $service = 'StripeLive'; + $servicestatus = 1; + } +} + + + +/* + * Actions + */ + +$langs->load("main"); + +// TODO Do we really need a user in setup just to have an name to fill an email topic when it is a technical system notification email +$user = new User($db); +$user->fetch($conf->global->STRIPE_USER_ACCOUNT_FOR_ACTIONS); +$user->getrights(); + +// list of action +$stripe=new Stripe($db); + +// Subject +$societeName = $conf->global->MAIN_INFO_SOCIETE_NOM; +if (! empty($conf->global->MAIN_APPLICATION_TITLE)) $societeName = $conf->global->MAIN_APPLICATION_TITLE; + + +dol_syslog("Stripe confirm_payment was called"); +dol_syslog("GET=".var_export($_GET, true)); +dol_syslog("POST=".var_export($_POST, true)); + + +header('Content-Type: application/json'); + +# retrieve json from POST body +$json_str = file_get_contents('php://input'); +$json_obj = json_decode($json_str); + +$intent = null; +try { + if (isset($json_obj->payment_method_id)) { + # Create the PaymentIntent + $intent = \Stripe\PaymentIntent::create([ + 'payment_method' => $json_obj->payment_method_id, + 'amount' => 1099, + 'currency' => 'eur', + 'confirmation_method' => 'manual', + 'confirm' => true, + ]); + } + if (isset($json_obj->payment_intent_id)) { + $intent = \Stripe\PaymentIntent::retrieve( + $json_obj->payment_intent_id + ); + $intent->confirm(); + } + generatePaymentResponse($intent); +} catch (\Stripe\Error\Base $e) { + # Display error on client + echo json_encode([ + 'error' => $e->getMessage() + ]); +} + +function generatePaymentResponse($intent) { + if ($intent->status == 'requires_source_action' && + $intent->next_action->type == 'use_stripe_sdk') { + # Tell the client to handle the action + echo json_encode([ + 'requires_action' => true, + 'payment_intent_client_secret' => $intent->client_secret + ]); + } else if ($intent->status == 'succeeded') { + # The payment didn’t need any additional actions and completed! + # Handle post-payment fulfillment + + // TODO + + echo json_encode([ + "success" => true + ]); + } else { + # Invalid status + http_response_code(500); + echo json_encode(['error' => 'Invalid PaymentIntent status']); + } +} diff --git a/htdocs/public/stripe/ipn.php b/htdocs/public/stripe/ipn.php index caab7114744..ca7db10f9d1 100644 --- a/htdocs/public/stripe/ipn.php +++ b/htdocs/public/stripe/ipn.php @@ -25,15 +25,17 @@ if (is_numeric($entity)) define("DOLENTITY", $entity); require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; -require_once DOL_DOCUMENT_ROOT.'/includes/stripe/init.php'; -require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/ccountry.class.php'; require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; -require_once DOL_DOCUMENT_ROOT .'/core/class/CMailFile.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; + +require_once DOL_DOCUMENT_ROOT.'/includes/stripe/init.php'; +require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; + if (empty($conf->stripe->enabled)) accessforbidden('', 0, 0, 1); diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index 5ad35d82008..54737791032 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -328,6 +328,9 @@ class Stripe extends CommonObject "statement_descriptor" => dol_trunc($description, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description) "metadata" => array('dol_type'=>$object->element, 'dol_id'=>$object->id, 'dol_version'=>DOL_VERSION, 'dol_entity'=>$conf->entity, 'ipaddress'=>$ipaddress) ); + // save_payment_method = true, + // payment_method_types = + // payment_method = if ($conf->entity!=$conf->global->STRIPECONNECT_PRINCIPAL && $fee>0) { From 0c432c28a833c68628cb08311366336a70190027 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 26 Apr 2019 13:08:19 +0200 Subject: [PATCH 048/132] Trans --- htdocs/langs/en_US/stripe.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/stripe.lang b/htdocs/langs/en_US/stripe.lang index 64ce7b15aff..1eb0a649a74 100644 --- a/htdocs/langs/en_US/stripe.lang +++ b/htdocs/langs/en_US/stripe.lang @@ -40,7 +40,7 @@ STRIPE_LIVE_WEBHOOK_KEY=Webhook live key ONLINE_PAYMENT_WAREHOUSE=Stock to use for stock decrease when online payment is done
(TODO When option to decrease stock is done on an action on invoice and the online payment generate itself the invoice ?) StripeLiveEnabled=Stripe live enabled (otherwise test/sandbox mode) StripeImportPayment=Import Stripe payments -ExampleOfTestCreditCard=Example of credit card for test: %s (valid), %s (error CVC), %s (expired), %s (charge fails) +ExampleOfTestCreditCard=Example of credit card for test: %s => valid, %s => error CVC, %s => expired, %s => charge fails StripeGateways=Stripe gateways OAUTH_STRIPE_TEST_ID=Stripe Connect Client ID (ca_...) OAUTH_STRIPE_LIVE_ID=Stripe Connect Client ID (ca_...) From 3e02dc2465533591ffa45a78fa0563de72a78566 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Fri, 26 Apr 2019 13:23:30 +0200 Subject: [PATCH 049/132] FIX : dolibarrize fk_soc ->socid for member --- htdocs/adherents/class/adherent.class.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 201b6610817..00534dd3879 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -86,6 +86,7 @@ class Adherent extends CommonObject * @var int Thirdparty ID */ public $fk_soc; + public $socid; /** * @var string Address @@ -1275,6 +1276,7 @@ class Adherent extends CommonObject $this->societe = $obj->company; $this->company = $obj->company; $this->fk_soc = $obj->fk_soc; + $this->socid = $obj->fk_soc; $this->address = $obj->address; $this->zip = $obj->zip; $this->town = $obj->town; From 143cbec2816aabdae56b765c2428bcfc2533e9f2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 26 Apr 2019 13:23:33 +0200 Subject: [PATCH 050/132] Fix test --- htdocs/projet/element.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/projet/element.php b/htdocs/projet/element.php index 23ee7fd8e2d..c2ea95d14ca 100644 --- a/htdocs/projet/element.php +++ b/htdocs/projet/element.php @@ -474,7 +474,7 @@ $listofreferent=array( 'lang'=>'banks', 'buttonnew'=>'AddVariousPayment', 'testnew'=>$user->rights->banque->modifier, - 'test'=>$conf->banque->enabled && $user->rights->banque->lire), + 'test'=>$conf->banque->enabled && $user->rights->banque->lire && empty($conf->global->BANK_USE_OLD_VARIOUS_PAYMENT)), /* No need for this, available on dedicated tab "Agenda/Events" 'agenda'=>array( 'name'=>"Agenda", From 9b9295ab50d544f91189c54cab21a8704ded4790 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Fri, 26 Apr 2019 14:25:58 +0200 Subject: [PATCH 051/132] Update adherent.class.php --- htdocs/adherents/class/adherent.class.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 00534dd3879..9c32417efb4 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -10,6 +10,7 @@ * Copyright (C) 2015-2018 Frédéric France * Copyright (C) 2015 Raphaël Doursenaud * Copyright (C) 2016 Juanjo Menent + * Copyright (C) 2018-2019 Thibault FOUCART * * 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,7 +87,6 @@ class Adherent extends CommonObject * @var int Thirdparty ID */ public $fk_soc; - public $socid; /** * @var string Address @@ -558,7 +558,7 @@ class Adherent extends CommonObject $sql.= ", gender = ".($this->gender != -1 ? "'".$this->db->escape($this->gender)."'" : "null"); // 'man' or 'woman' $sql.= ", login = ".($this->login?"'".$this->db->escape($this->login)."'":"null"); $sql.= ", societe = ".($this->societe?"'".$this->db->escape($this->societe)."'":"null"); - $sql.= ", fk_soc = ".($this->fk_soc > 0?$this->db->escape($this->fk_soc):"null"); + $sql.= ", fk_soc = ".($this->socid > 0?$this->db->escape($this->socid):"null"); $sql.= ", address = ".($this->address?"'".$this->db->escape($this->address)."'":"null"); $sql.= ", zip = ".($this->zip?"'".$this->db->escape($this->zip)."'":"null"); $sql.= ", town = ".($this->town?"'".$this->db->escape($this->town)."'":"null"); @@ -1276,7 +1276,6 @@ class Adherent extends CommonObject $this->societe = $obj->company; $this->company = $obj->company; $this->fk_soc = $obj->fk_soc; - $this->socid = $obj->fk_soc; $this->address = $obj->address; $this->zip = $obj->zip; $this->town = $obj->town; From 423c5c3ac8adadaddd39d4ed9297104591175a13 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Fri, 26 Apr 2019 14:26:50 +0200 Subject: [PATCH 052/132] Update card.php --- htdocs/adherents/card.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index 9903255e52f..5d57208eb0e 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -82,7 +82,7 @@ if (! empty($canvas)) } // Security check -$result=restrictedArea($user, 'adherent', $id, '', '', 'fk_soc', 'rowid', $objcanvas); +$result=restrictedArea($user, 'adherent', $id, '', '', 'socid', 'rowid', $objcanvas); if ($id > 0) { @@ -163,10 +163,10 @@ if (empty($reshook)) $error=0; if (! $error) { - if ($socid != $object->fk_soc) // If link differs from currently in database + if ($socid != $object->socid) // If link differs from currently in database { $sql ="SELECT rowid FROM ".MAIN_DB_PREFIX."adherent"; - $sql.=" WHERE fk_soc = '".$socid."'"; + $sql.=" WHERE socid = '".$socid."'"; $sql.=" AND entity = ".$conf->entity; $resql = $db->query($sql); if ($resql) @@ -492,7 +492,7 @@ if (empty($reshook)) //$object->note = $comment; $object->morphy = $morphy; $object->user_id = $userid; - $object->fk_soc = $socid; + $object->socid = $socid; $object->public = $public; // Fill array 'array_options' with data from add form @@ -1333,10 +1333,10 @@ else if (! empty($conf->societe->enabled)) { print '
'.$langs->trans("LinkedToDolibarrThirdParty").''; - if ($object->fk_soc) + if ($object->socid) { $company=new Societe($db); - $result=$company->fetch($object->fk_soc); + $result=$company->fetch($object->socid); print $company->getNomUrl(1); } else @@ -1421,7 +1421,7 @@ else $text=$langs->trans("ConfirmCreateLogin").'
'; if (! empty($conf->societe->enabled)) { - if ($object->fk_soc > 0) $text.=$langs->trans("UserWillBeExternalUser"); + if ($object->socid > 0) $text.=$langs->trans("UserWillBeExternalUser"); else $text.=$langs->trans("UserWillBeInternalUser"); } print $form->formconfirm($_SERVER["PHP_SELF"]."?rowid=".$object->id, $langs->trans("CreateDolibarrLogin"), $text, "confirm_create_user", $formquestion, 'yes'); @@ -1688,17 +1688,17 @@ else print ''; print ''; print ''; print ''; print '
'; - print $form->select_company($object->fk_soc, 'socid', '', 1); + print $form->select_company($object->socid, 'socid', '', 1); print '
'; } else { - if ($object->fk_soc) + if ($object->socid) { $company=new Societe($db); - $result=$company->fetch($object->fk_soc); + $result=$company->fetch($object->socid); print $company->getNomUrl(1); } else @@ -1848,7 +1848,7 @@ else } // Create third party - if (! empty($conf->societe->enabled) && ! $object->fk_soc) + if (! empty($conf->societe->enabled) && ! $object->socid) { if ($user->rights->societe->creer) { From 485bc8cd7c964393a197e4dcb974eedaff2105f1 Mon Sep 17 00:00:00 2001 From: Mavyre Date: Fri, 26 Apr 2019 14:45:59 +0200 Subject: [PATCH 053/132] Corrected syncRates parameter --- htdocs/multicurrency/class/multicurrency.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/multicurrency/class/multicurrency.class.php b/htdocs/multicurrency/class/multicurrency.class.php index ea39cb85b8e..2abfb0e2624 100644 --- a/htdocs/multicurrency/class/multicurrency.class.php +++ b/htdocs/multicurrency/class/multicurrency.class.php @@ -629,7 +629,7 @@ class MultiCurrency extends CommonObject * @param array $response array of reponse from api to sync dolibarr rates * @return void */ - public static function syncRates($response) + public static function syncRates($key) { global $conf, $db, $langs; From 3e99a40b9e09e2e660cbb1cecea5d2acbfd5a9db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Fri, 26 Apr 2019 17:47:47 +0200 Subject: [PATCH 054/132] Update website.lib.php --- htdocs/core/lib/website.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/website.lib.php b/htdocs/core/lib/website.lib.php index 56f6cdf97a3..198f91a4446 100644 --- a/htdocs/core/lib/website.lib.php +++ b/htdocs/core/lib/website.lib.php @@ -145,7 +145,7 @@ function dolKeepOnlyPhpCode($str) $newstr = ''; //split on each opening tag - $parts = explode(' Date: Fri, 26 Apr 2019 17:57:23 +0200 Subject: [PATCH 055/132] Update confirm_payment.php --- htdocs/public/stripe/confirm_payment.php | 49 ++++++++++++++---------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/htdocs/public/stripe/confirm_payment.php b/htdocs/public/stripe/confirm_payment.php index 90f21da6b6b..ea59b13dcb9 100644 --- a/htdocs/public/stripe/confirm_payment.php +++ b/htdocs/public/stripe/confirm_payment.php @@ -97,14 +97,14 @@ dol_syslog("POST=".var_export($_POST, true)); header('Content-Type: application/json'); -# retrieve json from POST body +// retrieve json from POST body $json_str = file_get_contents('php://input'); $json_obj = json_decode($json_str); $intent = null; try { if (isset($json_obj->payment_method_id)) { - # Create the PaymentIntent + // Create the PaymentIntent $intent = \Stripe\PaymentIntent::create([ 'payment_method' => $json_obj->payment_method_id, 'amount' => 1099, @@ -121,32 +121,39 @@ try { } generatePaymentResponse($intent); } catch (\Stripe\Error\Base $e) { - # Display error on client + // Display error on client echo json_encode([ 'error' => $e->getMessage() ]); } -function generatePaymentResponse($intent) { +/* + * generate payment response + * + * @param \Stripe\PaymentIntent $intent PaymentIntent + * @return void + */ +function generatePaymentResponse($intent) +{ if ($intent->status == 'requires_source_action' && $intent->next_action->type == 'use_stripe_sdk') { - # Tell the client to handle the action - echo json_encode([ - 'requires_action' => true, - 'payment_intent_client_secret' => $intent->client_secret - ]); - } else if ($intent->status == 'succeeded') { - # The payment didn’t need any additional actions and completed! - # Handle post-payment fulfillment + // Tell the client to handle the action + echo json_encode([ + 'requires_action' => true, + 'payment_intent_client_secret' => $intent->client_secret + ]); + } elseif ($intent->status == 'succeeded') { + // The payment didn’t need any additional actions and completed! + // Handle post-payment fulfillment - // TODO + // TODO - echo json_encode([ - "success" => true - ]); - } else { - # Invalid status - http_response_code(500); - echo json_encode(['error' => 'Invalid PaymentIntent status']); - } + echo json_encode([ + "success" => true + ]); + } else { + // Invalid status + http_response_code(500); + echo json_encode(['error' => 'Invalid PaymentIntent status']); + } } From c90dc13a21c949643f378e519315f1fdc261b14e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 27 Apr 2019 13:02:52 +0200 Subject: [PATCH 056/132] CSS --- htdocs/theme/eldy/global.inc.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index f234ba319c2..38b05e30b9f 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -5640,7 +5640,7 @@ div.tabsElem a.tab { /* nboftopmenuentries = , fontsize= */ /* rule to reduce top menu - 1st reduction: Reduce width of top menu icons */ -@media only screen and (max-width: px) /* reduction 1 */ +@media only screen and (max-width: global->THEME_ELDY_WITDHOFFSET_FOR_REDUC1) ? round($nbtopmenuentries * 90, 0) + 240 : $conf->global->THEME_ELDY_WITDHOFFSET_FOR_REDUC1; ?>px) /* reduction 1 */ { div.tmenucenter { width: px; /* size of viewport */ @@ -5673,7 +5673,7 @@ div.tabsElem a.tab { } } /* rule to reduce top menu - 2nd reduction: Reduce width of top menu icons again */ -@media only screen and (max-width: px) /* reduction 2 */ +@media only screen and (max-width: global->THEME_ELDY_WITDHOFFSET_FOR_REDUC2) ? round($nbtopmenuentries * 69, 0) + 40 : $conf->global->THEME_ELDY_WITDHOFFSET_FOR_REDUC2; ?>px) /* reduction 2 */ { div.mainmenu { height: 23px; @@ -5697,7 +5697,7 @@ div.tabsElem a.tab { } } /* rule to reduce top menu - 3rd reduction: The menu for user is on left */ -@media only screen and (max-width: px) /* reduction 3 */ +@media only screen and (max-width: global->THEME_ELDY_WITDHOFFSET_FOR_REDUC3) ? round($nbtopmenuentries * 47, 0) + 40 : $conf->global->THEME_ELDY_WITDHOFFSET_FOR_REDUC3; ?>px) /* reduction 3 */ { .side-nav { z-index: 200; From 15d57df1774a93012de7475aef945af2933f22a7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 27 Apr 2019 13:03:11 +0200 Subject: [PATCH 057/132] CSS --- htdocs/main.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 6ffd5a088e8..fa3a8c1cd43 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -1813,7 +1813,7 @@ function top_menu_user(User $user, Translate $langs)
'; + print ''; if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print ''; print ''; $formother->select_year($search_syear?$search_syear:-1, 'search_syear', 1, 20, 5); @@ -532,7 +532,7 @@ if (! empty($arrayfields['t.dateo']['checked'])) // End date if (! empty($arrayfields['t.datee']['checked'])) { - print ''; + print ''; if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print ''; print ''; $formother->select_year($search_eyear?$search_eyear:-1, 'search_eyear', 1, 20, 5); @@ -657,7 +657,7 @@ while ($i < min($num, $limit)) // Ref if (! empty($arrayfields['t.ref']['checked'])) { - print ''; + print ''; print $object->getNomUrl(1, 'withproject'); if ($object->hasDelay()) print img_warning("Late"); print '
'; @@ -958,7 +968,14 @@ if ($resql) print ''; print ''; From cef5bb15b1e8f876d0cacd70269cab05356bff40 Mon Sep 17 00:00:00 2001 From: Ludovic Canivet Date: Mon, 29 Apr 2019 11:43:25 +0200 Subject: [PATCH 071/132] Search ticket by thirdparty name instead of id --- htdocs/ticket/list.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/htdocs/ticket/list.php b/htdocs/ticket/list.php index 3cd594b3eb9..ad6ac18d386 100644 --- a/htdocs/ticket/list.php +++ b/htdocs/ticket/list.php @@ -52,7 +52,7 @@ $id = GETPOST('id', 'int'); $msg_id = GETPOST('msg_id', 'int'); $socid = GETPOST('socid', 'int'); $projectid = GETPOST('projectid', 'int'); -$search_fk_soc=GETPOST('$search_fk_soc', 'int')?GETPOST('$search_fk_soc', 'int'):GETPOST('socid', 'int'); +$search_societe = GETPOST('search_societe', 'alpha'); $search_fk_project=GETPOST('search_fk_project', 'int')?GETPOST('search_fk_project', 'int'):GETPOST('projectid', 'int'); $search_fk_status = GETPOST('search_fk_statut', 'array'); $mode = GETPOST('mode', 'alpha'); @@ -210,6 +210,7 @@ $sql.= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t"; if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)"; if ($object->ismultientitymanaged == 1) $sql.= " WHERE t.entity IN (".getEntity($object->element).")"; else $sql.=" WHERE 1 = 1"; +$sql.= " AND t.fk_soc = s.rowid"; foreach($search as $key => $val) { @@ -231,7 +232,7 @@ foreach($search as $key => $val) if ($search[$key] != '') $sql.=natural_search($key, $search[$key], $mode_search); } if ($search_all) $sql.= natural_search(array_keys($fieldstosearchall), $search_all); -if ($search_fk_soc) $sql.= natural_search('fk_soc', $search_fk_soc, 2); +if ($search_societe) $sql .= natural_search('s.nom', $search_societe); if ($search_fk_project) $sql.= natural_search('fk_project', $search_fk_project, 2); if (! $user->societe_id && ($mode == "mine" || (!$user->admin && $conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY))) { $sql.= " AND (t.fk_user_assign = ".$user->id; @@ -538,6 +539,10 @@ foreach($object->fields as $key => $val) print Form::multiselectarray('search_fk_statut', $arrayofstatus, array_values($search[$key]), 0, 0, 'minwidth150', 1, 0, '', '', ''); print ''; } + elseif ($key == "fk_soc") + { + print ''; + } else { print ''; } From dfd0e97d20e0e7419e6fb8092f0265ac519bb620 Mon Sep 17 00:00:00 2001 From: Ludovic Canivet Date: Mon, 29 Apr 2019 11:46:14 +0200 Subject: [PATCH 072/132] Search ticket by thirdparty name instead of id 2/2 --- htdocs/ticket/list.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/ticket/list.php b/htdocs/ticket/list.php index ad6ac18d386..402f3b717a4 100644 --- a/htdocs/ticket/list.php +++ b/htdocs/ticket/list.php @@ -208,9 +208,10 @@ $sql.=$hookmanager->resPrint; $sql=preg_replace('/, $/', '', $sql); $sql.= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t"; if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)"; +$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON (t.fk_soc = s.rowid)"; if ($object->ismultientitymanaged == 1) $sql.= " WHERE t.entity IN (".getEntity($object->element).")"; else $sql.=" WHERE 1 = 1"; -$sql.= " AND t.fk_soc = s.rowid"; + foreach($search as $key => $val) { From e3af373cd35bcf6c81b49c7300db1cf6cef8d210 Mon Sep 17 00:00:00 2001 From: Ludovic Canivet Date: Mon, 29 Apr 2019 15:43:34 +0200 Subject: [PATCH 073/132] Fix tms date format on ticket list --- htdocs/ticket/list.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/ticket/list.php b/htdocs/ticket/list.php index 402f3b717a4..96af20dc591 100644 --- a/htdocs/ticket/list.php +++ b/htdocs/ticket/list.php @@ -638,6 +638,7 @@ while ($i < min($num, $limit)) elseif ($key == 'category_code') print $langs->getLabelFromKey($db, $object->category_code, 'c_ticket_category', 'code', 'label'); elseif ($key == 'severity_code') print $langs->getLabelFromKey($db, $object->severity_code, 'c_ticket_severity', 'code', 'label'); elseif ($key == 'type_code') print $langs->getLabelFromKey($db, $object->type_code, 'c_ticket_type', 'code', 'label'); + elseif ($key == 'tms') print dol_print_date($db->jdate($obj->$key), 'dayhour', 'tzuser'); elseif (in_array($val['type'], array('date','datetime','timestamp'))) print $object->showOutputField($val, $key, $db->jdate($obj->$key), ''); else print $object->showOutputField($val, $key, $obj->$key, ''); print ''; From 8091cff0094b213093d252467b2c1bcdc2e78401 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 29 Apr 2019 15:44:16 +0200 Subject: [PATCH 074/132] Can edit param of operation for email collector --- htdocs/admin/emailcollector_card.php | 36 +++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/htdocs/admin/emailcollector_card.php b/htdocs/admin/emailcollector_card.php index 31a8520505d..e71299b65e3 100644 --- a/htdocs/admin/emailcollector_card.php +++ b/htdocs/admin/emailcollector_card.php @@ -48,6 +48,8 @@ $cancel = GETPOST('cancel', 'aZ09'); $contextpage= GETPOST('contextpage', 'aZ')?GETPOST('contextpage', 'aZ'):'myobjectcard'; // To manage different context of search $backtopage = GETPOST('backtopage', 'alpha'); +$operationid = GETPOST('operationid', 'int'); + // Initialize technical objects $object = new EmailCollector($db); $extrafields = new ExtraFields($db); @@ -64,6 +66,7 @@ foreach ($object->fields as $key => $val) { if (GETPOST('search_'.$key, 'alpha')) $search[$key]=GETPOST('search_'.$key, 'alpha'); } +if (GETPOST('saveoperation2')) $action = 'updateoperation'; if (empty($action) && empty($id) && empty($ref)) $action='view'; // Load object @@ -165,6 +168,24 @@ if (GETPOST('addoperation', 'alpha')) } } +if ($action == 'updateoperation') +{ + $emailcollectoroperation = new EmailCollectorAction($db); + $emailcollectoroperation->fetch(GETPOST('rowidoperation2', 'int')); + + $emailcollectoroperation->actionparam = GETPOST('operationparam2', 'none'); + + $result = $emailcollectoroperation->update($user); + + if ($result > 0) + { + $object->fetchActions(); + } + else + { + setEventMessages($emailcollectoroperation->errors, $emailcollectoroperation->error, 'errors'); + } +} if ($action == 'deleteoperation') { $emailcollectoroperation = new EmailCollectorAction($db); @@ -564,7 +585,18 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print $form->textwithpicto('', $langs->transnoentitiesnoconv('IfTrackingIDFoundEventWillBeLinked')); } print ''; - print ''; + print ''; // Move up/down print ''; // Delete print ''; print ''; From 483d017fc5a8ec8b2b71eb2f0155832325f8267f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 29 Apr 2019 16:16:44 +0200 Subject: [PATCH 075/132] Fix creation of project --- .../class/emailcollector.class.php | 80 ++++++++++++------- 1 file changed, 50 insertions(+), 30 deletions(-) diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 04f64a78280..4052a180bc1 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -1570,37 +1570,57 @@ class EmailCollector extends CommonObject $projecttocreate->note_private = $descriptionfull; $projecttocreate->entity = $conf->entity; - // Get next project Ref - $defaultref=''; - $modele = empty($conf->global->PROJECT_ADDON)?'mod_project_simple':$conf->global->PROJECT_ADDON; - - // Search template files - $file=''; $classname=''; $filefound=0; $reldir=''; - $dirmodels=array_merge(array('/'), (array) $conf->modules_parts['models']); - foreach($dirmodels as $reldir) - { - $file=dol_buildpath($reldir."core/modules/project/".$modele.'.php', 0); - if (file_exists($file)) - { - $filefound=1; - $classname = $modele; - break; - } - } - - if ($filefound) - { - $result=dol_include_once($reldir."core/modules/project/".$modele.'.php'); - $modProject = new $classname; - - $defaultref = $modProject->getNextValue(($thirdpartystatic->id > 0 ? $thirdpartystatic : null), $projecttocreate); - } - - $projecttocreate->ref = $defaultref; - - // Overwrite values with values extracted from source email + // Overwrite values with values extracted from source email. + // This may overwrite any $projecttocreate->xxx properties. + $savesocid = $projecttocreate->socid; $errorforthisaction = $this->overwritePropertiesOfObject($projecttocreate, $operation['actionparam'], $messagetext, $subject, $header); + // Set project ref if not yet defined + if (empty($projecttocreate->ref)) + { + // Get next project Ref + $defaultref=''; + $modele = empty($conf->global->PROJECT_ADDON)?'mod_project_simple':$conf->global->PROJECT_ADDON; + + // Search template files + $file=''; $classname=''; $filefound=0; $reldir=''; + $dirmodels=array_merge(array('/'), (array) $conf->modules_parts['models']); + foreach($dirmodels as $reldir) + { + $file=dol_buildpath($reldir."core/modules/project/".$modele.'.php', 0); + if (file_exists($file)) + { + $filefound=1; + $classname = $modele; + break; + } + } + + if ($filefound) + { + $result=dol_include_once($reldir."core/modules/project/".$modele.'.php'); + $modProject = new $classname; + + if ($savesocid > 0) + { + if ($savesocid != $projecttocreate->socid) + { + $errorforactions++; + setEventMessages('You loaded a thirdparty (id='.$savesocid.') and you force another thirdparty id (id='.$projecttocreate->socid.') by setting socid in operation with a different value'); + } + } + else { + if ($projecttocreate->socid > 0) + { + $thirdpartystatic->fetch($projecttocreate->socid); + } + } + + $defaultref = $modProject->getNextValue(($thirdpartystatic->id > 0 ? $thirdpartystatic : null), $projecttocreate); + } + $projecttocreate->ref = $defaultref; + } + if ($errorforthisaction) { $errorforactions++; @@ -1610,7 +1630,7 @@ class EmailCollector extends CommonObject if (empty($projecttocreate->ref) || (is_numeric($projecttocreate->ref) && $projecttocreate->ref <= 0)) { $errorforactions++; - $this->error = 'Failed to create project: Can\'t get a valid value for project Ref with numbering template '.$modele; + $this->error = 'Failed to create project: Can\'t get a valid value for project Ref with numbering template '.$modele.' thirdpartyid'; } else { From d0eecf9be5055781d7e14dbab4f06f5139e78847 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 29 Apr 2019 16:38:56 +0200 Subject: [PATCH 076/132] Fix emailcollector --- .../class/emailcollector.class.php | 78 ++++++++++++------- 1 file changed, 49 insertions(+), 29 deletions(-) diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 4052a180bc1..808de3da147 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -1685,37 +1685,57 @@ class EmailCollector extends CommonObject $tickettocreate->entity = $conf->entity; //$tickettocreate->fk_contact = $contactstatic->id; - // Get next project Ref - $defaultref=''; - $modele = empty($conf->global->TICKET_ADDON)?'mod_ticket_simple':$conf->global->TICKET_ADDON; - - // Search template files - $file=''; $classname=''; $filefound=0; $reldir=''; - $dirmodels=array_merge(array('/'), (array) $conf->modules_parts['models']); - foreach($dirmodels as $reldir) - { - $file=dol_buildpath($reldir."core/modules/ticket/".$modele.'.php', 0); - if (file_exists($file)) - { - $filefound=1; - $classname = $modele; - break; - } - } - - if ($filefound) - { - $result=dol_include_once($reldir."core/modules/ticket/".$modele.'.php'); - $modTicket = new $classname; - - $defaultref = $modTicket->getNextValue(($thirdpartystatic->id > 0 ? $thirdpartystatic : null), $tickettocreate); - } - - $tickettocreate->ref = $defaultref; - - // Overwrite values with values extracted from source email + // Overwrite values with values extracted from source email. + // This may overwrite any $projecttocreate->xxx properties. + $savesocid = $tickettocreate->socid; $errorforthisaction = $this->overwritePropertiesOfObject($tickettocreate, $operation['actionparam'], $messagetext, $subject, $header); + // Set ticket ref if not yet defined + if (empty($tickettocreate->ref)) + { + // Get next project Ref + $defaultref=''; + $modele = empty($conf->global->TICKET_ADDON)?'mod_ticket_simple':$conf->global->TICKET_ADDON; + + // Search template files + $file=''; $classname=''; $filefound=0; $reldir=''; + $dirmodels=array_merge(array('/'), (array) $conf->modules_parts['models']); + foreach($dirmodels as $reldir) + { + $file=dol_buildpath($reldir."core/modules/ticket/".$modele.'.php', 0); + if (file_exists($file)) + { + $filefound=1; + $classname = $modele; + break; + } + } + + if ($filefound) + { + $result=dol_include_once($reldir."core/modules/ticket/".$modele.'.php'); + $modProject = new $classname; + + if ($savesocid > 0) + { + if ($savesocid != $tickettocreate->socid) + { + $errorforactions++; + setEventMessages('You loaded a thirdparty (id='.$savesocid.') and you force another thirdparty id (id='.$tickettocreate->socid.') by setting socid in operation with a different value'); + } + } + else { + if ($tickettocreate->socid > 0) + { + $thirdpartystatic->fetch($tickettocreate->socid); + } + } + + $defaultref = $modTicket->getNextValue(($thirdpartystatic->id > 0 ? $thirdpartystatic : null), $projecttocreate); + } + $tickettocreate->ref = $defaultref; + } + if ($errorforthisaction) { $errorforactions++; From 7c26785cb2015270b860b95248d11d26f868cf88 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 29 Apr 2019 16:47:00 +0200 Subject: [PATCH 077/132] Fix emailcollector --- htdocs/emailcollector/class/emailcollector.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 808de3da147..eea1a7a6132 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -1630,7 +1630,7 @@ class EmailCollector extends CommonObject if (empty($projecttocreate->ref) || (is_numeric($projecttocreate->ref) && $projecttocreate->ref <= 0)) { $errorforactions++; - $this->error = 'Failed to create project: Can\'t get a valid value for project Ref with numbering template '.$modele.' thirdpartyid'; + $this->error = 'Failed to create project: Can\'t get a valid value for the field ref with numbering template = '.$modele.', thirdparty id = '.$thirdpartystatic->id; } else { @@ -1745,7 +1745,7 @@ class EmailCollector extends CommonObject if (is_numeric($tickettocreate->ref) && $tickettocreate->ref <= 0) { $errorforactions++; - $this->error = "Failed to create ticket: Can't get a valid value for ticket Ref. Check the numbering module used to generate the reference in setup of module Ticket."; + $this->error = 'Failed to create ticket: Can\'t get a valid value for the field ref with numbering template = '.$modele.', thirdparty id = '.$thirdpartystatic->id; } else { From c7fcecc3364cba568894391e693b53bb0a4cf857 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 29 Apr 2019 17:17:25 +0200 Subject: [PATCH 078/132] Fix email not loaded --- htdocs/langs/en_US/admin.lang | 2 +- htdocs/projet/list.php | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 3979ee83638..90abbe90fc6 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1853,7 +1853,7 @@ WithoutDolTrackingID=Dolibarr Tracking ID not found FormatZip=Zip MainMenuCode=Menu entry code (mainmenu) ECMAutoTree=Show automatic ECM tree -OperationParamDesc=Define values to use for action, or how to extract values. For example:
objproperty1=SET:abc
objproperty2=EXTRACT:HEADER:X-Myheaderkey.*[^\s]+(.*)
options_myextrafield=EXTRACT:SUBJECT:([^\s]*)
object.objproperty4=EXTRACT:BODY:My company name is\s([^\s]*)

Use a ; char as separator to extract or set several properties. +OperationParamDesc=Define values to use for action, or how to extract values. For example:
objproperty1=SET:abc
objproperty1=SET:a value with replacement of __objproperty1__
objproperty3=SETIFEMPTY:abc
objproperty4=EXTRACT:HEADER:X-Myheaderkey.*[^\s]+(.*)
options_myextrafield=EXTRACT:SUBJECT:([^\s]*)
object.objproperty5=EXTRACT:BODY:My company name is\s([^\s]*)

Use a ; char as separator to extract or set several properties. OpeningHours=Opening hours OpeningHoursDesc=Enter here the regular opening hours of your company. ResourceSetup=Configuration of Resource module diff --git a/htdocs/projet/list.php b/htdocs/projet/list.php index 1a7fb9317e1..c58ac17f980 100644 --- a/htdocs/projet/list.php +++ b/htdocs/projet/list.php @@ -279,7 +279,7 @@ if (count($listofprojectcontacttype) == 0) $listofprojectcontacttype[0]='0'; $distinct='DISTINCT'; // We add distinct until we are added a protection to be sure a contact of a project and task is only once. $sql = "SELECT ".$distinct." p.rowid as id, p.ref, p.title, p.fk_statut, p.fk_opp_status, p.public, p.fk_user_creat"; $sql.= ", p.datec as date_creation, p.dateo as date_start, p.datee as date_end, p.opp_amount, p.opp_percent, p.tms as date_update, p.budget_amount, p.bill_time"; -$sql.= ", s.nom as name, s.rowid as socid"; +$sql.= ", s.rowid as socid, s.nom as name, s.email"; $sql.= ", cls.code as opp_status_code"; // We'll need these fields in order to filter by categ if ($search_categ) $sql .= ", cs.fk_categorie, cs.fk_project"; @@ -706,6 +706,10 @@ while ($i < min($num, $limit)) $userAccess = $object->restrictedProjectArea($user); // why this ? if ($userAccess >= 0) { + $socstatic->id=$obj->socid; + $socstatic->name=$obj->name; + $socstatic->email=$obj->email; + print '
'; // Project url @@ -731,8 +735,6 @@ while ($i < min($num, $limit)) print '\n"; } diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index e1a05258ea5..a9c8df670b5 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -2761,6 +2761,7 @@ elseif (! empty($object->id)) $modelmail='order_supplier_send'; $defaulttopic='SendOrderRef'; $diroutput = $conf->fournisseur->commande->dir_output; + $autocopy='MAIN_MAIL_AUTOCOPY_SUPPLIER_ORDER_TO'; $trackid = 'sor'.$object->id; include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php'; diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index a7b6fe32fb1..3956684d9b2 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -3206,6 +3206,7 @@ else $modelmail='invoice_supplier_send'; $defaulttopic='SendBillRef'; $diroutput = $conf->fournisseur->facture->dir_output; + $autocopy='MAIN_MAIL_AUTOCOPY_SUPPLIER_INVOICE_TO'; $trackid = 'sin'.$object->id; include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php'; diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index cf0131ef53f..e7cefc9b576 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -1286,6 +1286,7 @@ elseif ($object->id > 0) $modelmail='project'; $defaulttopic='SendProjectRef'; $diroutput = $conf->projet->dir_output; + $autocopy='MAIN_MAIL_AUTOCOPY_PROJECT_TO'; // used to know the automatic BCC to add $trackid = 'proj'.$object->id; include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php'; diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index 85297634ec3..0d9f36602ea 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -1877,6 +1877,7 @@ if ($action == 'create') $modelmail='supplier_proposal_send'; $defaulttopic='SendAskRef'; $diroutput = $conf->supplier_proposal->dir_output; + $autocopy='MAIN_MAIL_AUTOCOPY_SUPPLIER_PROPOSAL_TO'; $trackid = 'spr'.$object->id; include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php'; From 5d40124b2277bcc9e802ef6aebfee7b436d34db3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 29 Apr 2019 20:15:03 +0200 Subject: [PATCH 083/132] Fix import of product price with multilevel prices --- htdocs/core/modules/modProduct.class.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/htdocs/core/modules/modProduct.class.php b/htdocs/core/modules/modProduct.class.php index b725ef878a3..a5f32c5831a 100644 --- a/htdocs/core/modules/modProduct.class.php +++ b/htdocs/core/modules/modProduct.class.php @@ -362,7 +362,7 @@ class modProduct extends DolibarrModules 'sp.fk_soc'=>array('rule'=>'fetchidfromref','classfile'=>'/societe/class/societe.class.php','class'=>'Societe','method'=>'fetch','element'=>'ThirdParty'), 'sp.fk_product'=>array('rule'=>'fetchidfromref','classfile'=>'/product/class/product.class.php','class'=>'Product','method'=>'fetch','element'=>'Product') ); - $this->import_examplevalues_array[$r]=array('sp.fk_product'=>"PREF123456", + $this->import_examplevalues_array[$r]=array('sp.fk_product'=>"PROD_REF or id:123456", 'sp.fk_soc'=>"My Supplier",'sp.ref_fourn'=>"SupplierRef", 'sp.quantity'=>"1", 'sp.tva_tx'=>'21', 'sp.price'=>"50", 'sp.unitprice'=>'50', @@ -381,7 +381,7 @@ class modProduct extends DolibarrModules $this->import_entities_array[$r]=array(); // We define here only fields that use another icon that the one defined into import_icon $this->import_tables_array[$r]=array('pr'=>MAIN_DB_PREFIX.'product_price'); $this->import_tables_creator_array[$r]=array('pr'=>'fk_user_author'); // Fields to store import user id - $this->import_fields_array[$r]=array('pr.fk_product'=>"ProductRowid*", + $this->import_fields_array[$r]=array('pr.fk_product'=>"ProductOrService*", 'pr.price_base_type'=>"PriceLevelPriceBase",'pr.price_level'=>"PriceLevel", 'pr.price'=>"PriceLevelUnitPriceHT",'pr.price_ttc'=>"PriceLevelUnitPriceTTC", 'pr.price_min'=>"MinPriceLevelUnitPriceHT",'pr.price_min_ttc'=>"MinPriceLevelUnitPriceTTC", @@ -389,7 +389,10 @@ class modProduct extends DolibarrModules 'pr.date_price'=>'DateCreation*'); if (is_object($mysoc) && $mysoc->useNPR()) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r],array('pr.recuperableonly'=>'NPR')); $this->import_regex_array[$r]=array('pr.datec'=>'^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$','pr.recuperableonly'=>'^[0|1]$'); - $this->import_examplevalues_array[$r]=array('pr.fk_product'=>"1", + $this->import_convertvalue_array[$r]=array( + 'pr.fk_product'=>array('rule'=>'fetchidfromref','classfile'=>'/product/class/product.class.php','class'=>'Product','method'=>'fetch','element'=>'Product') + ); + $this->import_examplevalues_array[$r]=array('pr.fk_product'=>"PROD_REF or id:123456", 'pr.price_base_type'=>"HT",'pr.price_level'=>"1", 'pr.price'=>"100",'pr.price_ttc'=>"110", 'pr.price_min'=>"100",'pr.price_min_ttc'=>"110", @@ -407,13 +410,13 @@ class modProduct extends DolibarrModules $this->import_entities_array[$r]=array(); // We define here only fields that use another icon that the one defined into import_icon $this->import_tables_array[$r]=array('l'=>MAIN_DB_PREFIX.'product_lang'); // multiline translation, one line per translation - $this->import_fields_array[$r]=array('l.fk_product'=>'Ref', 'l.lang'=>'Language', 'l.label'=>'TranslatedLabel', 'l.description'=>'TranslatedDescription'); + $this->import_fields_array[$r]=array('l.fk_product'=>'ProductOrService*', 'l.lang'=>'Language', 'l.label'=>'TranslatedLabel', 'l.description'=>'TranslatedDescription'); //$this->import_fields_array[$r]['l.note']='TranslatedNote'; $this->import_convertvalue_array[$r]=array( 'l.fk_product'=>array('rule'=>'fetchidfromref','classfile'=>'/product/class/product.class.php','class'=>'Product','method'=>'fetch','element'=>'Product') ); - $this->import_examplevalues_array[$r]=array('l.fk_product'=>'MyProductRef','l.lang'=>'en_US','l.label'=>'Label in en_US','l.description'=>'Desc in en_US'); - $this->import_updatekeys_array[$r]=array('l.fk_product'=>'Ref','l.lang'=>'Language'); + $this->import_examplevalues_array[$r]=array('l.fk_product'=>'PROD_REF or id:123456','l.lang'=>'en_US','l.label'=>'Label in en_US','l.description'=>'Desc in en_US'); + $this->import_updatekeys_array[$r]=array('l.fk_product'=>'ProductOrService','l.lang'=>'Language'); } } From bbc6c0fe0ccfb4dacfac787f89a5fdd8cd9e560e Mon Sep 17 00:00:00 2001 From: Supermanu Date: Sat, 27 Apr 2019 18:44:52 +0200 Subject: [PATCH 084/132] Show help text for extrafields in forms --- htdocs/core/class/commonobject.class.php | 2 +- htdocs/core/class/extrafields.class.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 60bfd1e5305..d25f5d80cba 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -6523,7 +6523,7 @@ abstract class CommonObject $out .= $extrafields->showOutputField($key, $value); break; case "edit": - $out .= $extrafields->showInputField($key, $value, '', $keysuffix, '', 0, $this->id); + $out .= $extrafields->showInputField($key, $value, '', $keysuffix, '', 0, $this->id, $this->table_element); break; } diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index 26acdf50fcc..caea57280b9 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -1567,6 +1567,9 @@ class ExtraFields if ($type == 'date') $out.=' (YYYY-MM-DD)'; elseif ($type == 'datetime') $out.=' (YYYY-MM-DD HH:MM:SS)'; */ + if (! empty($help)) { + $out .= $form->textwithpicto("", $help); + } return $out; } From 101f6a5af3a972ab70118ceb0de3772164c0cbef Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 29 Apr 2019 20:41:36 +0200 Subject: [PATCH 085/132] FIX Several fixes on import of services/products --- htdocs/core/modules/modProduct.class.php | 21 ++- htdocs/core/modules/modService.class.php | 182 ++++++++++++++--------- 2 files changed, 127 insertions(+), 76 deletions(-) diff --git a/htdocs/core/modules/modProduct.class.php b/htdocs/core/modules/modProduct.class.php index a5f32c5831a..cde60b3af7b 100644 --- a/htdocs/core/modules/modProduct.class.php +++ b/htdocs/core/modules/modProduct.class.php @@ -201,6 +201,11 @@ class modProduct extends DolibarrModules if (! empty($conf->fournisseur->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('s.nom'=>'product_supplier_ref','pf.ref_fourn'=>'product_supplier_ref','pf.unitprice'=>'product_supplier_ref','pf.quantity'=>'product_supplier_ref','pf.remise_percent'=>'product_supplier_ref','pf.delivery_time_days'=>'product_supplier_ref')); if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('l.lang'=>'translation', 'l.label'=>'translation','l.description'=>'translation','l.note'=>'translation')); if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_dependencies_array[$r]=array('category'=>'p.rowid'); + if (! empty($conf->stock->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.stock'=>'product','p.pmp'=>'product')); + if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.barcode'=>'product')); + if (! empty($conf->fournisseur->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('s.nom'=>'product_supplier_ref','pf.ref_fourn'=>'product_supplier_ref','pf.unitprice'=>'product_supplier_ref','pf.quantity'=>'product_supplier_ref','pf.remise_percent'=>'product_supplier_ref','pf.delivery_time_days'=>'product_supplier_ref')); + if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('l.lang'=>'translation', 'l.label'=>'translation','l.description'=>'translation','l.note'=>'translation')); + if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_dependencies_array[$r]=array('category'=>'p.rowid'); $this->export_sql_start[$r]='SELECT DISTINCT '; $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'product as p'; if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_product as cp ON cp.fk_product = p.rowid LEFT JOIN '.MAIN_DB_PREFIX.'categorie as cat ON cp.fk_categorie = cat.rowid'; @@ -218,7 +223,7 @@ class modProduct extends DolibarrModules $this->export_label[$r]="ProductsMultiPrice"; // Translation key (used only if key ExportDataset_xxx_z not found) $this->export_permission[$r]=array(array("produit","export")); $this->export_fields_array[$r]=array('p.rowid'=>"Id",'p.ref'=>"Ref", - 'pr.price_base_type'=>"PriceLevelPriceBase",'pr.price_level'=>"PriceLevel", + 'pr.price_base_type'=>"PriceBase",'pr.price_level'=>"PriceLevel", 'pr.price'=>"PriceLevelUnitPriceHT",'pr.price_ttc'=>"PriceLevelUnitPriceTTC", 'pr.price_min'=>"MinPriceLevelUnitPriceHT",'pr.price_min_ttc'=>"MinPriceLevelUnitPriceTTC", 'pr.tva_tx'=>'PriceLevelVATRate', @@ -362,7 +367,7 @@ class modProduct extends DolibarrModules 'sp.fk_soc'=>array('rule'=>'fetchidfromref','classfile'=>'/societe/class/societe.class.php','class'=>'Societe','method'=>'fetch','element'=>'ThirdParty'), 'sp.fk_product'=>array('rule'=>'fetchidfromref','classfile'=>'/product/class/product.class.php','class'=>'Product','method'=>'fetch','element'=>'Product') ); - $this->import_examplevalues_array[$r]=array('sp.fk_product'=>"PROD_REF or id:123456", + $this->import_examplevalues_array[$r]=array('sp.fk_product'=>"PRODUCT_REF or id:123456", 'sp.fk_soc'=>"My Supplier",'sp.ref_fourn'=>"SupplierRef", 'sp.quantity'=>"1", 'sp.tva_tx'=>'21', 'sp.price'=>"50", 'sp.unitprice'=>'50', @@ -382,18 +387,18 @@ class modProduct extends DolibarrModules $this->import_tables_array[$r]=array('pr'=>MAIN_DB_PREFIX.'product_price'); $this->import_tables_creator_array[$r]=array('pr'=>'fk_user_author'); // Fields to store import user id $this->import_fields_array[$r]=array('pr.fk_product'=>"ProductOrService*", - 'pr.price_base_type'=>"PriceLevelPriceBase",'pr.price_level'=>"PriceLevel", + 'pr.price_base_type'=>"PriceBase",'pr.price_level'=>"PriceLevel", 'pr.price'=>"PriceLevelUnitPriceHT",'pr.price_ttc'=>"PriceLevelUnitPriceTTC", 'pr.price_min'=>"MinPriceLevelUnitPriceHT",'pr.price_min_ttc'=>"MinPriceLevelUnitPriceTTC", - 'pr.tva_tx'=>'PriceLevelVATRate', 'pr.date_price'=>'DateCreation*'); + if (! empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) $this->import_fields_array[$r]['pr.tva_tx']='VATRate'; if (is_object($mysoc) && $mysoc->useNPR()) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r],array('pr.recuperableonly'=>'NPR')); $this->import_regex_array[$r]=array('pr.datec'=>'^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$','pr.recuperableonly'=>'^[0|1]$'); $this->import_convertvalue_array[$r]=array( 'pr.fk_product'=>array('rule'=>'fetchidfromref','classfile'=>'/product/class/product.class.php','class'=>'Product','method'=>'fetch','element'=>'Product') ); - $this->import_examplevalues_array[$r]=array('pr.fk_product'=>"PROD_REF or id:123456", - 'pr.price_base_type'=>"HT",'pr.price_level'=>"1", + $this->import_examplevalues_array[$r]=array('pr.fk_product'=>"PRODUCT_REF or id:123456", + 'pr.price_base_type'=>"HT (for excl tax) or TTC (for inc tax)",'pr.price_level'=>"1", 'pr.price'=>"100",'pr.price_ttc'=>"110", 'pr.price_min'=>"100",'pr.price_min_ttc'=>"110", 'pr.tva_tx'=>'20', @@ -410,12 +415,12 @@ class modProduct extends DolibarrModules $this->import_entities_array[$r]=array(); // We define here only fields that use another icon that the one defined into import_icon $this->import_tables_array[$r]=array('l'=>MAIN_DB_PREFIX.'product_lang'); // multiline translation, one line per translation - $this->import_fields_array[$r]=array('l.fk_product'=>'ProductOrService*', 'l.lang'=>'Language', 'l.label'=>'TranslatedLabel', 'l.description'=>'TranslatedDescription'); + $this->import_fields_array[$r]=array('l.fk_product'=>'ProductOrService*', 'l.lang'=>'Language*', 'l.label'=>'TranslatedLabel', 'l.description'=>'TranslatedDescription'); //$this->import_fields_array[$r]['l.note']='TranslatedNote'; $this->import_convertvalue_array[$r]=array( 'l.fk_product'=>array('rule'=>'fetchidfromref','classfile'=>'/product/class/product.class.php','class'=>'Product','method'=>'fetch','element'=>'Product') ); - $this->import_examplevalues_array[$r]=array('l.fk_product'=>'PROD_REF or id:123456','l.lang'=>'en_US','l.label'=>'Label in en_US','l.description'=>'Desc in en_US'); + $this->import_examplevalues_array[$r]=array('l.fk_product'=>'PRODUCT_REF or id:123456','l.lang'=>'en_US','l.label'=>'Label in en_US','l.description'=>'Desc in en_US'); $this->import_updatekeys_array[$r]=array('l.fk_product'=>'ProductOrService','l.lang'=>'Language'); } } diff --git a/htdocs/core/modules/modService.class.php b/htdocs/core/modules/modService.class.php index 6e5f5562a77..3f7462ee463 100644 --- a/htdocs/core/modules/modService.class.php +++ b/htdocs/core/modules/modService.class.php @@ -145,61 +145,44 @@ class modService extends DolibarrModules $this->export_code[$r]=$this->rights_class.'_'.$r; $this->export_label[$r]="Services"; // Translation key (used only if key ExportDataset_xxx_z not found) $this->export_permission[$r]=array(array("service","export")); - $this->export_fields_array[$r]=array('p.rowid'=>"Id",'p.ref'=>"Ref",'p.label'=>"Label",'p.description'=>"Description",'p.accountancy_code_sell'=>"ProductAccountancySellCode",'p.accountancy_code_buy'=>"ProductAccountancyBuyCode",'p.note'=>"Note",'p.price_base_type'=>"PriceBase",'p.price'=>"UnitPriceHT",'p.price_ttc'=>"UnitPriceTTC",'p.tva_tx'=>'VATRate','p.tosell'=>"OnSell",'p.tobuy'=>"OnBuy",'p.duration'=>"Duration",'p.datec'=>'DateCreation','p.tms'=>'DateModification'); - if (! empty($conf->stock->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('p.stock'=>'Stock')); + $this->export_fields_array[$r]=array('p.rowid'=>"Id",'p.ref'=>"Ref",'p.label'=>"Label",'p.description'=>"Description",'p.url'=>"PublicUrl",'p.accountancy_code_sell'=>"ProductAccountancySellCode",'p.accountancy_code_buy'=>"ProductAccountancyBuyCode",'p.note'=>"Note",'p.price_base_type'=>"PriceBase",'p.price'=>"UnitPriceHT",'p.price_ttc'=>"UnitPriceTTC",'p.tva_tx'=>'VATRate','p.tosell'=>"OnSell",'p.tobuy'=>"OnBuy",'p.duration'=>"Duration",'p.datec'=>'DateCreation','p.tms'=>'DateModification'); + if (is_object($mysoc) && $mysoc->useNPR()) $this->export_fields_array[$r]['p.recuperableonly']='NPR'; + if (! empty($conf->stock->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('p.stock'=>'Stock','p.seuil_stock_alerte'=>'StockLimit','p.desiredstock'=>'DesiredStock','p.pmp'=>'PMPValue')); + if (! empty($conf->barcode->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('p.barcode'=>'BarCode')); + if (! empty($conf->fournisseur->enabled) || !empty($conf->margin->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('p.cost_price'=>'CostPrice')); + $keyforselect='product'; $keyforelement='product'; $keyforaliasextra='extra'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; + if (! empty($conf->fournisseur->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('s.nom'=>'Supplier','pf.ref_fourn'=>'SupplierRef','pf.quantity'=>'QtyMin','pf.remise_percent'=>'DiscountQtyMin','pf.unitprice'=>'BuyingPrice','pf.delivery_time_days'=>'NbDaysToDelivery')); + if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('group_concat(cat.label)'=>'Categories')); + if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('l.lang'=>'Language', 'l.label'=>'TranslatedLabel','l.description'=>'TranslatedDescription','l.note'=>'TranslatedNote')); if (! empty($conf->global->PRODUCT_USE_UNITS)) $this->export_fields_array[$r]['p.fk_unit'] = 'Unit'; - //$this->export_TypeFields_array[$r]=array('p.ref'=>"Text",'p.label'=>"Text",'p.description'=>"Text",'p.accountancy_code_sell'=>"Text",'p.accountancy_code_buy'=>"Text",'p.note'=>"Text",'p.price_base_type'=>"Text",'p.price'=>"Numeric",'p.price_ttc'=>"Numeric",'p.tva_tx'=>'Numeric','p.tosell'=>"Boolean",'p.duration'=>"Duree",'p.datec'=>'Date','p.tms'=>'Date'); - $this->export_TypeFields_array[$r]=array('p.ref'=>"Text",'p.label'=>"Text",'p.description'=>"Text",'p.accountancy_code_sell'=>"Text",'p.accountancy_code_buy'=>"Text",'p.note'=>"Text",'p.price_base_type'=>"Text",'p.price'=>"Numeric",'p.price_ttc'=>"Numeric",'p.tva_tx'=>'Numeric','p.tosell'=>"Boolean",'p.tobuy'=>"Boolean",'p.duration'=>"Duree",'p.datec'=>'Date','p.tms'=>'Date'); + $this->export_TypeFields_array[$r]=array('p.ref'=>"Text",'p.label'=>"Text",'p.description'=>"Text",'p.url'=>"Text",'p.accountancy_code_sell'=>"Text",'p.accountancy_code_buy'=>"Text",'p.note'=>"Text",'p.price_base_type'=>"Text",'p.price'=>"Numeric",'p.price_ttc'=>"Numeric",'p.tva_tx'=>'Numeric','p.tosell'=>"Boolean",'p.tobuy'=>"Boolean",'p.duration'=>"Duree",'p.datec'=>'Date','p.tms'=>'Date'); if (! empty($conf->stock->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r],array('p.stock'=>'Numeric')); if (! empty($conf->barcode->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r],array('p.barcode'=>'Text')); - $this->export_entities_array[$r]=array('p.rowid'=>"service",'p.ref'=>"service",'p.label'=>"service",'p.description'=>"service",'p.accountancy_code_sell'=>'service','p.note'=>"service",'p.price_base_type'=>"service",'p.price'=>"service",'p.price_ttc'=>"service",'p.tva_tx'=>"service",'p.tosell'=>"service",'p.tobuy'=>"service",'p.duration'=>"service",'p.datec'=>"service",'p.tms'=>"service"); - if (! empty($conf->stock->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.stock'=>'service')); - if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.barcode'=>'service')); - // Add extra fields - $sql="SELECT name, label, type FROM ".MAIN_DB_PREFIX."extrafields WHERE elementtype = 'product'"; - $resql=$this->db->query($sql); - if ($resql) // This can fail when class is used on old database (during migration for example) - { - while ($obj=$this->db->fetch_object($resql)) - { - $fieldname='extra.'.$obj->name; - $fieldlabel=ucfirst($obj->label); - $typeFilter="Text"; - switch($obj->type) - { - case 'int': - case 'double': - case 'price': - $typeFilter="Numeric"; - break; - case 'date': - case 'datetime': - $typeFilter="Date"; - break; - case 'boolean': - $typeFilter="Boolean"; - break; - case 'sellist': - $tmp=''; - $tmpparam=unserialize($obj->param); // $tmp ay be array 'options' => array 'c_currencies:code_iso:code_iso' => null - if ($tmpparam['options'] && is_array($tmpparam['options'])) $tmp=array_shift(array_keys($tmpparam['options'])); - if (preg_match('/[a-z0-9_]+:[a-z0-9_]+:[a-z0-9_]+/', $tmp)) $typeFilter="List:".$tmp; - break; - } - $this->export_fields_array[$r][$fieldname]=$fieldlabel; - $this->export_TypeFields_array[$r][$fieldname]=$typeFilter; - $this->export_entities_array[$r][$fieldname]='product'; - } - } - // End add extra fields - + if (! empty($conf->fournisseur->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r],array('s.nom'=>'Text','pf.ref_fourn'=>'Text','pf.unitprice'=>'Numeric','pf.quantity'=>'Numeric','pf.remise_percent'=>'Numeric','pf.delivery_time_days'=>'Numeric')); + if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r],array('l.lang'=>'Text', 'l.label'=>'Text','l.description'=>'Text','l.note'=>'Text')); + if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r],array("group_concat(cat.label)"=>'Text')); + $this->export_entities_array[$r]=array(); // We define here only fields that use another icon that the one defined into import_icon + if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array("group_concat(cat.label)"=>'category')); + if (! empty($conf->stock->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.stock'=>'product','p.pmp'=>'product')); + if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.barcode'=>'product')); + if (! empty($conf->fournisseur->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('s.nom'=>'product_supplier_ref','pf.ref_fourn'=>'product_supplier_ref','pf.unitprice'=>'product_supplier_ref','pf.quantity'=>'product_supplier_ref','pf.remise_percent'=>'product_supplier_ref','pf.delivery_time_days'=>'product_supplier_ref')); + if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('l.lang'=>'translation', 'l.label'=>'translation','l.description'=>'translation','l.note'=>'translation')); + if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_dependencies_array[$r]=array('category'=>'p.rowid'); + if (! empty($conf->stock->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.stock'=>'product','p.pmp'=>'product')); + if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.barcode'=>'product')); + if (! empty($conf->fournisseur->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('s.nom'=>'product_supplier_ref','pf.ref_fourn'=>'product_supplier_ref','pf.unitprice'=>'product_supplier_ref','pf.quantity'=>'product_supplier_ref','pf.remise_percent'=>'product_supplier_ref','pf.delivery_time_days'=>'product_supplier_ref')); + if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('l.lang'=>'translation', 'l.label'=>'translation','l.description'=>'translation','l.note'=>'translation')); + if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_dependencies_array[$r]=array('category'=>'p.rowid'); $this->export_sql_start[$r]='SELECT DISTINCT '; $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'product as p'; - $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product_extrafields as extra ON p.rowid = extra.fk_object'; + if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_product as cp ON cp.fk_product = p.rowid LEFT JOIN '.MAIN_DB_PREFIX.'categorie as cat ON cp.fk_categorie = cat.rowid'; + if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product_lang as l ON l.fk_product = p.rowid'; + $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product_extrafields as extra ON p.rowid = extra.fk_object'; if (! empty($conf->fournisseur->enabled)) $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product_fournisseur_price as pf ON pf.fk_product = p.rowid LEFT JOIN '.MAIN_DB_PREFIX.'societe s ON s.rowid = pf.fk_soc'; $this->export_sql_end[$r] .=' WHERE p.fk_product_type = 1 AND p.entity IN ('.getEntity('product').')'; - - + if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_sql_order[$r] =' GROUP BY p.rowid'; // FIXME The group by used a generic value to say "all fields in select except function fields" + if (empty($conf->product->enabled)) // We enable next import templates only if module product not already enabled (to avoid duplicate entries) { if (! empty($conf->global->PRODUIT_MULTIPRICES)) @@ -210,11 +193,12 @@ class modService extends DolibarrModules $this->export_label[$r]="ProductsMultiPrice"; // Translation key (used only if key ExportDataset_xxx_z not found) $this->export_permission[$r]=array(array("produit","export")); $this->export_fields_array[$r]=array('p.rowid'=>"Id",'p.ref'=>"Ref", - 'pr.price_base_type'=>"PriceLevelPriceBase",'pr.price_level'=>"PriceLevel", + 'pr.price_base_type'=>"PriceBase",'pr.price_level'=>"PriceLevel", 'pr.price'=>"PriceLevelUnitPriceHT",'pr.price_ttc'=>"PriceLevelUnitPriceTTC", 'pr.price_min'=>"MinPriceLevelUnitPriceHT",'pr.price_min_ttc'=>"MinPriceLevelUnitPriceTTC", 'pr.tva_tx'=>'PriceLevelVATRate', 'pr.date_price'=>'DateCreation'); + if (is_object($mysoc) && $mysoc->useNPR()) $this->export_fields_array[$r]['pr.recuperableonly']='NPR'; //$this->export_TypeFields_array[$r]=array( // 'p.ref'=>"Text",'p.label'=>"Text",'p.description'=>"Text",'p.url'=>"Text",'p.accountancy_code_sell'=>"Text",'p.accountancy_code_buy'=>"Text", // 'p.note'=>"Text",'p.length'=>"Numeric",'p.surface'=>"Numeric",'p.volume'=>"Numeric",'p.weight'=>"Numeric",'p.customcode'=>'Text', @@ -226,15 +210,63 @@ class modService extends DolibarrModules 'pr.price_ttc'=>"product", 'pr.price_min'=>"product",'pr.price_min_ttc'=>"product", 'pr.tva_tx'=>'product', - 'pr.date_price'=>"product"); + 'pr.recuperableonly'=>'product', + 'pr.date_price'=>"product"); $this->export_sql_start[$r]='SELECT DISTINCT '; $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'product as p'; - $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product_price as pr ON p.rowid = pr.fk_product'; + $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product_price as pr ON p.rowid = pr.fk_product AND pr.entity = '.$conf->entity; // export prices only for the current entity $this->export_sql_end[$r] .=' WHERE p.fk_product_type = 0 AND p.entity IN ('.getEntity('product').')'; } + + if (! empty($conf->global->PRODUIT_SOUSPRODUITS)) + { + // Exports virtual products + $r++; + $this->export_code[$r]=$this->rights_class.'_'.$r; + $this->export_label[$r]="AssociatedProducts"; // Translation key (used only if key ExportDataset_xxx_z not found) + $this->export_permission[$r]=array(array("produit","export")); + $this->export_fields_array[$r]=array( + 'p.rowid'=>"Id",'p.ref'=>"Ref",'p.label'=>"Label",'p.description'=>"Description",'p.url'=>"PublicUrl", + 'p.accountancy_code_sell'=>"ProductAccountancySellCode",'p.accountancy_code_buy'=>"ProductAccountancyBuyCode",'p.note'=>"Note", + 'p.length'=>"Length",'p.surface'=>"Surface",'p.volume'=>"Volume",'p.weight'=>"Weight",'p.customcode'=>'CustomCode', + 'p.price_base_type'=>"PriceBase",'p.price'=>"UnitPriceHT",'p.price_ttc'=>"UnitPriceTTC",'p.tva_tx'=>'VATRate','p.tosell'=>"OnSell", + 'p.tobuy'=>"OnBuy",'p.datec'=>'DateCreation','p.tms'=>'DateModification' + ); + if (! empty($conf->stock->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('p.stock'=>'Stock','p.seuil_stock_alerte'=>'StockLimit','p.desiredstock'=>'DesiredStock','p.pmp'=>'PMPValue')); + if (! empty($conf->barcode->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('p.barcode'=>'BarCode')); + $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('pa.qty'=>'Qty','pa.incdec'=>'ComposedProductIncDecStock')); + $this->export_TypeFields_array[$r]=array( + 'p.ref'=>"Text",'p.label'=>"Text",'p.description'=>"Text",'p.url'=>"Text",'p.accountancy_code_sell'=>"Text",'p.accountancy_code_buy'=>"Text", + 'p.note'=>"Text",'p.length'=>"Numeric",'p.surface'=>"Numeric",'p.volume'=>"Numeric",'p.weight'=>"Numeric",'p.customcode'=>'Text', + 'p.price_base_type'=>"Text",'p.price'=>"Numeric",'p.price_ttc'=>"Numeric",'p.tva_tx'=>'Numeric','p.tosell'=>"Boolean",'p.tobuy'=>"Boolean", + 'p.datec'=>'Date','p.tms'=>'Date' + ); + if (! empty($conf->stock->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r],array('p.stock'=>'Numeric','p.seuil_stock_alerte'=>'Numeric','p.desiredstock'=>'Numeric','p.pmp'=>'Numeric','p.cost_price'=>'Numeric')); + if (! empty($conf->barcode->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r],array('p.barcode'=>'Text')); + $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r],array('pa.qty'=>'Numeric')); + $this->export_entities_array[$r]=array( + 'p.rowid'=>"virtualproduct",'p.ref'=>"virtualproduct",'p.label'=>"virtualproduct",'p.description'=>"virtualproduct",'p.url'=>"virtualproduct", + 'p.accountancy_code_sell'=>'virtualproduct','p.accountancy_code_buy'=>'virtualproduct','p.note'=>"virtualproduct",'p.length'=>"virtualproduct", + 'p.surface'=>"virtualproduct",'p.volume'=>"virtualproduct",'p.weight'=>"virtualproduct",'p.customcode'=>'virtualproduct', + 'p.price_base_type'=>"virtualproduct",'p.price'=>"virtualproduct",'p.price_ttc'=>"virtualproduct",'p.tva_tx'=>"virtualproduct", + 'p.tosell'=>"virtualproduct",'p.tobuy'=>"virtualproduct",'p.datec'=>"virtualproduct",'p.tms'=>"virtualproduct" + ); + if (! empty($conf->stock->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.stock'=>'virtualproduct','p.seuil_stock_alerte'=>'virtualproduct','p.desiredstock'=>'virtualproduct','p.pmp'=>'virtualproduct')); + if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.barcode'=>'virtualproduct')); + $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('pa.qty'=>"subproduct",'pa.incdec'=>'subproduct')); + $keyforselect='product'; $keyforelement='product'; $keyforaliasextra='extra'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; + $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('p2.rowid'=>"Id",'p2.ref'=>"Ref",'p2.label'=>"Label",'p2.description'=>"Description")); + $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p2.rowid'=>"subproduct",'p2.ref'=>"subproduct",'p2.label'=>"subproduct",'p2.description'=>"subproduct")); + $this->export_sql_start[$r]='SELECT DISTINCT '; + $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'product as p'; + $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product_extrafields as extra ON p.rowid = extra.fk_object,'; + $this->export_sql_end[$r] .=' '.MAIN_DB_PREFIX.'product_association as pa, '.MAIN_DB_PREFIX.'product as p2'; + $this->export_sql_end[$r] .=' WHERE p.fk_product_type = 0 AND p.entity IN ('.getEntity('product').')'; + $this->export_sql_end[$r] .=' AND p.rowid = pa.fk_product_pere AND p2.rowid = pa.fk_product_fils'; + } } - // Imports //-------- $r=0; @@ -250,11 +282,17 @@ class modService extends DolibarrModules 'p.ref'=>"Ref*",'p.label'=>"Label*",'p.description'=>"Description",'p.url'=>"PublicUrl",'p.accountancy_code_sell'=>"ProductAccountancySellCode", 'p.accountancy_code_buy'=>"ProductAccountancyBuyCode",'p.note'=>"Note",'p.length'=>"Length",'p.surface'=>"Surface",'p.volume'=>"Volume", 'p.weight'=>"Weight",'p.duration'=>"Duration",'p.customcode'=>'CustomCode','p.price'=>"SellingPriceHT",'p.price_ttc'=>"SellingPriceTTC", - 'p.tva_tx'=>'VAT','p.tosell'=>"OnSell*",'p.tobuy'=>"OnBuy*",'p.fk_product_type'=>"Type*",'p.finished'=>'Nature','p.datec'=>'DateCreation' + 'p.tva_tx'=>'VATRate','p.tosell'=>"OnSell*",'p.tobuy'=>"OnBuy*",'p.fk_product_type'=>"Type*",'p.finished'=>'Nature','p.datec'=>'DateCreation' ); - if (! empty($conf->barcode->enabled)) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r],array('p.barcode'=>'BarCode')); + //if (! empty($conf->stock->enabled)) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r],array('p.seuil_stock_alerte'=>'StockLimit','p.desiredstock'=>'DesiredStock','p.pmp'=>'PMPValue')); + if (! empty($conf->fournisseur->enabled) || !empty($conf->margin->enabled)) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r],array('p.cost_price'=>'CostPrice')); + if (is_object($mysoc) && $mysoc->useNPR()) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r],array('p.recuperableonly'=>'NPR')); + if (is_object($mysoc) && $mysoc->useLocalTax(1)) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r],array('p.localtax1_tx'=>'LT1', 'p.localtax1_type'=>'LT1Type')); + if (is_object($mysoc) && $mysoc->useLocalTax(2)) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r],array('p.localtax2_tx'=>'LT2', 'p.localtax2_type'=>'LT2Type')); + if (! empty($conf->barcode->enabled)) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r],array('p.barcode'=>'BarCode')); if (! empty($conf->global->PRODUCT_USE_UNITS)) $this->import_fields_array[$r]['p.fk_unit'] = 'Unit'; // Add extra fields + $import_extrafield_sample=array(); $sql="SELECT name, label, fieldrequired FROM ".MAIN_DB_PREFIX."extrafields WHERE elementtype = 'product' AND entity IN (0,".$conf->entity.")"; $resql=$this->db->query($sql); if ($resql) // This can fail when class is used on old database (during migration for example) @@ -264,13 +302,15 @@ class modService extends DolibarrModules $fieldname='extra.'.$obj->name; $fieldlabel=ucfirst($obj->label); $this->import_fields_array[$r][$fieldname]=$fieldlabel.($obj->fieldrequired?'*':''); + $import_extrafield_sample[$fieldname]=$fieldlabel; } } // End add extra fields $this->import_fieldshidden_array[$r]=array('extra.fk_object'=>'lastrowid-'.MAIN_DB_PREFIX.'product'); // aliastable.field => ('user->id' or 'lastrowid-'.tableparent) - $this->import_regex_array[$r]=array('p.ref'=>'[^ ]','p.tosell'=>'^[0|1]$','p.tobuy'=>'^[0|1]$','p.fk_product_type'=>'^[0|1]$','p.datec'=>'^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$'); - $this->import_examplevalues_array[$r]=array('p.ref'=>"PREF123456",'p.label'=>"My product",'p.description'=>"This is a description example for record",'p.note'=>"Some note",'p.price'=>"100",'p.price_ttc'=>"110",'p.tva_tx'=>'10','p.tosell'=>"0 or 1",'p.tobuy'=>"0 or 1",'p.fk_product_type'=>"0 for product/1 for service",'p.finished'=>'','p.duration'=>"1y",'p.datec'=>'2008-12-31'); - + $this->import_regex_array[$r]=array('p.ref'=>'[^ ]','p.tosell'=>'^[0|1]$','p.tobuy'=>'^[0|1]$','p.fk_product_type'=>'^[0|1]$','p.datec'=>'^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$','p.recuperableonly'=>'^[0|1]$'); + $import_sample=array('p.ref'=>"PREF123456",'p.label'=>"My product",'p.description'=>"This is a description example for record",'p.note'=>"Some note",'p.price'=>"100",'p.price_ttc'=>"110",'p.tva_tx'=>'10','p.tosell'=>"0 or 1",'p.tobuy'=>"0 or 1",'p.fk_product_type'=>"0 for product/1 for service",'p.finished'=>'','p.duration'=>"1y",'p.datec'=>'2008-12-31','p.recuperableonly'=>'0 or 1'); + $this->import_examplevalues_array[$r]=array_merge($import_sample,$import_extrafield_sample); + $this->import_updatekeys_array[$r]=array('p.ref'=>'Ref','p.barcode'=>'BarCode'); if (empty($conf->product->enabled)) // We enable next import templates only if module product not already enabled (to avoid duplicate entries) { @@ -301,12 +341,13 @@ class modService extends DolibarrModules 'sp.fk_soc'=>array('rule'=>'fetchidfromref','classfile'=>'/societe/class/societe.class.php','class'=>'Societe','method'=>'fetch','element'=>'ThirdParty'), 'sp.fk_product'=>array('rule'=>'fetchidfromref','classfile'=>'/product/class/product.class.php','class'=>'Product','method'=>'fetch','element'=>'Product') ); - $this->import_examplevalues_array[$r]=array('sp.fk_product'=>"PREF123456", + $this->import_examplevalues_array[$r]=array('sp.fk_product'=>"SERVICE_REF or id:123456", 'sp.fk_soc'=>"My Supplier",'sp.ref_fourn'=>"SupplierRef", 'sp.quantity'=>"1", 'sp.tva_tx'=>'21', 'sp.price'=>"50", 'sp.unitprice'=>'50', 'sp.remise_percent'=>'0' ); + $this->import_updatekeys_array[$r]=array('sp.fk_product'=>'ProductOrService','sp.ref_fourn'=>'SupplierRef','sp.fk_soc'=>'Supplier'); } if (! empty($conf->global->PRODUIT_MULTIPRICES)) @@ -319,18 +360,23 @@ class modService extends DolibarrModules $this->import_entities_array[$r]=array(); // We define here only fields that use another icon that the one defined into import_icon $this->import_tables_array[$r]=array('pr'=>MAIN_DB_PREFIX.'product_price'); $this->import_tables_creator_array[$r]=array('pr'=>'fk_user_author'); // Fields to store import user id - $this->import_fields_array[$r]=array('pr.fk_product'=>"ProductRowid*", - 'pr.price_base_type'=>"PriceLevelPriceBase",'pr.price_level'=>"PriceLevel", + $this->import_fields_array[$r]=array('pr.fk_product'=>"ProductOrService*", + 'pr.price_base_type'=>"PriceBase",'pr.price_level'=>"PriceLevel", 'pr.price'=>"PriceLevelUnitPriceHT",'pr.price_ttc'=>"PriceLevelUnitPriceTTC", 'pr.price_min'=>"MinPriceLevelUnitPriceHT",'pr.price_min_ttc'=>"MinPriceLevelUnitPriceTTC", - 'pr.tva_tx'=>'PriceLevelVATRate', 'pr.date_price'=>'DateCreation*'); - $this->import_regex_array[$r]=array('pr.datec'=>'^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$'); - $this->import_examplevalues_array[$r]=array('pr.fk_product'=>"1", - 'pr.price_base_type'=>"HT",'pr.price_level'=>"1", + if (! empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) $this->import_fields_array[$r]['pr.tva_tx']='VATRate'; + if (is_object($mysoc) && $mysoc->useNPR()) $this->import_fields_array[$r]=array_merge($this->import_fields_array[$r],array('pr.recuperableonly'=>'NPR')); + $this->import_regex_array[$r]=array('pr.datec'=>'^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$','pr.recuperableonly'=>'^[0|1]$'); + $this->import_convertvalue_array[$r]=array( + 'pr.fk_product'=>array('rule'=>'fetchidfromref','classfile'=>'/product/class/product.class.php','class'=>'Product','method'=>'fetch','element'=>'Product') + ); + $this->import_examplevalues_array[$r]=array('pr.fk_product'=>"SERVICE_REF or id:123456", + 'pr.price_base_type'=>"HT (for excl tax) or TTC (for inc tax)",'pr.price_level'=>"1", 'pr.price'=>"100",'pr.price_ttc'=>"110", 'pr.price_min'=>"100",'pr.price_min_ttc'=>"110", - 'pr.tva_tx'=>'19.6', + 'pr.tva_tx'=>'20', + 'pr.recuperableonly'=>'0', 'pr.date_price'=>'2013-04-10'); } @@ -343,13 +389,13 @@ class modService extends DolibarrModules $this->import_entities_array[$r]=array(); // We define here only fields that use another icon that the one defined into import_icon $this->import_tables_array[$r]=array('l'=>MAIN_DB_PREFIX.'product_lang'); // multiline translation, one line per translation - $this->import_fields_array[$r]=array('l.fk_product'=>'Ref', 'l.lang'=>'Language', 'l.label'=>'TranslatedLabel', 'l.description'=>'TranslatedDescription'); + $this->import_fields_array[$r]=array('l.fk_product'=>'ProductOrService*', 'l.lang'=>'Language*', 'l.label'=>'TranslatedLabel', 'l.description'=>'TranslatedDescription'); //$this->import_fields_array[$r]['l.note']='TranslatedNote'; $this->import_convertvalue_array[$r]=array( 'l.fk_product'=>array('rule'=>'fetchidfromref','classfile'=>'/product/class/product.class.php','class'=>'Product','method'=>'fetch','element'=>'Product') ); - $this->import_examplevalues_array[$r]=array('l.fk_product'=>'MyProductRef','l.lang'=>'en_US','l.label'=>'Label in en_US','l.description'=>'Desc in en_US'); - $this->import_updatekeys_array[$r]=array('l.fk_product'=>'Ref','l.lang'=>'Language'); + $this->import_examplevalues_array[$r]=array('l.fk_product'=>'SERVICE_REF or id:123456','l.lang'=>'en_US','l.label'=>'Label in en_US','l.description'=>'Desc in en_US'); + $this->import_updatekeys_array[$r]=array('l.fk_product'=>'ProductOrService','l.lang'=>'Language'); } } } From ef8bb1f5ca921da670672ad59e6d25aac6054892 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 29 Apr 2019 20:55:45 +0200 Subject: [PATCH 086/132] Add MAIN_DOLEDITOR_HEIGHT as quick hack to fix pb of too small area --- htdocs/core/tpl/objectline_create.tpl.php | 2 +- htdocs/core/tpl/objectline_edit.tpl.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index c949d73c060..26eb1504c42 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -316,7 +316,7 @@ else { if (! empty($conf->global->MAIN_INPUT_DESC_HEIGHT)) $nbrows=$conf->global->MAIN_INPUT_DESC_HEIGHT; $toolbarname='dolibarr_details'; if (! empty($conf->global->FCKEDITOR_ENABLE_DETAILS_FULL)) $toolbarname='dolibarr_notes'; - $doleditor=new DolEditor('dp_desc',GETPOST('dp_desc'),'',100,$toolbarname,'',false,true,$enabled,$nbrows,'98%'); + $doleditor=new DolEditor('dp_desc', GETPOST('dp_desc'), '', (empty($conf->global->MAIN_DOLEDITOR_HEIGHT)?100:$conf->global->MAIN_DOLEDITOR_HEIGHT), $toolbarname, '', false, true, $enabled, $nbrows, '98%'); $doleditor->Create(); // Show autofill date for recuring invoices diff --git a/htdocs/core/tpl/objectline_edit.tpl.php b/htdocs/core/tpl/objectline_edit.tpl.php index 05bfc3b106d..6ef1332fc72 100644 --- a/htdocs/core/tpl/objectline_edit.tpl.php +++ b/htdocs/core/tpl/objectline_edit.tpl.php @@ -113,7 +113,7 @@ $coldisplay=-1; // We remove first td $enable=(isset($conf->global->FCKEDITOR_ENABLE_DETAILS)?$conf->global->FCKEDITOR_ENABLE_DETAILS:0); $toolbarname='dolibarr_details'; if (! empty($conf->global->FCKEDITOR_ENABLE_DETAILS_FULL)) $toolbarname='dolibarr_notes'; - $doleditor=new DolEditor('product_desc',$line->description,'',164,$toolbarname,'',false,true,$enable,$nbrows,'98%'); + $doleditor=new DolEditor('product_desc', $line->description, '', (empty($conf->global->MAIN_DOLEDITOR_HEIGHT)?164:$conf->global->MAIN_DOLEDITOR_HEIGHT), $toolbarname, '', false, true, $enable, $nbrows, '98%'); $doleditor->Create(); } else { print ''; From d55c440740e3fff677580b08c2337b5544f24974 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 29 Apr 2019 21:23:01 +0200 Subject: [PATCH 087/132] Fix some product and services export profiles --- htdocs/core/modules/modProduct.class.php | 36 +++++++++++++++++++-- htdocs/core/modules/modService.class.php | 40 +++++++++++++++++++++--- htdocs/langs/en_US/products.lang | 3 +- 3 files changed, 72 insertions(+), 7 deletions(-) diff --git a/htdocs/core/modules/modProduct.class.php b/htdocs/core/modules/modProduct.class.php index cde60b3af7b..94e3d56cb12 100644 --- a/htdocs/core/modules/modProduct.class.php +++ b/htdocs/core/modules/modProduct.class.php @@ -245,7 +245,39 @@ class modProduct extends DolibarrModules $this->export_sql_start[$r]='SELECT DISTINCT '; $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'product as p'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product_price as pr ON p.rowid = pr.fk_product AND pr.entity = '.$conf->entity; // export prices only for the current entity - $this->export_sql_end[$r] .=' WHERE p.fk_product_type = 0 AND p.entity IN ('.getEntity('product').')'; + $this->export_sql_end[$r] .=' WHERE p.entity IN ('.getEntity('product').')'; // For product and service profile + } + + if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES)) + { + // Exports product multiprice + $r++; + $this->export_code[$r]=$this->rights_class.'_'.$r; + $this->export_label[$r]="ProductsPricePerCustomer"; // Translation key (used only if key ExportDataset_xxx_z not found) + $this->export_permission[$r]=array(array("produit","export")); + $this->export_fields_array[$r]=array('p.rowid'=>"Id",'p.ref'=>"Ref", + 's.nom'=>'ThirdParty', + 'pr.price_base_type'=>"PriceBase", + 'pr.price'=>"PriceUnitPriceHT",'pr.price_ttc'=>"PriceUnitPriceTTC", + 'pr.price_min'=>"MinPriceUnitPriceHT",'pr.price_min_ttc'=>"MinPriceUnitPriceTTC", + 'pr.tva_tx'=>'PriceVATRate', + 'pr.default_vat_code'=>'PriceVATCode', + 'pr.datec'=>'DateCreation'); + if (is_object($mysoc) && $mysoc->useNPR()) $this->export_fields_array[$r]['pr.recuperableonly']='NPR'; + $this->export_entities_array[$r]=array('p.rowid'=>"product",'p.ref'=>"product", + 's.nom'=>'company', + 'pr.price_base_type'=>"product",'pr.price'=>"product", + 'pr.price_ttc'=>"product", + 'pr.price_min'=>"product",'pr.price_min_ttc'=>"product", + 'pr.tva_tx'=>'product', + 'pr.default_vat_code'=>'product', + 'pr.recuperableonly'=>'product', + 'pr.datec'=>"product"); + $this->export_sql_start[$r]='SELECT DISTINCT '; + $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'product as p'; + $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product_customer_price as pr ON p.rowid = pr.fk_product AND pr.entity = '.$conf->entity; // export prices only for the current entity + $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe as s ON pr.fk_soc = s.rowid'; + $this->export_sql_end[$r] .=' WHERE p.entity IN ('.getEntity('product').')'; // For product and service profile } if (! empty($conf->global->PRODUIT_SOUSPRODUITS)) @@ -292,7 +324,7 @@ class modProduct extends DolibarrModules $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'product as p'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product_extrafields as extra ON p.rowid = extra.fk_object,'; $this->export_sql_end[$r] .=' '.MAIN_DB_PREFIX.'product_association as pa, '.MAIN_DB_PREFIX.'product as p2'; - $this->export_sql_end[$r] .=' WHERE p.fk_product_type = 0 AND p.entity IN ('.getEntity('product').')'; + $this->export_sql_end[$r] .=' WHERE p.entity IN ('.getEntity('product').')'; // For product and service profile $this->export_sql_end[$r] .=' AND p.rowid = pa.fk_product_pere AND p2.rowid = pa.fk_product_fils'; } diff --git a/htdocs/core/modules/modService.class.php b/htdocs/core/modules/modService.class.php index 3f7462ee463..9ff04f3fd71 100644 --- a/htdocs/core/modules/modService.class.php +++ b/htdocs/core/modules/modService.class.php @@ -182,7 +182,7 @@ class modService extends DolibarrModules if (! empty($conf->fournisseur->enabled)) $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product_fournisseur_price as pf ON pf.fk_product = p.rowid LEFT JOIN '.MAIN_DB_PREFIX.'societe s ON s.rowid = pf.fk_soc'; $this->export_sql_end[$r] .=' WHERE p.fk_product_type = 1 AND p.entity IN ('.getEntity('product').')'; if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_sql_order[$r] =' GROUP BY p.rowid'; // FIXME The group by used a generic value to say "all fields in select except function fields" - + if (empty($conf->product->enabled)) // We enable next import templates only if module product not already enabled (to avoid duplicate entries) { if (! empty($conf->global->PRODUIT_MULTIPRICES)) @@ -215,9 +215,41 @@ class modService extends DolibarrModules $this->export_sql_start[$r]='SELECT DISTINCT '; $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'product as p'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product_price as pr ON p.rowid = pr.fk_product AND pr.entity = '.$conf->entity; // export prices only for the current entity - $this->export_sql_end[$r] .=' WHERE p.fk_product_type = 0 AND p.entity IN ('.getEntity('product').')'; + $this->export_sql_end[$r] .=' WHERE p.entity IN ('.getEntity('product').')'; } - + + if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES)) + { + // Exports product multiprice + $r++; + $this->export_code[$r]=$this->rights_class.'_'.$r; + $this->export_label[$r]="ProductsPricePerCustomer"; // Translation key (used only if key ExportDataset_xxx_z not found) + $this->export_permission[$r]=array(array("produit","export")); + $this->export_fields_array[$r]=array('p.rowid'=>"Id",'p.ref'=>"Ref", + 's.nom'=>'ThirdParty', + 'pr.price_base_type'=>"PriceBase", + 'pr.price'=>"PriceUnitPriceHT",'pr.price_ttc'=>"PriceUnitPriceTTC", + 'pr.price_min'=>"MinPriceUnitPriceHT",'pr.price_min_ttc'=>"MinPriceUnitPriceTTC", + 'pr.tva_tx'=>'PriceVATRate', + 'pr.default_vat_code'=>'PriceVATCode', + 'pr.datec'=>'DateCreation'); + if (is_object($mysoc) && $mysoc->useNPR()) $this->export_fields_array[$r]['pr.recuperableonly']='NPR'; + $this->export_entities_array[$r]=array('p.rowid'=>"product",'p.ref'=>"product", + 's.nom'=>'company', + 'pr.price_base_type'=>"product",'pr.price'=>"product", + 'pr.price_ttc'=>"product", + 'pr.price_min'=>"product",'pr.price_min_ttc'=>"product", + 'pr.tva_tx'=>'product', + 'pr.default_vat_code'=>'product', + 'pr.recuperableonly'=>'product', + 'pr.datec'=>"product"); + $this->export_sql_start[$r]='SELECT DISTINCT '; + $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'product as p'; + $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product_customer_price as pr ON p.rowid = pr.fk_product AND pr.entity = '.$conf->entity; // export prices only for the current entity + $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'societe as s ON pr.fk_soc = s.rowid'; + $this->export_sql_end[$r] .=' WHERE p.entity IN ('.getEntity('product').')'; + } + if (! empty($conf->global->PRODUIT_SOUSPRODUITS)) { // Exports virtual products @@ -262,7 +294,7 @@ class modService extends DolibarrModules $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'product as p'; $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product_extrafields as extra ON p.rowid = extra.fk_object,'; $this->export_sql_end[$r] .=' '.MAIN_DB_PREFIX.'product_association as pa, '.MAIN_DB_PREFIX.'product as p2'; - $this->export_sql_end[$r] .=' WHERE p.fk_product_type = 0 AND p.entity IN ('.getEntity('product').')'; + $this->export_sql_end[$r] .=' WHERE p.entity IN ('.getEntity('product').')'; $this->export_sql_end[$r] .=' AND p.rowid = pa.fk_product_pere AND p2.rowid = pa.fk_product_fils'; } } diff --git a/htdocs/langs/en_US/products.lang b/htdocs/langs/en_US/products.lang index 80955c0a74e..8a96e062203 100644 --- a/htdocs/langs/en_US/products.lang +++ b/htdocs/langs/en_US/products.lang @@ -337,4 +337,5 @@ CloneDestinationReference=Destination product reference ErrorCopyProductCombinations=There was an error while copying the product variants ErrorDestinationProductNotFound=Destination product not found ErrorProductCombinationNotFound=Product variant not found -ActionAvailableOnVariantProductOnly=Action only available on the variant of product \ No newline at end of file +ActionAvailableOnVariantProductOnly=Action only available on the variant of product +ProductsPricePerCustomer=Product prices per customers \ No newline at end of file From c12a16abea49f48f4ff0ebcc69abb57bda5421da Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 30 Apr 2019 02:49:13 +0200 Subject: [PATCH 088/132] Fix trans --- htdocs/langs/en_US/companies.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/companies.lang b/htdocs/langs/en_US/companies.lang index 7931f6ec3b6..ae189111c15 100644 --- a/htdocs/langs/en_US/companies.lang +++ b/htdocs/langs/en_US/companies.lang @@ -28,7 +28,7 @@ AliasNames=Alias name (commercial, trademark, ...) AliasNameShort=Alias Name Companies=Companies CountryIsInEEC=Country is inside the European Economic Community -PriceFormatInCurrentLanguage=Price format in current language +PriceFormatInCurrentLanguage=Price display format in the current language and currency ThirdPartyName=Third-party name ThirdPartyEmail=Third-party email ThirdParty=Third-party From f50210ef39575f6471f95962cf178477b1020f2d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 30 Apr 2019 03:07:20 +0200 Subject: [PATCH 089/132] Fix idempotency_key --- htdocs/stripe/class/stripe.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index 54737791032..d604dcdd3f2 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -589,7 +589,7 @@ class Stripe extends CommonObject $paymentarray["receipt_email"] = $societe->email; } - $charge = \Stripe\Charge::create($paymentarray, array("idempotency_key" => "$ref")); + $charge = \Stripe\Charge::create($paymentarray, array("idempotency_key" => "$description")); } } else { $fee = round(($object->total_ttc * ($conf->global->STRIPE_APPLICATION_FEE_PERCENT / 100) + $conf->global->STRIPE_APPLICATION_FEE) * 100); @@ -619,7 +619,7 @@ class Stripe extends CommonObject $paymentarray["receipt_email"] = $societe->email; } - $charge = \Stripe\Charge::create($paymentarray, array("idempotency_key" => "$ref","stripe_account" => "$account")); + $charge = \Stripe\Charge::create($paymentarray, array("idempotency_key" => "$description", "stripe_account" => "$account")); } if (isset($charge->id)) {} From acfc251253226ab5a0a7d8b3ab2c0434001730df Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 30 Apr 2019 03:09:54 +0200 Subject: [PATCH 090/132] Fix idempotency key --- htdocs/public/payment/newpayment.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index 69f2d96c8c2..f06228291ef 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -486,7 +486,7 @@ if ($action == 'charge' && ! empty($conf->stripe->enabled)) 'customer' => $customer->id, 'source' => $card, 'statement_descriptor' => dol_trunc($FULLTAG, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description) - ), array("idempotency_key" => "$ref", "stripe_account" => "$stripeacc")); + ), array("idempotency_key" => "$FULLTAG", "stripe_account" => "$stripeacc")); // Return $charge = array('id'=>'ch_XXXX', 'status'=>'succeeded|pending|failed', 'failure_code'=>, 'failure_message'=>...) if (empty($charge)) { @@ -534,7 +534,7 @@ if ($action == 'charge' && ! empty($conf->stripe->enabled)) 'description' => 'Stripe payment: '.$FULLTAG.' ref='.$ref, 'metadata' => $metadata, 'statement_descriptor' => dol_trunc($FULLTAG, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description) - ), array("idempotency_key" => "$ref", "stripe_account" => "$stripeacc")); + ), array("idempotency_key" => "$FULLTAG", "stripe_account" => "$stripeacc")); // Return $charge = array('id'=>'ch_XXXX', 'status'=>'succeeded|pending|failed', 'failure_code'=>, 'failure_message'=>...) if (empty($charge)) { From f2ecdac4543cb0e84637d9da20dd5bcd35291fef Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 30 Apr 2019 03:07:20 +0200 Subject: [PATCH 091/132] Fix idempotency_key Conflicts: htdocs/stripe/class/stripe.class.php --- htdocs/stripe/class/stripe.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index d8e7168e5c0..97bf463bd97 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -452,7 +452,7 @@ class Stripe extends CommonObject $paymentarray["receipt_email"] = $societe->email; } - $charge = \Stripe\Charge::create($paymentarray, array("idempotency_key" => "$ref")); + $charge = \Stripe\Charge::create($paymentarray, array("idempotency_key" => "$description")); } } else { @@ -480,7 +480,7 @@ class Stripe extends CommonObject $paymentarray["receipt_email"] = $societe->email; } - $charge = \Stripe\Charge::create($paymentarray, array("idempotency_key" => "$ref","stripe_account" => "$account")); + $charge = \Stripe\Charge::create($paymentarray, array("idempotency_key" => "$description", "stripe_account" => "$account")); } if (isset($charge->id)) {} From f8f40a9239a979714181e1b229b17b3ea9e86177 Mon Sep 17 00:00:00 2001 From: BENKE Charlene <1179011+defrance@users.noreply.github.com> Date: Tue, 30 Apr 2019 11:27:33 +0200 Subject: [PATCH 092/132] planned_timespent not present on task duration is the good one --- htdocs/core/modules/project/doc/pdf_timespent.modules.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/modules/project/doc/pdf_timespent.modules.php b/htdocs/core/modules/project/doc/pdf_timespent.modules.php index 007bf9c8e1d..2c69fbd6bab 100644 --- a/htdocs/core/modules/project/doc/pdf_timespent.modules.php +++ b/htdocs/core/modules/project/doc/pdf_timespent.modules.php @@ -260,7 +260,7 @@ class pdf_timespent extends ModelePDFProjects //$progress=($object->lines[$i]->progress?$object->lines[$i]->progress.'%':''); $datestart=dol_print_date($object->lines[$i]->date_start, 'day'); $dateend=dol_print_date($object->lines[$i]->date_end, 'day'); - $planned_timespent=convertSecondToTime((int) $object->lines[$i]->planned_timespent, 'allhourmin'); + $duration=convertSecondToTime((int) $object->lines[$i]->duration, 'allhourmin'); $showpricebeforepagebreak=1; @@ -348,7 +348,7 @@ class pdf_timespent extends ModelePDFProjects $pdf->MultiCell($this->posxlabel-$this->posxref, 3, $outputlangs->convToOutputCharset($ref), 0, 'L'); // timespent $pdf->SetXY($this->posxtimespent, $curY); - $pdf->MultiCell($this->posxdatestart-$this->posxtimespent, 3, $planned_timespent?$planned_timespent:'', 0, 'R'); + $pdf->MultiCell($this->posxdatestart-$this->posxtimespent, 3, $duration?$duration:'', 0, 'R'); // Progress //$pdf->SetXY($this->posxprogress, $curY); //$pdf->MultiCell($this->posxdatestart-$this->posxprogress, 3, $progress, 0, 'R'); From 0cd1fc79f22965af9f7251dd19135af0c885b7aa Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 30 Apr 2019 13:05:13 +0200 Subject: [PATCH 093/132] NEW Add a security permission to edit php dynamic content on website. --- htdocs/core/modules/modWebsite.class.php | 8 +++++++- htdocs/langs/en_US/website.lang | 1 + htdocs/website/index.php | 12 ++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/htdocs/core/modules/modWebsite.class.php b/htdocs/core/modules/modWebsite.class.php index 6f882f082ad..24a929c82a0 100644 --- a/htdocs/core/modules/modWebsite.class.php +++ b/htdocs/core/modules/modWebsite.class.php @@ -92,12 +92,18 @@ class modWebsite extends DolibarrModules $r++; $this->rights[$r][0] = 10002; - $this->rights[$r][1] = 'Create/modify website content'; + $this->rights[$r][1] = 'Create/modify website content (html and javascript content)'; $this->rights[$r][3] = 0; $this->rights[$r][4] = 'write'; $r++; $this->rights[$r][0] = 10003; + $this->rights[$r][1] = 'Create/modify website content (dynamic php code). Dangerous, must be reserved to restricted developers.'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'writephp'; + $r++; + + $this->rights[$r][0] = 10005; $this->rights[$r][1] = 'Delete website content'; $this->rights[$r][3] = 0; $this->rights[$r][4] = 'delete'; diff --git a/htdocs/langs/en_US/website.lang b/htdocs/langs/en_US/website.lang index f20aab8c0a7..4655bf3493a 100644 --- a/htdocs/langs/en_US/website.lang +++ b/htdocs/langs/en_US/website.lang @@ -97,3 +97,4 @@ ThisPageHasTranslationPages=This page/container has translation NoWebSiteCreateOneFirst=No website has been created yet. Create one first. GoTo=Go to DynamicPHPCodeContainsAForbiddenInstruction=You add dynamic PHP code that contains the PHP instruction '%s' that is forbidden by default as dynamic content (see hidden options WEBSITE_PHP_ALLOW_xxx to increase list of allowed commands). +NotAllowedToAddDynamicContent=You don't have permission to add or edit PHP dynamic content in websites. Ask permission or just keep code into php tags unmodified. \ No newline at end of file diff --git a/htdocs/website/index.php b/htdocs/website/index.php index 49859101ea9..2099102cced 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -1448,6 +1448,8 @@ if (($action == 'updatesource' || $action == 'updatecontent' || $action == 'conf { $db->begin(); + $phpfullcodestringold = dolKeepOnlyPhpCode($objectpage->content); + $objectpage->content = GETPOST('PAGE_CONTENT', 'none'); // Security analysis @@ -1469,6 +1471,16 @@ if (($action == 'updatesource' || $action == 'updatecontent' || $action == 'conf } } + if (empty($user->rights->website->writephp)) + { + if ($phpfullcodestringold != $phpfullcodestring) + { + $error++; + setEventMessages($langs->trans("NotAllowedToAddDynamicContent"), null, 'errors'); + if ($action == 'updatesource') $action = 'editsource'; + if ($action == 'updatecontent') $action = 'editcontent'; + } + } // Clean data. We remove all the head section. $objectpage->content = preg_replace('/.*<\/head>/ims', '', $objectpage->content); From feb0800208894ec4b855a624fdf82f81d0da80d6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 30 Apr 2019 13:50:03 +0200 Subject: [PATCH 094/132] Fix loading of website page object not done for home page --- htdocs/core/website.inc.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/htdocs/core/website.inc.php b/htdocs/core/website.inc.php index 93ae53dc461..138f96fc7f3 100644 --- a/htdocs/core/website.inc.php +++ b/htdocs/core/website.inc.php @@ -25,6 +25,8 @@ // Load website class include_once DOL_DOCUMENT_ROOT.'/website/class/website.class.php'; +include_once DOL_DOCUMENT_ROOT.'/website/class/websitepage.class.php'; + // Define $website if (! is_object($website)) { @@ -40,11 +42,14 @@ if (! is_object($weblangs)) if (! $pageid && ! empty($websitepagefile)) { $pageid = str_replace(array('.tpl.php', 'page'), array('', ''), basename($websitepagefile)); + if ($pageid == 'index.php') $pageid = $website->fk_default_home; +} +if (! is_object($websitepage)) +{ + $websitepage=new WebsitePage($db); } if ($pageid > 0) { - include_once DOL_DOCUMENT_ROOT.'/website/class/websitepage.class.php'; - $websitepage=new WebsitePage($db); $websitepage->fetch($pageid); } From 203998a2c7a207f1af39996ae10f67c58d646415 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 30 Apr 2019 13:51:04 +0200 Subject: [PATCH 095/132] Fix loading of website page object not done for home page --- htdocs/core/website.inc.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/core/website.inc.php b/htdocs/core/website.inc.php index 138f96fc7f3..e09cf08480b 100644 --- a/htdocs/core/website.inc.php +++ b/htdocs/core/website.inc.php @@ -48,6 +48,7 @@ if (! is_object($websitepage)) { $websitepage=new WebsitePage($db); } + if ($pageid > 0) { $websitepage->fetch($pageid); From b13bc0e698ce0a0577b33ae66e2e2c4e4c89f5e1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 30 Apr 2019 13:50:03 +0200 Subject: [PATCH 096/132] Fix loading of website page object not done for home page --- htdocs/core/website.inc.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/htdocs/core/website.inc.php b/htdocs/core/website.inc.php index 1338104de0b..4a2b267fe3a 100644 --- a/htdocs/core/website.inc.php +++ b/htdocs/core/website.inc.php @@ -25,6 +25,8 @@ // Load website class include_once DOL_DOCUMENT_ROOT.'/website/class/website.class.php'; +include_once DOL_DOCUMENT_ROOT.'/website/class/websitepage.class.php'; + // Define $website if (! is_object($website)) { @@ -40,11 +42,14 @@ if (! is_object($weblangs)) if (! $pageid && ! empty($websitepagefile)) { $pageid = str_replace(array('.tpl.php', 'page'), array('', ''), basename($websitepagefile)); + if ($pageid == 'index.php') $pageid = $website->fk_default_home; +} +if (! is_object($websitepage)) +{ + $websitepage=new WebsitePage($db); } if ($pageid > 0) { - include_once DOL_DOCUMENT_ROOT.'/website/class/websitepage.class.php'; - $websitepage=new WebsitePage($db); $websitepage->fetch($pageid); } From d9a1c2b235bf574c714b7be9b5f37583a164320b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Tue, 30 Apr 2019 13:54:50 +0200 Subject: [PATCH 097/132] Fix do not delete all discount when splitting --- htdocs/comm/remx.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/htdocs/comm/remx.php b/htdocs/comm/remx.php index a66e8e66500..eb1c14a4beb 100644 --- a/htdocs/comm/remx.php +++ b/htdocs/comm/remx.php @@ -1,7 +1,8 @@ - * Copyright (C) 2004-2012 Laurent Destailleur - * Copyright (C) 2008 Raphael Bertrand (Resultic) +/* Copyright (C) 2001-2004 Rodolphe Quiedeville + * Copyright (C) 2004-2012 Laurent Destailleur + * Copyright (C) 2008 Raphael Bertrand (Resultic) + * Copyright (C) 2019 Frédéric France * * 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 @@ -127,6 +128,8 @@ if ($action == 'confirm_split' && GETPOST("confirm") == 'yes') $db->begin(); $discount->fk_facture_source=0; // This is to delete only the require record (that we will recreate with two records) and not all family with same fk_facture_source + // This is to delete only the require record (that we will recreate with two records) and not all family with same fk_invoice_supplier_source + $discount->fk_invoice_supplier_source=0; $res=$discount->delete($user); $newid1=$newdiscount1->create($user); $newid2=$newdiscount2->create($user); From 2136bce4b052bca83c79e82055fee83cc16581c5 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 30 Apr 2019 15:10:38 +0200 Subject: [PATCH 098/132] FIX missing situation invoice in list --- htdocs/compta/facture/card.php | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index ebc4695dde8..82b876666db 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -1326,7 +1326,7 @@ if (empty($reshook)) } elseif ($typeamount=='variable') { $descline.= ' ('. $valuedeposit.'%)'; } - + $descline.= ' - '.$srcobject->ref; $result = $object->addline( $descline, @@ -2952,7 +2952,7 @@ if ($action == 'create') { // First situation invoice print '
'; - $tmp=' '; + $tmp=' '; $tmp = $tmp.''; $desc = $form->textwithpicto($tmp, $langs->transnoentities("InvoiceFirstSituationDesc"), 1, 'help', '', 0, 3); print $desc; @@ -3007,7 +3007,23 @@ if ($action == 'create') } else { - print '
'; + print '
'; + $tmp=' '; + $text = ' '; + $text.= '('.$langs->trans("YouMustCreateInvoiceFromThird").') '; + $desc = $form->textwithpicto($text, $langs->transnoentities("InvoiceFirstSituationDesc"), 1, 'help', '', 0, 3); + print $desc; + print '
'; + + print '
'; + $tmp=' '; + $text = ' '; + $text.= '('.$langs->trans("YouMustCreateInvoiceFromThird").') '; + $desc = $form->textwithpicto($text, $langs->transnoentities("InvoiceFirstSituationDesc"), 1, 'help', '', 0, 3); + print $desc; + print '
'; + + print '
'; $tmp=' '; $text = ' '; $text.= '('.$langs->trans("YouMustCreateInvoiceFromThird").') '; From 9c45b781af9446be13f5760848d7250b9387bda7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 30 Apr 2019 16:44:11 +0200 Subject: [PATCH 099/132] Fix balance of colspan --- htdocs/compta/facture/card.php | 33 ++++++----------------- htdocs/core/class/commonobject.class.php | 2 ++ htdocs/core/tpl/objectline_create.tpl.php | 2 ++ htdocs/core/tpl/objectline_edit.tpl.php | 29 +++++++++++--------- htdocs/core/tpl/objectline_view.tpl.php | 5 +++- htdocs/theme/eldy/global.inc.php | 2 +- 6 files changed, 34 insertions(+), 39 deletions(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 5e3873a83bc..cf27f54a82b 100755 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -4457,7 +4457,9 @@ elseif ($id > 0 || ! empty($ref)) // Show global modifiers if (! empty($conf->global->INVOICE_USE_SITUATION)) { - if ($object->situation_cycle_ref && $object->statut == 0) { + if ($object->situation_cycle_ref && $object->statut == 0) + { + print ''."\n"; print '
'; print '
'; @@ -4473,38 +4475,19 @@ elseif ($id > 0 || ! empty($ref)) if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) { print '
'; } - print ''; - print ''; - print ''; - if ($inputalsopricewithtax) print ''; - print ''; - print ''; - print ''; - if (! empty($conf->margin->enabled) && empty($user->societe_id)) - { - print ''; - if ((! empty($conf->global->DISPLAY_MARGIN_RATES) || ! empty($conf->global->DISPLAY_MARK_RATES)) && $usercanreadallmargin) { - print ''; - } - } - print ''; + print ''; + print ''; print ''; - print ''; - print ''; print "\n"; + print ''; // Adds a line numbering column if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) { - print ''; + print ''; } - print ''; print ''; - print ''; - print ''; - print ''; - print ''; print ''; - print ''; + print ''; print ''; print '
'; - print $facturestatic->getNomUrl(1, '', 200, 0, '', 0, 1); + if ($contextpage == 'poslist') + { + print $obj->ref; + } + else + { + print $facturestatic->getNomUrl(1, '', 200, 0, '', 0, 1); + } print empty($obj->increment)?'':' ('.$obj->increment.')'; $filename=dol_sanitizeFileName($obj->ref); diff --git a/htdocs/langs/en_US/cashdesk.lang b/htdocs/langs/en_US/cashdesk.lang index 4c71ce4b564..dd077e54045 100644 --- a/htdocs/langs/en_US/cashdesk.lang +++ b/htdocs/langs/en_US/cashdesk.lang @@ -61,4 +61,5 @@ NoPaimementModesDefined=No paiment mode defined in TakePOS configuration TicketVatGrouped=Group VAT by rate in tickets AutoPrintTickets=Automatically print tickets EnableBarOrRestaurantFeatures=Enable features for Bar or Restaurant -ConfirmDeletionOfThisPOSSale=Do your confirm the deletion of this current sale ? \ No newline at end of file +ConfirmDeletionOfThisPOSSale=Do your confirm the deletion of this current sale ? +History=History \ No newline at end of file diff --git a/htdocs/takepos/invoice.php b/htdocs/takepos/invoice.php index 09a60ffc3e9..2fc99b1a587 100644 --- a/htdocs/takepos/invoice.php +++ b/htdocs/takepos/invoice.php @@ -171,6 +171,13 @@ if ($action == 'valid' && $user->rights->facture->creer) } } +if ($action == 'history') +{ + $placeid = GETPOST('placeid', 'int'); + $invoice = new Facture($db); + $invoice->fetch($placeid); +} + if (($action=="addline" || $action=="freezone") && $placeid == 0) { $invoice->socid = $conf->global->CASHDESK_ID_THIRDPARTY; @@ -336,7 +343,7 @@ if ($action == "order" and $placeid != 0) } $sectionwithinvoicelink=''; -if ($action=="valid") +if ($action=="valid" || $action=="history") { $sectionwithinvoicelink.=''."\n"; $sectionwithinvoicelink.=''; diff --git a/htdocs/takepos/takepos.php b/htdocs/takepos/takepos.php index e5991b50702..143c6abf063 100644 --- a/htdocs/takepos/takepos.php +++ b/htdocs/takepos/takepos.php @@ -352,6 +352,12 @@ function Customer() { $.colorbox({href:"../societe/list.php?contextpage=poslist&nomassaction=1&place="+place, width:"90%", height:"80%", transition:"none", iframe:"true", title:"trans("Customer");?>"}); } +function History() +{ + console.log("Open box to select the history"); + $.colorbox({href:"../compta/facture/list.php?contextpage=poslist", width:"90%", height:"80%", transition:"none", iframe:"true", title:"trans("History");?>"}); +} + function CloseBill() { invoiceid = $("#invoiceid").val(); console.log("Open popup to enter payment on invoiceid="+invoiceid); @@ -607,6 +613,7 @@ else } $menus[$r++]=array('title'=>'
'.$langs->trans("Customer").'
', 'action'=>'Customer();'); +$menus[$r++]=array('title'=>'
'.$langs->trans("History").'
', 'action'=>'History();'); $menus[$r++]=array('title'=>'
'.$langs->trans("FreeZone").'
', 'action'=>'FreeZone();'); $menus[$r++]=array('title'=>'
'.$langs->trans("Payment").'
', 'action'=>'CloseBill();'); From 8f6f3d764f6661247e6b05100706dae91ac70575 Mon Sep 17 00:00:00 2001 From: Ludovic Canivet Date: Mon, 29 Apr 2019 10:58:00 +0200 Subject: [PATCH 070/132] Display category/Severity/type label instead of code --- htdocs/ticket/list.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/ticket/list.php b/htdocs/ticket/list.php index 989bbda8072..3cd594b3eb9 100644 --- a/htdocs/ticket/list.php +++ b/htdocs/ticket/list.php @@ -629,6 +629,9 @@ while ($i < min($num, $limit)) if ($cssforfield || $val['css']) print '"'; print '>'; if ($key == 'fk_statut') print $object->getLibStatut(5); + elseif ($key == 'category_code') print $langs->getLabelFromKey($db, $object->category_code, 'c_ticket_category', 'code', 'label'); + elseif ($key == 'severity_code') print $langs->getLabelFromKey($db, $object->severity_code, 'c_ticket_severity', 'code', 'label'); + elseif ($key == 'type_code') print $langs->getLabelFromKey($db, $object->type_code, 'c_ticket_type', 'code', 'label'); elseif (in_array($val['type'], array('date','datetime','timestamp'))) print $object->showOutputField($val, $key, $db->jdate($obj->$key), ''); else print $object->showOutputField($val, $key, $obj->$key, ''); print '
'.$ruleaction['actionparam'].''; + if ($action == 'editoperation' && $ruleaction['id'] == $operationid) + { + print '
'; + print '
'; + print ' '; + } + else + { + print $ruleaction['actionparam']; + } + print '
'; if ($i > 0) @@ -577,6 +609,8 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print ''; + print ' '.img_edit().''; + print '   '; print ' '.img_delete().''; print '
'; if ($obj->socid) { - $socstatic->id=$obj->socid; - $socstatic->name=$obj->name; print $socstatic->getNomUrl(1); } else From 5f54bd250c0c88a4ab06c4b0659dc6c153018919 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 29 Apr 2019 17:21:27 +0200 Subject: [PATCH 079/132] Suuport SETIFEMPTY flag --- .../class/emailcollector.class.php | 43 +++++++++++-------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index eea1a7a6132..710afc05cec 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -804,29 +804,36 @@ class EmailCollector extends CommonObject $this->errors[] = $this->error; } } - elseif (preg_match('/^SET:(.*)$/', $valueforproperty, $reg)) + elseif (preg_match('/^(SET|SETIFEMPTY):(.*)$/', $valueforproperty, $regforregex)) { - $valuetouse = $reg[1]; - $substitutionarray=array(); - $matcharray=array(); - preg_match_all('/__([a-z0-9]+(?:_[a-z0-9]+)?)__/i', $valuetouse, $matcharray); - //var_dump($tmpproperty.' - '.$object->$tmpproperty.' - '.$valuetouse); var_dump($matcharray); - if (is_array($matcharray[1])) // $matcharray[1] is array with list of substitution key found without the __ + $valuecurrent=''; + if (preg_match('/^options_/', $tmpproperty)) $valuecurrent = $object->array_options[preg_replace('/^options_/', '', $tmpproperty)]; + else $valuecurrent = $object->$tmpproperty; + + if ($regforregex[1] == 'SET' || empty($valuecurrent)) { - foreach($matcharray[1] as $keytoreplace) + $valuetouse = $regforregex[2]; + $substitutionarray=array(); + $matcharray=array(); + preg_match_all('/__([a-z0-9]+(?:_[a-z0-9]+)?)__/i', $valuetouse, $matcharray); + //var_dump($tmpproperty.' - '.$object->$tmpproperty.' - '.$valuetouse); var_dump($matcharray); + if (is_array($matcharray[1])) // $matcharray[1] is array with list of substitution key found without the __ { - if ($keytoreplace && isset($object->$keytoreplace)) + foreach($matcharray[1] as $keytoreplace) { - $substitutionarray['__'.$keytoreplace.'__']=$object->$keytoreplace; + if ($keytoreplace && isset($object->$keytoreplace)) + { + $substitutionarray['__'.$keytoreplace.'__']=$object->$keytoreplace; + } } } + //var_dump($substitutionarray); + dol_syslog(var_export($substitutionarray, true)); + //var_dump($substitutionarray); + $valuetouse = make_substitutions($valuetouse, $substitutionarray); + if (preg_match('/^options_/', $tmpproperty)) $object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $valuetouse; + else $object->$tmpproperty = $valuetouse; } - //var_dump($substitutionarray); - dol_syslog(var_export($substitutionarray, true)); - //var_dump($substitutionarray); - $valuetouse = make_substitutions($valuetouse, $substitutionarray); - if (preg_match('/^options_/', $tmpproperty)) $object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $valuetouse; - else $object->$tmpproperty = $valuetouse; } else { @@ -1391,11 +1398,11 @@ class EmailCollector extends CommonObject $this->errors[] = $this->error; } } - elseif (preg_match('/^SET:(.*)$/', $valueforproperty, $reg)) + elseif (preg_match('/^(SET|SETIFEMPTY):(.*)$/', $valueforproperty, $reg)) { //if (preg_match('/^options_/', $tmpproperty)) $object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $reg[1]; //else $object->$tmpproperty = $reg[1]; - $nametouseforthirdparty = $reg[1]; + $nametouseforthirdparty = $reg[2]; } else { From 3393aba85f51fef8560065dca2d6fc71457b3b21 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 29 Apr 2019 18:19:56 +0200 Subject: [PATCH 080/132] Fix autocopy on projects --- htdocs/projet/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index c1e40b9ffec..dbb12e32ebf 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -450,7 +450,7 @@ if (empty($reshook)) // Actions to send emails $trigger_name='PROJECT_SENTBYMAIL'; $paramname='id'; - $autocopy='MAIN_MAIL_AUTOCOPY_ORDER_TO'; // used to know the automatic BCC to add + $autocopy='MAIN_MAIL_AUTOCOPY_PROJECT_TO'; // used to know the automatic BCC to add $trackid='proj'.$object->id; include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php'; } From 899f41d68ca5a1321f2165264d7a0cbc4f7381b7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 29 Apr 2019 18:26:27 +0200 Subject: [PATCH 081/132] Fix bad constant MAIN_MAIL_AUTOCOPY into email form of project page. --- htdocs/projet/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php index 56646a1a470..cf0131ef53f 100644 --- a/htdocs/projet/card.php +++ b/htdocs/projet/card.php @@ -450,7 +450,7 @@ if (empty($reshook)) // Actions to send emails $trigger_name='PROJECT_SENTBYMAIL'; $paramname='id'; - $autocopy='MAIN_MAIL_AUTOCOPY_ORDER_TO'; // used to know the automatic BCC to add + $autocopy='MAIN_MAIL_AUTOCOPY_PROJECT_TO'; // used to know the automatic BCC to add $trackid='proj'.$object->id; include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php'; } From 627ef1445433e98d2ef420bfb9ae51983659b911 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 29 Apr 2019 18:51:15 +0200 Subject: [PATCH 082/132] FIX The autocopy feature was ko for suppliers --- htdocs/core/actions_massactions.inc.php | 1 + htdocs/core/class/html.formmail.class.php | 5 ++++- htdocs/fourn/commande/card.php | 1 + htdocs/fourn/facture/card.php | 1 + htdocs/projet/card.php | 1 + htdocs/supplier_proposal/card.php | 1 + 6 files changed, 9 insertions(+), 1 deletion(-) diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index da852b8a46d..910f9eca27a 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -344,6 +344,7 @@ if (! $error && $massaction == 'confirm_presend') if ($objectclass == 'Supplier_Proposal') $sendtobcc .= (empty($conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_PROPOSAL_TO) ? '' : (($sendtobcc?", ":"").$conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_PROPOSAL_TO)); if ($objectclass == 'CommandeFournisseur') $sendtobcc .= (empty($conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_ORDER_TO) ? '' : (($sendtobcc?", ":"").$conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_ORDER_TO)); if ($objectclass == 'FactureFournisseur') $sendtobcc .= (empty($conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_INVOICE_TO) ? '' : (($sendtobcc?", ":"").$conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_INVOICE_TO)); + if ($objectclass == 'Project') $sendtobcc .= (empty($conf->global->MAIN_MAIL_AUTOCOPY_PROJECT_TO) ? '' : (($sendtobcc?", ":"").$conf->global->MAIN_MAIL_AUTOCOPY_PROJECT_TO)); // $listofqualifiedobj is array with key = object id and value is instance of qualified objects, for the current thirdparty (but thirdparty property is not loaded yet) // $looparray will be an array with number of email to send for the current thirdparty (so 1 or n if n object for same thirdparty) diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index c42acac2549..bf03477643b 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -779,9 +779,12 @@ class FormMail extends Form $showinfobcc=''; if (! empty($conf->global->MAIN_MAIL_AUTOCOPY_PROPOSAL_TO) && ! empty($this->param['models']) && $this->param['models'] == 'propal_send') $showinfobcc=$conf->global->MAIN_MAIL_AUTOCOPY_PROPOSAL_TO; - if (! empty($conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_PROPOSAL_TO) && ! empty($this->param['models']) && $this->param['models'] == 'supplier_proposal_send') $showinfobcc=$conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_PROPOSAL_TO; if (! empty($conf->global->MAIN_MAIL_AUTOCOPY_ORDER_TO) && ! empty($this->param['models']) && $this->param['models'] == 'order_send') $showinfobcc=$conf->global->MAIN_MAIL_AUTOCOPY_ORDER_TO; if (! empty($conf->global->MAIN_MAIL_AUTOCOPY_INVOICE_TO) && ! empty($this->param['models']) && $this->param['models'] == 'facture_send') $showinfobcc=$conf->global->MAIN_MAIL_AUTOCOPY_INVOICE_TO; + if (! empty($conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_PROPOSAL_TO) && ! empty($this->param['models']) && $this->param['models'] == 'supplier_proposal_send') $showinfobcc=$conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_PROPOSAL_TO; + if (! empty($conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_ORDER_TO) && ! empty($this->param['models']) && $this->param['models'] == 'order_supplier_send') $showinfobcc=$conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_ORDER_TO; + if (! empty($conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_INVOICE_TO) && ! empty($this->param['models']) && $this->param['models'] == 'invoice_supplier_send') $showinfobcc=$conf->global->MAIN_MAIL_AUTOCOPY_SUPPLIER_INVOICE_TO; + if (! empty($conf->global->MAIN_MAIL_AUTOCOPY_PROJECT_TO) && ! empty($this->param['models']) && $this->param['models'] == 'project') $showinfobcc=$conf->global->MAIN_MAIL_AUTOCOPY_PROJECT_TO; if ($showinfobcc) $out.=' + '.$showinfobcc; $out.= "
 ' . $langs->trans('ModifyAllLines') . '     ' . $langs->trans('Progress') . '   ' . $langs->trans('ModifyAllLines') . '' . $langs->trans('Progress') . '   
  
     %
'; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 60bfd1e5305..8b20479a154 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -3963,8 +3963,10 @@ abstract class CommonObject // Reduction short print '
'.$langs->trans('ReductionShort').'' . $langs->trans('Progress') . '' . $langs->trans('TotalHT100') . 'trans('ReductionShort'); ?> ' . $langs->trans('Progress') . '
@@ -137,6 +140,7 @@ $coldisplay=-1; // We remove first td element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier') // We must have same test in printObjectLines { + $coldisplay++; ?>
'; print $form->selectUnits($line->fk_unit, "units"); print ' -rights->margins->creer)) + { $coldisplay++; -?> + ?> + product->enabled) || ! empty($conf->service->enabled)) { ?> @@ -218,8 +223,8 @@ $coldisplay=-1; // We remove first td + ">
">
trans('ServiceLimitedDuration').' '.$langs->trans('From').' '; ?> + trans('ServiceLimitedDuration').' '.$langs->trans('From').' '; ?> global->MAIN_USE_HOURMIN_IN_DATE_RANGE)?$conf->global->MAIN_USE_HOURMIN_IN_DATE_RANGE:''); print $form->selectDate($line->date_start, 'date_start', $hourmin, $hourmin, $line->date_start?0:1, "updateline", 1, 0); diff --git a/htdocs/core/tpl/objectline_view.tpl.php b/htdocs/core/tpl/objectline_view.tpl.php index a3bf7d587af..ba52a4a63c5 100644 --- a/htdocs/core/tpl/objectline_view.tpl.php +++ b/htdocs/core/tpl/objectline_view.tpl.php @@ -237,9 +237,12 @@ $domData .= ' data-product_type="'.$line->product_type.'"';   ' . $line->situation_percent . '%' . $line->situation_percent . '' . $langs->trans('Progress') . '' . $langs->trans('TotalHT100') . '' . $langs->trans('TotalHT100Short') . '' . $langs->trans('Progress') . '
global->MAIN_INPUT_DESC_HEIGHT)) $nbrows=$conf->global->MAIN_INPUT_DESC_HEIGHT; $toolbarname='dolibarr_details'; if (! empty($conf->global->FCKEDITOR_ENABLE_DETAILS_FULL)) $toolbarname='dolibarr_notes'; - $doleditor=new DolEditor('dp_desc', GETPOST('dp_desc'), '', (empty($conf->global->MAIN_DOLEDITOR_HEIGHT)?100:$conf->global->MAIN_DOLEDITOR_HEIGHT), $toolbarname, '', false, true, $enabled, $nbrows, '98%'); + $doleditor=new DolEditor('dp_desc', GETPOST('dp_desc', 'none'), '', (empty($conf->global->MAIN_DOLEDITOR_HEIGHT)?100:$conf->global->MAIN_DOLEDITOR_HEIGHT), $toolbarname, '', false, true, $enabled, $nbrows, '98%'); $doleditor->Create(); // Show autofill date for recurring invoices @@ -355,52 +355,71 @@ else { if ($object->element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier') // We must have same test in printObjectLines { ?> + $coldisplay++; "> tva_assuj == "0") echo ''.vatrate(0, true); else echo $form->load_tva('tva_tx', (isset($_POST["tva_tx"])?GETPOST("tva_tx", 'alpha', 2):-1), $seller, $buyer, 0, 0, '', false, 1); ?> + + "> "> "> "> '; print $form->selectUnits($line->fk_unit, "units"); print '">% % @@ -411,7 +430,6 @@ else { "> @@ -441,62 +456,18 @@ else { showOptionals($extrafieldsline, 'edit', array('style'=>$bcnd[$var], 'colspan'=>$coldisplay+8), '', '', empty($conf->global->MAIN_EXTRAFIELDS_IN_ONE_TD)?0:1); + print $objectline->showOptionals($extrafieldsline, 'edit', array('style'=>$bcnd[$var], 'colspan'=>$coldisplay), '', '', empty($conf->global->MAIN_EXTRAFIELDS_IN_ONE_TD)?0:1); } ?> service->enabled) || ($object->element == 'contrat')) && $dateSelector && GETPOST('type') != '0') // We show date field if required { - $colspan = 6; - - if ($object->element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier') // We must have same test in printObjectLines - { - $colspan++; - } - if ($this->situation_cycle_ref) { - $colspan++; - } - // We add 1 if col total ttc - if (!empty($inputalsopricewithtax)) { - $colspan++; - } - if ($conf->global->PRODUCT_USE_UNITS) { - $colspan++; - } - if (count($object->lines)) { - //There will be an edit and a delete button - $colspan += 2; - - // With this, there is a column move button ONLY if lines > 1 - if (in_array($object->element, array( - 'propal', - 'supplier_proposal', - 'facture', - 'facturerec', - 'invoice', - 'commande', - 'order', - 'order_supplier', - 'invoice_supplier' - ))) { - $colspan++; - } - } - - if (!empty($conf->multicurrency->enabled) && $this->multicurrency_code != $conf->currency) $colspan+=2; - - if (! empty($usemargins)) - { - if (!empty($user->rights->margins->creer)) $colspan++; // For the buying price - if (! empty($conf->global->DISPLAY_MARGIN_RATES)) $colspan++; - if (! empty($conf->global->DISPLAY_MARK_RATES)) $colspan++; - } ?>
+ situation_cycle_ref) { $coldisplay++; - print '%% trans('ServiceLimitedDuration').' '.$langs->trans('From').' '; ?> + trans('ServiceLimitedDuration').' '.$langs->trans('From').' '; ?> global->MAIN_USE_HOURMIN_IN_DATE_RANGE)?$conf->global->MAIN_USE_HOURMIN_IN_DATE_RANGE:''); print $form->selectDate($line->date_start, 'date_start', $hourmin, $hourmin, $line->date_start?0:1, "updateline", 1, 0); diff --git a/htdocs/core/tpl/objectline_view.tpl.php b/htdocs/core/tpl/objectline_view.tpl.php index ba52a4a63c5..09bedf2ec53 100644 --- a/htdocs/core/tpl/objectline_view.tpl.php +++ b/htdocs/core/tpl/objectline_view.tpl.php @@ -237,17 +237,22 @@ $domData .= ' data-product_type="'.$line->product_type.'"';   ' . $line->situation_percent . '%' . $line->situation_percent . '' . price($tmp[0]) . '' . $langs->trans('Progress') . ''.$langs->trans('MarginRate').''.$langs->trans('MarkRate').'">
'; - $checkbox_selected = ( GETPOST('send_email') == "1" ? ' checked' : ''); + $checkbox_selected = (GETPOST('send_email') == "1" ? ' checked' : ''); print ' '; print ''; print '
'; - $checkbox_selected = ( GETPOST('private_message') == "1" ? ' checked' : ''); + $checkbox_selected = (GETPOST('private_message', 'alpha') == "1" ? ' checked' : ''); print ' '; print ''; print ''; print $form->textwithpicto('', $langs->trans("TicketMessagePrivateHelp"), 1, 'help'); print '
'; $checkbox_selected = (GETPOST('private_message', 'alpha') == "1" ? ' checked' : ''); @@ -873,7 +861,7 @@ class FormTicket print ''; print $form->textwithpicto('', $langs->trans("TicketMessagePrivateHelp"), 1, 'help'); print '
'.$langs->trans("LanguageFile").' '.basename(dirname($pathtofile)).' : '.$pathtofile.''; - print ''.img_picto($langs->trans("Edit"), 'edit').''; - print ''.img_picto($langs->trans("Delete"), 'delete').''; + print ''.img_picto($langs->trans("Edit"), 'edit').''; + print ''.img_picto($langs->trans("Delete"), 'delete').''; print '
'; @@ -1698,7 +1751,7 @@ elseif (! empty($module)) print '
'; print '
'; print '
'; - print $langs->trans("Or"); + print $langs->trans("or"); print '
'; print '
'; print '
'; @@ -1782,8 +1835,26 @@ elseif (! empty($module)) print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print ' '.$langs->trans("ApiClassFile").' : '.($realpathtoapi?'':'').$pathtoapi.($realpathtoapi?'':'').''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; - print '   '.$langs->trans("GoToApiExplorer").''; + if ($realpathtoapi) + { + print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print '   '; + print ''.img_picto($langs->trans("Delete"), 'delete').''; + print '   '; + if (empty($conf->global->$const_name)) // If module is not activated + { + print ''.$langs->trans("GoToApiExplorer").''; + } + else + { + print ''.$langs->trans("GoToApiExplorer").''; + } + } + else + { + //print ''.$langs->trans("FileNotYetGenerated").' '; + print ''; + } print '
'; print ' '.$langs->trans("TestClassFile").' : '.($realpathtophpunit?'':'').$pathtophpunit.($realpathtophpunit?'':'').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; @@ -1824,7 +1895,7 @@ elseif (! empty($module)) $urlofcard = dol_buildpath($pathtocard, 1); print '
'; - print ' '.$langs->trans("PageForList").' : '.($realpathtosql?'':'').$pathtolist.($realpathtosql?'':'').''; + print ' '.$langs->trans("PageForList").' : '.($realpathtolist?'':'').$pathtolist.($realpathtolist?'':'').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print ' '.$langs->trans("PageForCreateEditView").' : '.($realpathtocard?'':'').$pathtocard.($realpathtocard?'':'').'?action=create'; @@ -1840,10 +1911,11 @@ elseif (! empty($module)) print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; + /* This is already on Tab CLI print '
'; print ' '.$langs->trans("ScriptFile").' : '.($realpathtoscript?'':'').$pathtoscript.($realpathtoscript?'':'').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; - print '
'; + print '
';*/ print '
'; @@ -1888,10 +1960,10 @@ elseif (! empty($module)) print ''; print ''; - print ''; + //print ''; print '

'; - print load_fiche_titre($langs->trans("Properties"), '', ''); + print load_fiche_titre($langs->trans("ObjectProperties"), '', ''); print '
'; @@ -2040,7 +2112,7 @@ elseif (! empty($module)) $format='asciidoc'; if (preg_match('/\.md$/i', $spec['name'])) $format='markdown'; print ' '.$langs->trans("SpecificationFile").' : '.$pathtofile.''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; } } @@ -2137,17 +2209,22 @@ elseif (! empty($module)) if ($action != 'editfile' || empty($file)) { - print ''.$langs->trans("MenusDefDesc", ''.$langs->trans('Menus').'').'
'; + print ''; + $htmlhelp=$langs->trans("MenusDefDescTooltip", ''.$langs->trans('Setup').' - '.$langs->trans('Menus').''); + print $form->textwithpicto($langs->trans("MenusDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'
'; + print '
'; print '
'; print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print '
'; print load_fiche_titre($langs->trans("ListOfMenusEntries"), '', ''); - print 'TODO...'; + // @TODO + print $langs->trans("FeatureNotYetAvailable"); + print '
'; print ''; print ''; @@ -2262,16 +2339,24 @@ elseif (! empty($module)) if ($action != 'editfile' || empty($file)) { - print ''.$langs->trans("PermissionsDefDesc", ''.$langs->trans('DefaultPermissions').'').'
'; + + print ''; + $htmlhelp=$langs->trans("PermissionsDefDescTooltip", ''.$langs->trans('DefaultPermissions').''); + print $form->textwithpicto($langs->trans("PermissionsDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'
'; + print '
'; print '
'; print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print '
'; print load_fiche_titre($langs->trans("ListOfPermissionsDefined"), '', ''); + + // @TODO + print $langs->trans("FeatureNotYetAvailable"); + print ''; print ''; print ''; @@ -2279,7 +2364,6 @@ elseif (! empty($module)) print ''; print ''; - print 'TODO...'; /* print '
'; print ''; @@ -2391,7 +2475,7 @@ elseif (! empty($module)) $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; print ''; print ''; - print ''; + print ''; + print ''; } else { print ''.$langs->trans("FileNotYetGenerated").''; - print ''; + print ''; } print ''; } @@ -2458,8 +2542,8 @@ elseif (! empty($module)) print ''; - print ''; + print ''; + print ''; print ''; } } @@ -2467,7 +2551,7 @@ elseif (! empty($module)) { print ''; + print ''; print ''; } print '
'; - print ''.img_picto($langs->trans("Edit"), 'edit').''; + print ''.img_picto($langs->trans("Edit"), 'edit').''; print '
'; @@ -2400,13 +2484,13 @@ elseif (! empty($module)) if (dol_is_file($dirins.'/'.$pathtohook)) { print ''.$pathtohook.''; - print ''.img_picto($langs->trans("Edit"), 'edit').''.img_picto($langs->trans("Delete"), 'delete').''.img_picto($langs->trans("Edit"), 'edit').''.img_picto($langs->trans("Delete"), 'delete').'
'; print ' '.$langs->trans("TriggersFile").' : '.$pathtofile.''; - print ''.img_picto($langs->trans("Edit"), 'edit').''.img_picto($langs->trans("Delete"), 'delete').''.img_picto($langs->trans("Edit"), 'edit').''.img_picto($langs->trans("Delete"), 'delete').'
'; print ' '.$langs->trans("NoTrigger"); - print '
'; @@ -2518,16 +2602,16 @@ elseif (! empty($module)) $pathtofile = $widget['relpath']; print ' '.$langs->trans("WidgetFile").' : '.$pathtofile.''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print ''; - print ''.img_picto($langs->trans("Delete"), 'delete').''; + print ''.img_picto($langs->trans("Delete"), 'delete').''; print ''; } } else { print ' '.$langs->trans("NoWidget"); - print ''; + print ''; print ''; } print ''; @@ -2605,15 +2689,15 @@ elseif (! empty($module)) $pathtofile = $clifile['relpath']; print ' '.$langs->trans("CLIFile").' : '.$pathtofile.''; - print ''.img_picto($langs->trans("Edit"), 'edit').''; - print ''.img_picto($langs->trans("Delete"), 'delete').''; + print ''.img_picto($langs->trans("Edit"), 'edit').''; + print ''.img_picto($langs->trans("Delete"), 'delete').''; print ''; } } else { print ' '.$langs->trans("NoCLIFile"); - print ''; + print ''; print ''; } print ''; @@ -2657,7 +2741,7 @@ elseif (! empty($module)) print '
'; print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print '
'; @@ -2786,8 +2870,8 @@ elseif (! empty($module)) if (preg_match('/\.md$/i', $spec['name'])) $format='markdown'; print ''; print ' '.$langs->trans("SpecificationFile").' : '.$pathtofile.''; - print ''.img_picto($langs->trans("Edit"), 'edit').''; - print ''.img_picto($langs->trans("Delete"), 'delete').''; + print ''.img_picto($langs->trans("Edit"), 'edit').''; + print ''.img_picto($langs->trans("Delete"), 'delete').''; print ''; } } @@ -2795,7 +2879,7 @@ elseif (! empty($module)) { print ''; print ' '.$langs->trans("FileNotYetGenerated"); - print ''; + print ''; print ''; } print ''; @@ -2880,6 +2964,9 @@ elseif (! empty($module)) if ($tab == 'buildpackage') { + print ''.$langs->trans("BuildPackageDesc").''; + print '
'; + if (! class_exists('ZipArchive') && ! defined('ODTPHP_PATHTOPCLZIP')) { print img_warning().' '.$langs->trans("ErrNoZipEngine"); diff --git a/htdocs/modulebuilder/template/class/api_mymodule.class.php b/htdocs/modulebuilder/template/class/api_mymodule.class.php index acf7f65454d..c37a0dba0e1 100644 --- a/htdocs/modulebuilder/template/class/api_mymodule.class.php +++ b/htdocs/modulebuilder/template/class/api_mymodule.class.php @@ -36,14 +36,6 @@ dol_include_once('/mymodule/class/myobject.class.php'); */ class MyModuleApi extends DolibarrApi { - /** - * @var array $FIELDS Mandatory fields, checked when create and update object - */ - static $FIELDS = array( - 'name', - ); - - /** * @var MyObject $myobject {@type MyObject} */ @@ -75,7 +67,7 @@ class MyModuleApi extends DolibarrApi */ public function get($id) { - if(! DolibarrApiAccess::$user->rights->myobject->read) { + if(! DolibarrApiAccess::$user->rights->mymodule->read) { throw new RestException(401); } @@ -84,8 +76,8 @@ class MyModuleApi extends DolibarrApi throw new RestException(404, 'MyObject not found'); } - if( ! DolibarrApi::_checkAccessToResource('myobject', $this->myobject->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + if( ! DolibarrApi::_checkAccessToResource('myobject', $this->myobject->id, 'mymodule_myobject')) { + throw new RestException(401, 'Access to instance id='.$this->myobject->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); } return $this->_cleanObjectDatas($this->myobject); @@ -113,33 +105,37 @@ class MyModuleApi extends DolibarrApi global $db, $conf; $obj_ret = array(); + $tmpobject = new MyObject($db); + + if(! DolibarrApiAccess::$user->rights->bbb->read) { + throw new RestException(401); + } $socid = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : ''; - $restictonsocid = 0; // Set to 1 if there is a field socid in table of object + $restrictonsocid = 0; // Set to 1 if there is a field socid in table of object // If the internal user must only see his customers, force searching by him $search_sale = 0; - if ($restictonsocid && ! DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) $search_sale = DolibarrApiAccess::$user->id; + if ($restrictonsocid && ! DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) $search_sale = DolibarrApiAccess::$user->id; $sql = "SELECT t.rowid"; - if ($restictonsocid && (!DolibarrApiAccess::$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."myobject_mytable as t"; + if ($restrictonsocid && (!DolibarrApiAccess::$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.$tmpobject->table_element." as t"; - if ($restictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale $sql.= " WHERE 1 = 1"; // Example of use $mode //if ($mode == 1) $sql.= " AND s.client IN (1, 3)"; //if ($mode == 2) $sql.= " AND s.client IN (2, 3)"; - $tmpobject = new MyObject($db); if ($tmpobject->ismultientitymanaged) $sql.= ' AND t.entity IN ('.getEntity('myobject').')'; - if ($restictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= " AND t.fk_soc = sc.fk_soc"; - if ($restictonsocid && $socid) $sql.= " AND t.fk_soc = ".$socid; - if ($restictonsocid && $search_sale > 0) $sql.= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= " AND t.fk_soc = sc.fk_soc"; + if ($restrictonsocid && $socid) $sql.= " AND t.fk_soc = ".$socid; + if ($restrictonsocid && $search_sale > 0) $sql.= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale // Insert sale filter - if ($restictonsocid && $search_sale > 0) { + if ($restrictonsocid && $search_sale > 0) { $sql .= " AND sc.fk_user = ".$search_sale; } if ($sqlfilters) @@ -176,7 +172,7 @@ class MyModuleApi extends DolibarrApi } } else { - throw new RestException(503, 'Error when retrieve myobject list'); + throw new RestException(503, 'Error when retrieving myobject list: '.$db->lasterror()); } if( ! count($obj_ret)) { throw new RestException(404, 'No myobject found'); @@ -194,7 +190,7 @@ class MyModuleApi extends DolibarrApi */ public function post($request_data = null) { - if(! DolibarrApiAccess::$user->rights->myobject->create) { + if(! DolibarrApiAccess::$user->rights->mymodule->write) { throw new RestException(401); } // Check mandatory fields @@ -220,7 +216,7 @@ class MyModuleApi extends DolibarrApi */ public function put($id, $request_data = null) { - if(! DolibarrApiAccess::$user->rights->myobject->create) { + if(! DolibarrApiAccess::$user->rights->mymodule->write) { throw new RestException(401); } @@ -229,8 +225,8 @@ class MyModuleApi extends DolibarrApi throw new RestException(404, 'MyObject not found'); } - if( ! DolibarrApi::_checkAccessToResource('myobject', $this->myobject->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + if( ! DolibarrApi::_checkAccessToResource('myobject', $this->myobject->id, 'mymodule_myobject')) { + throw new RestException(401, 'Access to instance id='.$this->myobject->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); } foreach($request_data as $field => $value) { @@ -254,11 +250,11 @@ class MyModuleApi extends DolibarrApi * @param int $id MyObject ID * @return array * - * @url DELETE myobject/{id} + * @url DELETE myobjects/{id} */ public function delete($id) { - if (! DolibarrApiAccess::$user->rights->myobject->delete) { + if (! DolibarrApiAccess::$user->rights->mymodule->delete) { throw new RestException(401); } $result = $this->myobject->fetch($id); @@ -266,8 +262,8 @@ class MyModuleApi extends DolibarrApi throw new RestException(404, 'MyObject not found'); } - if (! DolibarrApi::_checkAccessToResource('myobject', $this->myobject->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + if (! DolibarrApi::_checkAccessToResource('myobject', $this->myobject->id, 'mymodule_myobject')) { + throw new RestException(401, 'Access to instance id='.$this->myobject->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); } if (! $this->myobject->delete(DolibarrApiAccess::$user)) @@ -317,7 +313,8 @@ class MyModuleApi extends DolibarrApi private function _validate($data) { $myobject = array(); - foreach (MyObjectApi::$FIELDS as $field) { + foreach ($this->myobject->fields as $field => $propfield) { + if (in_array($field, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat')) || $propfield['notnull'] != 1) continue; // Not a mandatory field if (!isset($data[$field])) throw new RestException(400, "$field field missing"); $myobject[$field] = $data[$field]; diff --git a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php index 8a11a6c87b4..2dd29d10195 100644 --- a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php +++ b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php @@ -170,6 +170,7 @@ class modMyModule extends DolibarrModules // 'stock' to add a tab in stock view // 'thirdparty' to add a tab in third party view // 'user' to add a tab in user view + // Dictionaries $this->dictionaries=array(); /* Example: @@ -195,6 +196,7 @@ class modMyModule extends DolibarrModules 'tabcond'=>array($conf->mymodule->enabled,$conf->mymodule->enabled,$conf->mymodule->enabled) ); */ + // Boxes/Widgets // Add here list of php file(s) stored in mymodule/core/boxes that contains class to show a widget. $this->boxes = array( @@ -206,6 +208,7 @@ class modMyModule extends DolibarrModules //1=>array('file'=>'mymodulewidget2.php@mymodule','note'=>'Widget provided by MyModule'), //2=>array('file'=>'mymodulewidget3.php@mymodule','note'=>'Widget provided by MyModule') ); + // Cronjobs (List of cron jobs entries to add when module is enabled) // unit_frequency must be 60 for minute, 3600 for hour, 86400 for day, 604800 for week $this->cronjobs = array( @@ -228,26 +231,28 @@ class modMyModule extends DolibarrModules // 0=>array('label'=>'My label', 'jobtype'=>'method', 'class'=>'/dir/class/file.class.php', 'objectname'=>'MyClass', 'method'=>'myMethod', 'parameters'=>'param1, param2', 'comment'=>'Comment', 'frequency'=>2, 'unitfrequency'=>3600, 'status'=>0, 'test'=>'$conf->mymodule->enabled', 'priority'=>50), // 1=>array('label'=>'My label', 'jobtype'=>'command', 'command'=>'', 'parameters'=>'param1, param2', 'comment'=>'Comment', 'frequency'=>1, 'unitfrequency'=>3600*24, 'status'=>0, 'test'=>'$conf->mymodule->enabled', 'priority'=>50) // ); + // Permissions $this->rights = array(); // Permission array used by this module $r=0; $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) - $this->rights[$r][1] = 'Read myobject of MyModule'; // Permission label + $this->rights[$r][1] = 'Read objects of MyModule'; // Permission label $this->rights[$r][3] = 1; // Permission by default for new user (0/1) $this->rights[$r][4] = 'read'; // In php code, permission will be checked by test if ($user->rights->mymodule->level1->level2) $this->rights[$r][5] = ''; // In php code, permission will be checked by test if ($user->rights->mymodule->level1->level2) $r++; $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) - $this->rights[$r][1] = 'Create/Update myobject of MyModule'; // Permission label + $this->rights[$r][1] = 'Create/Update objects of MyModule'; // Permission label $this->rights[$r][3] = 1; // Permission by default for new user (0/1) $this->rights[$r][4] = 'write'; // In php code, permission will be checked by test if ($user->rights->mymodule->level1->level2) $this->rights[$r][5] = ''; // In php code, permission will be checked by test if ($user->rights->mymodule->level1->level2) $r++; $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) - $this->rights[$r][1] = 'Delete myobject of MyModule'; // Permission label + $this->rights[$r][1] = 'Delete objects of MyModule'; // Permission label $this->rights[$r][3] = 1; // Permission by default for new user (0/1) $this->rights[$r][4] = 'delete'; // In php code, permission will be checked by test if ($user->rights->mymodule->level1->level2) $this->rights[$r][5] = ''; // In php code, permission will be checked by test if ($user->rights->mymodule->level1->level2) + // Main menu entries $this->menu = array(); // List of menus to add $r=0; @@ -298,6 +303,7 @@ class modMyModule extends DolibarrModules 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both ); END MODULEBUILDER LEFTMENU MYOBJECT */ + // Exports $r=1; /* BEGIN MODULEBUILDER EXPORT MYOBJECT */ @@ -317,6 +323,26 @@ class modMyModule extends DolibarrModules $this->export_sql_end[$r] .=' AND t.entity IN ('.getEntity('myobject').')'; $r++; */ /* END MODULEBUILDER EXPORT MYOBJECT */ + + // Imports + $r=1; + /* BEGIN MODULEBUILDER IMPORT MYOBJECT */ + /* + $langs->load("mymodule@mymodule"); + $this->export_code[$r]=$this->rights_class.'_'.$r; + $this->export_label[$r]='MyObjectLines'; // Translation key (used only if key ExportDataset_xxx_z not found) + $this->export_icon[$r]='myobject@mymodule'; + $keyforclass = 'MyObject'; $keyforclassfile='/mymobule/class/myobject.class.php'; $keyforelement='myobject'; + include DOL_DOCUMENT_ROOT.'/core/commonfieldsinexport.inc.php'; + $keyforselect='myobject'; $keyforaliasextra='extra'; $keyforelement='myobject'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; + //$this->export_dependencies_array[$r]=array('mysubobject'=>'ts.rowid', 't.myfield'=>array('t.myfield2','t.myfield3')); // To force to activate one or several fields if we select some fields that need same (like to select a unique key if we ask a field of a child to avoid the DISTINCT to discard them, or for computed field than need several other fields) + $this->export_sql_start[$r]='SELECT DISTINCT '; + $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'myobject as t'; + $this->export_sql_end[$r] .=' WHERE 1 = 1'; + $this->export_sql_end[$r] .=' AND t.entity IN ('.getEntity('myobject').')'; + $r++; */ + /* END MODULEBUILDER IMPORT MYOBJECT */ } /** * Function called when module is enabled. diff --git a/htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php b/htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php index 4388c6399db..1718a6a72d5 100644 --- a/htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php +++ b/htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php @@ -97,7 +97,7 @@ class InterfaceMyModuleTriggers extends DolibarrTriggers */ public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf) { - if (empty($conf->mymodule->enabled)) return 0; // Module not active, we do nothing + if (empty($conf->mymodule->enabled)) return 0; // If module is not enabled, we do nothing // Put here code you want to execute when a Dolibarr business events occurs. // Data and type of action are stored into $object and $action @@ -302,7 +302,9 @@ class InterfaceMyModuleTriggers extends DolibarrTriggers //case 'SHIPPING_CLOSED': //case 'SHIPPING_REOPEN': //case 'SHIPPING_DELETE': - // break; + + // and more... + default: dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); break; From 0f8c7df6fe005b92d2436befb388eac8ac91a623 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 2 May 2019 12:19:43 +0200 Subject: [PATCH 109/132] Debug api of module BOM --- htdocs/api/index.php | 3 +- htdocs/bom/class/api_boms.class.php | 59 ++++++++----------- htdocs/core/lib/functions2.lib.php | 3 + .../template/class/api_mymodule.class.php | 6 +- 4 files changed, 34 insertions(+), 37 deletions(-) diff --git a/htdocs/api/index.php b/htdocs/api/index.php index 4207618d125..3f47731316c 100644 --- a/htdocs/api/index.php +++ b/htdocs/api/index.php @@ -234,12 +234,13 @@ if (! empty($reg[1]) && ($reg[1] != 'explorer' || ($reg[2] != '/swagger.json' && $classname = ucwords($module); - dol_syslog('Search /' . $moduledirforclass . '/class/api_' . $classfile . '.class.php => dir_part_file=' . $dir_part_file . ' classname=' . $classname); + dol_syslog('Search api file /' . $moduledirforclass . '/class/api_' . $classfile . '.class.php => dir_part_file=' . $dir_part_file . ' classname=' . $classname); $res = false; if ($dir_part_file) $res = include_once $dir_part_file; if (! $res) { + dol_syslog('Failed to make include_once '.$dir_part_file, LOG_WARNING); print 'API not found (failed to include API file)'; header('HTTP/1.1 501 API not found (failed to include API file)'); exit(0); diff --git a/htdocs/bom/class/api_boms.class.php b/htdocs/bom/class/api_boms.class.php index 47e22a3bf62..54f289a5b23 100644 --- a/htdocs/bom/class/api_boms.class.php +++ b/htdocs/bom/class/api_boms.class.php @@ -28,21 +28,13 @@ require_once DOL_DOCUMENT_ROOT.'/bom/class/bom.class.php'; */ /** - * API class for bom bom + * API class for bom * * @access protected * @class DolibarrApiAccess {@requires user,external} */ -class BOMs extends DolibarrApi +class Boms extends DolibarrApi { - /** - * @var array $FIELDS Mandatory fields, checked when create and update object - */ - static $FIELDS = array( - 'label' - ); - - /** * @var BOM $bom {@type BOM} */ @@ -71,16 +63,16 @@ class BOMs extends DolibarrApi */ public function get($id) { - if(! DolibarrApiAccess::$user->rights->bom->read) { + if (! DolibarrApiAccess::$user->rights->bom->read) { throw new RestException(401); } $result = $this->bom->fetch($id); - if( ! $result ) { + if (! $result) { throw new RestException(404, 'BOM not found'); } - if( ! DolibarrApi::_checkAccessToResource('bom', $this->bom->id)) { + if (! DolibarrApi::_checkAccessToResource('bom', $this->bom->id, 'bom_bom')) { throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } @@ -107,33 +99,33 @@ class BOMs extends DolibarrApi global $db, $conf; $obj_ret = array(); - + $tmpobject = new BOM($db); + $socid = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : ''; - $restictonsocid = 0; // Set to 1 if there is a field socid in table of object + $restrictonsocid = 0; // Set to 1 if there is a field socid in table of object // If the internal user must only see his customers, force searching by him $search_sale = 0; - if ($restictonsocid && ! DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) $search_sale = DolibarrApiAccess::$user->id; + if ($restrictonsocid && ! DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) $search_sale = DolibarrApiAccess::$user->id; $sql = "SELECT t.rowid"; - if ($restictonsocid && (!DolibarrApiAccess::$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."bom_mytable as t"; + if ($restrictonsocid && (!DolibarrApiAccess::$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.$tmpobject->table_element." as t"; - if ($restictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale $sql.= " WHERE 1 = 1"; // Example of use $mode //if ($mode == 1) $sql.= " AND s.client IN (1, 3)"; //if ($mode == 2) $sql.= " AND s.client IN (2, 3)"; - $tmpobject = new BOM($db); if ($tmpobject->ismultientitymanaged) $sql.= ' AND t.entity IN ('.getEntity('bom').')'; - if ($restictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= " AND t.fk_soc = sc.fk_soc"; - if ($restictonsocid && $socid) $sql.= " AND t.fk_soc = ".$socid; - if ($restictonsocid && $search_sale > 0) $sql.= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= " AND t.fk_soc = sc.fk_soc"; + if ($restrictonsocid && $socid) $sql.= " AND t.fk_soc = ".$socid; + if ($restrictonsocid && $search_sale > 0) $sql.= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale // Insert sale filter - if ($restictonsocid && $search_sale > 0) + if ($restrictonsocid && $search_sale > 0) { $sql .= " AND sc.fk_user = ".$search_sale; } @@ -190,7 +182,7 @@ class BOMs extends DolibarrApi */ public function post($request_data = null) { - if(! DolibarrApiAccess::$user->rights->bom->create) { + if(! DolibarrApiAccess::$user->rights->bom->write) { throw new RestException(401); } // Check mandatory fields @@ -215,7 +207,7 @@ class BOMs extends DolibarrApi */ public function put($id, $request_data = null) { - if(! DolibarrApiAccess::$user->rights->bom->create) { + if(! DolibarrApiAccess::$user->rights->bom->write) { throw new RestException(401); } @@ -224,7 +216,7 @@ class BOMs extends DolibarrApi throw new RestException(404, 'BOM not found'); } - if( ! DolibarrApi::_checkAccessToResource('bom', $this->bom->id)) { + if( ! DolibarrApi::_checkAccessToResource('bom', $this->bom->id, 'bom_bom')) { throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } @@ -239,7 +231,7 @@ class BOMs extends DolibarrApi } else { - throw new RestException(500, $this->commande->error); + throw new RestException(500, $this->bom->error); } } @@ -259,7 +251,7 @@ class BOMs extends DolibarrApi throw new RestException(404, 'BOM not found'); } - if (! DolibarrApi::_checkAccessToResource('bom', $this->bom->id)) { + if (! DolibarrApi::_checkAccessToResource('bom', $this->bom->id, 'bom_bom')) { throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } @@ -309,12 +301,13 @@ class BOMs extends DolibarrApi */ private function _validate($data) { - $bom = array(); - foreach (BOMs::$FIELDS as $field) { + $myobject = array(); + foreach ($this->myobject->fields as $field => $propfield) { + if (in_array($field, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat')) || $propfield['notnull'] != 1) continue; // Not a mandatory field if (!isset($data[$field])) throw new RestException(400, "$field field missing"); - $bom[$field] = $data[$field]; + $myobject[$field] = $data[$field]; } - return $bom; + return $myobject; } } diff --git a/htdocs/core/lib/functions2.lib.php b/htdocs/core/lib/functions2.lib.php index 16fb210ee4d..e5c765383af 100644 --- a/htdocs/core/lib/functions2.lib.php +++ b/htdocs/core/lib/functions2.lib.php @@ -2436,6 +2436,9 @@ function getModuleDirForApiClass($module) elseif ($module == 'tickets') { $moduledirforclass = 'ticket'; } + elseif ($module == 'boms') { + $moduledirforclass = 'bom'; + } return $moduledirforclass; } diff --git a/htdocs/modulebuilder/template/class/api_mymodule.class.php b/htdocs/modulebuilder/template/class/api_mymodule.class.php index c37a0dba0e1..0fcd9a8afd4 100644 --- a/htdocs/modulebuilder/template/class/api_mymodule.class.php +++ b/htdocs/modulebuilder/template/class/api_mymodule.class.php @@ -67,16 +67,16 @@ class MyModuleApi extends DolibarrApi */ public function get($id) { - if(! DolibarrApiAccess::$user->rights->mymodule->read) { + if (! DolibarrApiAccess::$user->rights->mymodule->read) { throw new RestException(401); } $result = $this->myobject->fetch($id); - if( ! $result ) { + if (! $result) { throw new RestException(404, 'MyObject not found'); } - if( ! DolibarrApi::_checkAccessToResource('myobject', $this->myobject->id, 'mymodule_myobject')) { + if (! DolibarrApi::_checkAccessToResource('myobject', $this->myobject->id, 'mymodule_myobject')) { throw new RestException(401, 'Access to instance id='.$this->myobject->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); } From ceeb9752ce3f10deb72c0103aab03652856a35bb Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 2 May 2019 12:28:40 +0200 Subject: [PATCH 110/132] Fix PHPCS --- htdocs/core/lib/price.lib.php | 15 ++++----- htdocs/core/lib/website.lib.php | 2 +- htdocs/core/modules/modProduct.class.php | 8 ++--- htdocs/core/modules/modService.class.php | 40 +++++++++++------------ htdocs/core/tpl/objectline_create.tpl.php | 14 ++++---- htdocs/public/stripe/confirm_payment.php | 29 +++++++++------- 6 files changed, 57 insertions(+), 51 deletions(-) diff --git a/htdocs/core/lib/price.lib.php b/htdocs/core/lib/price.lib.php index a649d9d225e..d2b9ee56685 100644 --- a/htdocs/core/lib/price.lib.php +++ b/htdocs/core/lib/price.lib.php @@ -82,7 +82,7 @@ * 25=multicurrency_total_tax1 for total_ht * 26=multicurrency_total_tax2 for total_ht */ -function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocaltax1_rate, $uselocaltax2_rate, $remise_percent_global, $price_base_type, $info_bits, $type, $seller = '', $localtaxes_array='', $progress=100, $multicurrency_tx=1, $pu_devise=0) +function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocaltax1_rate, $uselocaltax2_rate, $remise_percent_global, $price_base_type, $info_bits, $type, $seller = '', $localtaxes_array = '', $progress = 100, $multicurrency_tx = 1, $pu_devise = 0) { global $conf,$mysoc,$db; @@ -188,9 +188,9 @@ function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocalt //If input unit price is 'HT', we need to have the totals with main VAT for a correct calculation if ($price_base_type != 'TTC') { - $tot_sans_remise_wt = price2num($tot_sans_remise * (1 + ($txtva / 100)),'MU'); - $tot_avec_remise_wt = price2num($tot_avec_remise * (1 + ($txtva / 100)),'MU'); - $pu_wt = price2num($pu * (1 + ($txtva / 100)),'MU'); + $tot_sans_remise_wt = price2num($tot_sans_remise * (1 + ($txtva / 100)), 'MU'); + $tot_avec_remise_wt = price2num($tot_avec_remise * (1 + ($txtva / 100)), 'MU'); + $pu_wt = price2num($pu * (1 + ($txtva / 100)), 'MU'); } else { @@ -292,9 +292,9 @@ function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocalt //If input unit price is 'TTC', we need to have the totals without main VAT for a correct calculation if ($price_base_type == 'TTC') { - $tot_sans_remise= price2num($tot_sans_remise / (1 + ($txtva / 100)),'MU'); - $tot_avec_remise= price2num($tot_avec_remise / (1 + ($txtva / 100)),'MU'); - $pu = price2num($pu / (1 + ($txtva / 100)),'MU'); + $tot_sans_remise= price2num($tot_sans_remise / (1 + ($txtva / 100)), 'MU'); + $tot_avec_remise= price2num($tot_avec_remise / (1 + ($txtva / 100)), 'MU'); + $pu = price2num($pu / (1 + ($txtva / 100)), 'MU'); } $apply_tax = false; @@ -411,4 +411,3 @@ function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocalt return $result; } - diff --git a/htdocs/core/lib/website.lib.php b/htdocs/core/lib/website.lib.php index 56f6cdf97a3..198f91a4446 100644 --- a/htdocs/core/lib/website.lib.php +++ b/htdocs/core/lib/website.lib.php @@ -145,7 +145,7 @@ function dolKeepOnlyPhpCode($str) $newstr = ''; //split on each opening tag - $parts = explode('fournisseur->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('s.nom'=>'product_supplier_ref','pf.ref_fourn'=>'product_supplier_ref','pf.unitprice'=>'product_supplier_ref','pf.quantity'=>'product_supplier_ref','pf.remise_percent'=>'product_supplier_ref','pf.delivery_time_days'=>'product_supplier_ref')); if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('l.lang'=>'translation', 'l.label'=>'translation','l.description'=>'translation','l.note'=>'translation')); if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_dependencies_array[$r]=array('category'=>'p.rowid'); - if (! empty($conf->stock->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.stock'=>'product','p.pmp'=>'product')); - if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.barcode'=>'product')); - if (! empty($conf->fournisseur->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('s.nom'=>'product_supplier_ref','pf.ref_fourn'=>'product_supplier_ref','pf.unitprice'=>'product_supplier_ref','pf.quantity'=>'product_supplier_ref','pf.remise_percent'=>'product_supplier_ref','pf.delivery_time_days'=>'product_supplier_ref')); - if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('l.lang'=>'translation', 'l.label'=>'translation','l.description'=>'translation','l.note'=>'translation')); + if (! empty($conf->stock->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('p.stock'=>'product','p.pmp'=>'product')); + if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('p.barcode'=>'product')); + if (! empty($conf->fournisseur->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('s.nom'=>'product_supplier_ref','pf.ref_fourn'=>'product_supplier_ref','pf.unitprice'=>'product_supplier_ref','pf.quantity'=>'product_supplier_ref','pf.remise_percent'=>'product_supplier_ref','pf.delivery_time_days'=>'product_supplier_ref')); + if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('l.lang'=>'translation', 'l.label'=>'translation','l.description'=>'translation','l.note'=>'translation')); if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_dependencies_array[$r]=array('category'=>'p.rowid'); $this->export_sql_start[$r]='SELECT DISTINCT '; $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'product as p'; diff --git a/htdocs/core/modules/modService.class.php b/htdocs/core/modules/modService.class.php index 119339d6022..4ac6999b8d5 100644 --- a/htdocs/core/modules/modService.class.php +++ b/htdocs/core/modules/modService.class.php @@ -143,32 +143,32 @@ class modService extends DolibarrModules $this->export_permission[$r]=array(array("service","export")); $this->export_fields_array[$r]=array('p.rowid'=>"Id",'p.ref'=>"Ref",'p.label'=>"Label",'p.description'=>"Description",'p.url'=>"PublicUrl",'p.accountancy_code_sell'=>"ProductAccountancySellCode",'p.accountancy_code_buy'=>"ProductAccountancyBuyCode",'p.note'=>"Note",'p.price_base_type'=>"PriceBase",'p.price'=>"UnitPriceHT",'p.price_ttc'=>"UnitPriceTTC",'p.tva_tx'=>'VATRate','p.tosell'=>"OnSell",'p.tobuy'=>"OnBuy",'p.duration'=>"Duration",'p.datec'=>'DateCreation','p.tms'=>'DateModification'); if (is_object($mysoc) && $mysoc->useNPR()) $this->export_fields_array[$r]['p.recuperableonly']='NPR'; - if (! empty($conf->stock->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('p.stock'=>'Stock','p.seuil_stock_alerte'=>'StockLimit','p.desiredstock'=>'DesiredStock','p.pmp'=>'PMPValue')); - if (! empty($conf->barcode->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('p.barcode'=>'BarCode')); - if (! empty($conf->fournisseur->enabled) || !empty($conf->margin->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('p.cost_price'=>'CostPrice')); + if (! empty($conf->stock->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p.stock'=>'Stock','p.seuil_stock_alerte'=>'StockLimit','p.desiredstock'=>'DesiredStock','p.pmp'=>'PMPValue')); + if (! empty($conf->barcode->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p.barcode'=>'BarCode')); + if (! empty($conf->fournisseur->enabled) || !empty($conf->margin->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('p.cost_price'=>'CostPrice')); $keyforselect='product'; $keyforelement='product'; $keyforaliasextra='extra'; include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; - if (! empty($conf->fournisseur->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('s.nom'=>'Supplier','pf.ref_fourn'=>'SupplierRef','pf.quantity'=>'QtyMin','pf.remise_percent'=>'DiscountQtyMin','pf.unitprice'=>'BuyingPrice','pf.delivery_time_days'=>'NbDaysToDelivery')); - if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('group_concat(cat.label)'=>'Categories')); - if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r],array('l.lang'=>'Language', 'l.label'=>'TranslatedLabel','l.description'=>'TranslatedDescription','l.note'=>'TranslatedNote')); + if (! empty($conf->fournisseur->enabled)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('s.nom'=>'Supplier','pf.ref_fourn'=>'SupplierRef','pf.quantity'=>'QtyMin','pf.remise_percent'=>'DiscountQtyMin','pf.unitprice'=>'BuyingPrice','pf.delivery_time_days'=>'NbDaysToDelivery')); + if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('group_concat(cat.label)'=>'Categories')); + if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_fields_array[$r]=array_merge($this->export_fields_array[$r], array('l.lang'=>'Language', 'l.label'=>'TranslatedLabel','l.description'=>'TranslatedDescription','l.note'=>'TranslatedNote')); if (! empty($conf->global->PRODUCT_USE_UNITS)) $this->export_fields_array[$r]['p.fk_unit'] = 'Unit'; $this->export_TypeFields_array[$r]=array('p.ref'=>"Text",'p.label'=>"Text",'p.description'=>"Text",'p.url'=>"Text",'p.accountancy_code_sell'=>"Text",'p.accountancy_code_buy'=>"Text",'p.note'=>"Text",'p.price_base_type'=>"Text",'p.price'=>"Numeric",'p.price_ttc'=>"Numeric",'p.tva_tx'=>'Numeric','p.tosell'=>"Boolean",'p.tobuy'=>"Boolean",'p.duration'=>"Duree",'p.datec'=>'Date','p.tms'=>'Date'); - if (! empty($conf->stock->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r],array('p.stock'=>'Numeric')); - if (! empty($conf->barcode->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r],array('p.barcode'=>'Text')); - if (! empty($conf->fournisseur->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r],array('s.nom'=>'Text','pf.ref_fourn'=>'Text','pf.unitprice'=>'Numeric','pf.quantity'=>'Numeric','pf.remise_percent'=>'Numeric','pf.delivery_time_days'=>'Numeric')); - if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r],array('l.lang'=>'Text', 'l.label'=>'Text','l.description'=>'Text','l.note'=>'Text')); - if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r],array("group_concat(cat.label)"=>'Text')); + if (! empty($conf->stock->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('p.stock'=>'Numeric')); + if (! empty($conf->barcode->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('p.barcode'=>'Text')); + if (! empty($conf->fournisseur->enabled)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('s.nom'=>'Text','pf.ref_fourn'=>'Text','pf.unitprice'=>'Numeric','pf.quantity'=>'Numeric','pf.remise_percent'=>'Numeric','pf.delivery_time_days'=>'Numeric')); + if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array('l.lang'=>'Text', 'l.label'=>'Text','l.description'=>'Text','l.note'=>'Text')); + if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_TypeFields_array[$r]=array_merge($this->export_TypeFields_array[$r], array("group_concat(cat.label)"=>'Text')); $this->export_entities_array[$r]=array(); // We define here only fields that use another icon that the one defined into import_icon - if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array("group_concat(cat.label)"=>'category')); - if (! empty($conf->stock->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.stock'=>'product','p.pmp'=>'product')); - if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.barcode'=>'product')); - if (! empty($conf->fournisseur->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('s.nom'=>'product_supplier_ref','pf.ref_fourn'=>'product_supplier_ref','pf.unitprice'=>'product_supplier_ref','pf.quantity'=>'product_supplier_ref','pf.remise_percent'=>'product_supplier_ref','pf.delivery_time_days'=>'product_supplier_ref')); - if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('l.lang'=>'translation', 'l.label'=>'translation','l.description'=>'translation','l.note'=>'translation')); + if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array("group_concat(cat.label)"=>'category')); + if (! empty($conf->stock->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('p.stock'=>'product','p.pmp'=>'product')); + if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('p.barcode'=>'product')); + if (! empty($conf->fournisseur->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('s.nom'=>'product_supplier_ref','pf.ref_fourn'=>'product_supplier_ref','pf.unitprice'=>'product_supplier_ref','pf.quantity'=>'product_supplier_ref','pf.remise_percent'=>'product_supplier_ref','pf.delivery_time_days'=>'product_supplier_ref')); + if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('l.lang'=>'translation', 'l.label'=>'translation','l.description'=>'translation','l.note'=>'translation')); if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_dependencies_array[$r]=array('category'=>'p.rowid'); - if (! empty($conf->stock->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.stock'=>'product','p.pmp'=>'product')); - if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('p.barcode'=>'product')); - if (! empty($conf->fournisseur->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('s.nom'=>'product_supplier_ref','pf.ref_fourn'=>'product_supplier_ref','pf.unitprice'=>'product_supplier_ref','pf.quantity'=>'product_supplier_ref','pf.remise_percent'=>'product_supplier_ref','pf.delivery_time_days'=>'product_supplier_ref')); - if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r],array('l.lang'=>'translation', 'l.label'=>'translation','l.description'=>'translation','l.note'=>'translation')); + if (! empty($conf->stock->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('p.stock'=>'product','p.pmp'=>'product')); + if (! empty($conf->barcode->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('p.barcode'=>'product')); + if (! empty($conf->fournisseur->enabled)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('s.nom'=>'product_supplier_ref','pf.ref_fourn'=>'product_supplier_ref','pf.unitprice'=>'product_supplier_ref','pf.quantity'=>'product_supplier_ref','pf.remise_percent'=>'product_supplier_ref','pf.delivery_time_days'=>'product_supplier_ref')); + if (! empty($conf->global->MAIN_MULTILANGS)) $this->export_entities_array[$r]=array_merge($this->export_entities_array[$r], array('l.lang'=>'translation', 'l.label'=>'translation','l.description'=>'translation','l.note'=>'translation')); if (! empty($conf->global->EXPORTTOOL_CATEGORIES)) $this->export_dependencies_array[$r]=array('category'=>'p.rowid'); $this->export_sql_start[$r]='SELECT DISTINCT '; $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'product as p'; diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index 04911584809..be493fd97a7 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -163,14 +163,14 @@ if ($nolinesbefore) { ?> global->MAIN_VIEW_LINE_NUMBER)) { - $coldisplay++; - ?> - - global->MAIN_VIEW_LINE_NUMBER)) { + $coldisplay++; + ?> + + payment_method_id)) { - # Create the PaymentIntent + // Create the PaymentIntent $intent = \Stripe\PaymentIntent::create([ 'payment_method' => $json_obj->payment_method_id, 'amount' => 1099, @@ -121,32 +121,39 @@ try { } generatePaymentResponse($intent); } catch (\Stripe\Error\Base $e) { - # Display error on client + // Display error on client echo json_encode([ 'error' => $e->getMessage() ]); } +/** + * generatePaymentResponse + * + * @param object $intent Intent + * @return void + */ function generatePaymentResponse($intent) { if ($intent->status == 'requires_source_action' && - $intent->next_action->type == 'use_stripe_sdk') { - # Tell the client to handle the action + $intent->next_action->type == 'use_stripe_sdk') + { + // Tell the client to handle the action echo json_encode([ 'requires_action' => true, 'payment_intent_client_secret' => $intent->client_secret ]); - } else if ($intent->status == 'succeeded') { - # The payment didn’t need any additional actions and completed! - # Handle post-payment fulfillment + } elseif ($intent->status == 'succeeded') { + // The payment didn’t need any additional actions and completed! + // Handle post-payment fulfillment // TODO echo json_encode([ "success" => true ]); - } else { - # Invalid status + } else { + // Invalid status http_response_code(500); echo json_encode(['error' => 'Invalid PaymentIntent status']); - } + } } From 590c6fb91f306cffa801297d98c1930ae34b9527 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 2 May 2019 12:40:34 +0200 Subject: [PATCH 111/132] Update adherent.class.php --- htdocs/adherents/class/adherent.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 799e3518865..bb7c67dc52c 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -1268,7 +1268,7 @@ class Adherent extends CommonObject $this->id = $obj->rowid; $this->ref_ext = $obj->ref_ext; - $this->civility_id = $obj->civility_code; + $this->civility_id = $obj->civility_code; // Bad. Kept for backard compatibility $this->civility_code = $obj->civility_code; $this->civility = $obj->civility_code?($langs->trans("Civility".$obj->civility_code) != ("Civility".$obj->civility_code) ? $langs->trans("Civility".$obj->civility_code) : $obj->civility_code):''; From cf7b27786c01d7fc5646b814f17b8e93042f59bf Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 2 May 2019 12:43:01 +0200 Subject: [PATCH 112/132] Update multicurrency.class.php --- htdocs/multicurrency/class/multicurrency.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/multicurrency/class/multicurrency.class.php b/htdocs/multicurrency/class/multicurrency.class.php index 2abfb0e2624..479c71aa177 100644 --- a/htdocs/multicurrency/class/multicurrency.class.php +++ b/htdocs/multicurrency/class/multicurrency.class.php @@ -626,7 +626,7 @@ class MultiCurrency extends CommonObject /** * Sync rates from api * - * @param array $response array of reponse from api to sync dolibarr rates + * @param string $key Key to use. Come from $conf->global->MULTICURRENCY_APP_ID. * @return void */ public static function syncRates($key) From 4a81e8fd62aa3d39c50cb0cdab95148d700fe9ff Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 2 May 2019 13:24:28 +0200 Subject: [PATCH 113/132] Debug call to apilayer --- htdocs/admin/multicurrency.php | 100 ++++++++---------- htdocs/langs/en_US/multicurrency.lang | 6 +- .../class/multicurrency.class.php | 7 +- 3 files changed, 52 insertions(+), 61 deletions(-) diff --git a/htdocs/admin/multicurrency.php b/htdocs/admin/multicurrency.php index fbf6603d139..fa622a7ee81 100644 --- a/htdocs/admin/multicurrency.php +++ b/htdocs/admin/multicurrency.php @@ -109,9 +109,18 @@ elseif ($action == 'update_currency') } } } -elseif ($action == 'synchronize') +elseif ($action == 'setapilayer') { - MultiCurrency::syncRates($conf->global->MULTICURRENCY_APP_ID); + if (GETPOSTISSET('modify_apilayer')) + { + dolibarr_set_const($db, 'MULTICURRENCY_APP_ID', GETPOST('MULTICURRENCY_APP_ID', 'alpha')); + dolibarr_set_const($db, 'MULTICURRENCY_APP_SOURCE', GETPOST('MULTICURRENCY_APP_SOURCE', 'alpha')); + dolibarr_set_const($db, 'MULTICURRENCY_ALTERNATE_SOURCE', GETPOST('MULTICURRENCY_ALTERNATE_SOURCE', 'alpha')); + } + else + { + MultiCurrency::syncRates($conf->global->MULTICURRENCY_APP_ID); + } } @@ -177,17 +186,20 @@ if ($conf->use_javascript_ajax) { } print ''; -//Online payment with currency on document -print ''; -print ''.$langs->transnoentitiesnoconv("multicurrency_useCurrency").''; -print ''; -if ($conf->use_javascript_ajax) { - print ajax_constantonoff('MULTICURRENCY_USE_CURRENCY_ON_DOCUMENT'); -} else { - $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); - print $form->selectarray("MULTICURRENCY_USE_CURRENCY_ON_DOCUMENT", $arrval, $conf->global->MULTICURRENCY_USE_CURRENCY_ON_DOCUMENT); +// Online payment with currency on document. This option should be on by default. +if ($conf->global->MAIN_FEATURES_LEVEL >= 2) +{ + print ''; + print ''.$langs->transnoentitiesnoconv("MULTICURRENCY_USE_CURRENCY_ON_DOCUMENT").''; + print ''; + if ($conf->use_javascript_ajax) { + print ajax_constantonoff('MULTICURRENCY_USE_CURRENCY_ON_DOCUMENT'); + } else { + $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); + print $form->selectarray("MULTICURRENCY_USE_CURRENCY_ON_DOCUMENT", $arrval, $conf->global->MULTICURRENCY_USE_CURRENCY_ON_DOCUMENT); + } + print ''; } -print ''; /* TODO uncomment when the functionality will integrated @@ -224,59 +236,48 @@ print '
'; if (!empty($conf->global->MAIN_MULTICURRENCY_ALLOW_SYNCHRONIZATION)) { + print ''; + print ''; + print ''; + print '
'; print ''; - print ''; - print ''."\n"; - print ''; + $urlforapilayer='https://currencylayer.com'; //https://apilayer.net + print ''; + print ''."\n"; + print ''; print ''; - print ''; + print ''; print ''; - print ''; print ''; print ''; print ''; print ''; print ''; print '
'.$form->textwithpicto($langs->trans("CurrencyLayerAccount"), $langs->trans("CurrencyLayerAccount_help_to_synchronize")).''; - print ''; - print ''; - print ''; - print $langs->trans("Value").' '; - print ''; - print '
'.$form->textwithpicto($langs->trans("CurrencyLayerAccount"), $langs->trans("CurrencyLayerAccount_help_to_synchronize", $urlforapilayer)).''; + print ''; + print $langs->trans("Value").' '; + print ''; + print '
'.$langs->transnoentitiesnoconv("multicurrency_appId").''.$langs->transnoentitiesnoconv("multicurrency_appId").''; - print '
'; - print ''; - print ''; print ' '; - print ''; - print '
'; print '
'.$langs->transnoentitiesnoconv("multicurrency_appCurrencySource").''; - print '
'; - print ''; - print ''; print ' '; // Default: USD - print ''; print '
'; print '
'.$langs->transnoentitiesnoconv("multicurrency_alternateCurrencySource").''; - print '
'; - print ''; - print ''; print ' '; // Example: EUR - print ''; - print '
'; print '
'; print '
'; print '
'; -} + print ''; +} print '
'; print ''; @@ -287,15 +288,17 @@ print ''."\n"; print ''; print ''; +print ''; +print ''; + print ''; print ''; print ''; print ''; + print ''; print ''; @@ -325,23 +328,6 @@ foreach ($TCurrency as &$currency) print '
'.$langs->trans("Rate").'
'.$form->selectCurrency('', 'code').''; -print ''; -print ''; print ' '; print ''; print '
'; print '
'; -print ' - -'; // End of page llxFooter(); diff --git a/htdocs/langs/en_US/multicurrency.lang b/htdocs/langs/en_US/multicurrency.lang index 47c5590b862..68791b41320 100644 --- a/htdocs/langs/en_US/multicurrency.lang +++ b/htdocs/langs/en_US/multicurrency.lang @@ -7,10 +7,10 @@ multicurrency_syncronize_error=Synchronization error: %s MULTICURRENCY_USE_RATE_ON_DOCUMENT_DATE=Use the date of the document to find the currency rate, instead of using the latest known rate multicurrency_useOriginTx=When an object is created from another, keep the original rate from the source object (otherwise use the latest known rate) CurrencyLayerAccount=CurrencyLayer API -CurrencyLayerAccount_help_to_synchronize=You must create an account on their website to use this functionality.
Get your API key.
If you use a free account you can't change the currency source (USD by default).
If your main currency is not USD you can use the alternate currency source to force your main currency.

You are limited to 1000 synchronizations per month. +CurrencyLayerAccount_help_to_synchronize=You must create an account on website %s to use this functionality.
Get your API key.
If you use a free account you can't change the currency source (USD by default).
If your main currency is not USD you can use the alternate currency source to force your main currency.

You are limited to 1000 synchronizations per month. multicurrency_appId=API key -multicurrency_appCurrencySource=Currency source -multicurrency_alternateCurrencySource=Alternate currency source +multicurrency_appCurrencySource=Source currency +multicurrency_alternateCurrencySource=Alternate source currency CurrenciesUsed=Currencies used CurrenciesUsed_help_to_add=Add the different currencies and rates you need to use on your proposals, orders etc. rate=rate diff --git a/htdocs/multicurrency/class/multicurrency.class.php b/htdocs/multicurrency/class/multicurrency.class.php index ea39cb85b8e..7cb73686fc5 100644 --- a/htdocs/multicurrency/class/multicurrency.class.php +++ b/htdocs/multicurrency/class/multicurrency.class.php @@ -633,7 +633,11 @@ class MultiCurrency extends CommonObject { global $conf, $db, $langs; - $ch = curl_init('http://apilayer.net/api/live?access_key='.$key.''); + $urlendpoint = 'http://apilayer.net/api/live?access_key='.$key; + dol_syslog("Call url endpoint ".$urlendpoint); + + // TODO Use getURLContent() function instead. + $ch = curl_init($urlendpoint); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); @@ -663,6 +667,7 @@ class MultiCurrency extends CommonObject } else { + dol_syslog("Failed to call endpoint ".$response->error->info, LOG_WARNING); setEventMessages($langs->trans('multicurrency_syncronize_error', $response->error->info), null, 'errors'); } } From 51456802792e2c470669b487a94e601e69c6314f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 2 May 2019 13:31:47 +0200 Subject: [PATCH 114/132] Debug hidden option MAIN_MULTICURRENCY_ALLOW_SYNCHRONIZATION --- htdocs/admin/multicurrency.php | 11 ++++++++++- htdocs/multicurrency/class/multicurrency.class.php | 10 +++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/htdocs/admin/multicurrency.php b/htdocs/admin/multicurrency.php index fa622a7ee81..9602f9c383b 100644 --- a/htdocs/admin/multicurrency.php +++ b/htdocs/admin/multicurrency.php @@ -249,7 +249,7 @@ if (!empty($conf->global->MAIN_MULTICURRENCY_ALLOW_SYNCHRONIZATION)) print ''.$form->textwithpicto($langs->trans("CurrencyLayerAccount"), $langs->trans("CurrencyLayerAccount_help_to_synchronize", $urlforapilayer)).''."\n"; print ''; print ''; - print $langs->trans("Value").' '; + print $langs->trans("Value").' '; print ''; print ''; @@ -328,6 +328,15 @@ foreach ($TCurrency as &$currency) print ''; print '
'; +print ' + +'; // End of page llxFooter(); diff --git a/htdocs/multicurrency/class/multicurrency.class.php b/htdocs/multicurrency/class/multicurrency.class.php index 42d53db20ad..faf05bdc571 100644 --- a/htdocs/multicurrency/class/multicurrency.class.php +++ b/htdocs/multicurrency/class/multicurrency.class.php @@ -626,14 +626,18 @@ class MultiCurrency extends CommonObject /** * Sync rates from api * - * @param string $key Key to use. Come from $conf->global->MULTICURRENCY_APP_ID. + * @param string $key Key to use. Come from $conf->global->MULTICURRENCY_APP_ID. + * @param int $addifnotfound Add if not found * @return void */ - public static function syncRates($key) + public static function syncRates($key, $addifnotfound = 0) { global $conf, $db, $langs; $urlendpoint = 'http://apilayer.net/api/live?access_key='.$key; + //$urlendpoint.='&format=1'; + $urlendpoint.=(empty($conf->global->MULTICURRENCY_APP_SOURCE) ? '' : '&source='.$conf->global->MULTICURRENCY_APP_SOURCE); + dol_syslog("Call url endpoint ".$urlendpoint); // TODO Use getURLContent() function instead. @@ -658,7 +662,7 @@ class MultiCurrency extends CommonObject { $obj->updateRate($rate); } - else + elseif ($addifnotfound) { self::addRateFromDolibarr($code, $rate); } From e81f10c79033ee9bcd4133e9cff2308918902692 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 2 May 2019 13:45:49 +0200 Subject: [PATCH 115/132] Debug hidden option MAIN_MULTICURRENCY_ALLOW_SYNCHRONIZATION --- htdocs/admin/multicurrency.php | 10 +++++----- htdocs/core/class/html.form.class.php | 12 ++++++++++-- htdocs/langs/en_US/multicurrency.lang | 2 +- htdocs/multicurrency/class/multicurrency.class.php | 4 ++-- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/htdocs/admin/multicurrency.php b/htdocs/admin/multicurrency.php index 9602f9c383b..4a10f663e34 100644 --- a/htdocs/admin/multicurrency.php +++ b/htdocs/admin/multicurrency.php @@ -115,7 +115,7 @@ elseif ($action == 'setapilayer') { dolibarr_set_const($db, 'MULTICURRENCY_APP_ID', GETPOST('MULTICURRENCY_APP_ID', 'alpha')); dolibarr_set_const($db, 'MULTICURRENCY_APP_SOURCE', GETPOST('MULTICURRENCY_APP_SOURCE', 'alpha')); - dolibarr_set_const($db, 'MULTICURRENCY_ALTERNATE_SOURCE', GETPOST('MULTICURRENCY_ALTERNATE_SOURCE', 'alpha')); + //dolibarr_set_const($db, 'MULTICURRENCY_ALTERNATE_SOURCE', GETPOST('MULTICURRENCY_ALTERNATE_SOURCE', 'alpha')); } else { @@ -249,8 +249,8 @@ if (!empty($conf->global->MAIN_MULTICURRENCY_ALLOW_SYNCHRONIZATION)) print ''.$form->textwithpicto($langs->trans("CurrencyLayerAccount"), $langs->trans("CurrencyLayerAccount_help_to_synchronize", $urlforapilayer)).''."\n"; print ''; print ''; - print $langs->trans("Value").' '; print ''; + print ''; print ''; print ''; @@ -266,11 +266,11 @@ if (!empty($conf->global->MAIN_MULTICURRENCY_ALLOW_SYNCHRONIZATION)) print ''; print ''; - print ''; + /*print ''; print ''.$langs->transnoentitiesnoconv("multicurrency_alternateCurrencySource").''; print ''; print ' '; // Example: EUR - print ''; + print '';*/ print ''; print '
'; @@ -292,7 +292,7 @@ print ''; print ''; print ''; -print ''.$form->selectCurrency('', 'code').''; +print ''.$form->selectCurrency('', 'code', 1).''; print ''; print ' '; print ''; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 93cbdb138a0..3c4ac0b9804 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -4781,9 +4781,10 @@ class Form * * @param string $selected preselected currency code * @param string $htmlname name of HTML select list + * @param string $mode 0 = Add currency symbol into label, 1 = Add 3 letter iso code * @return string */ - public function selectCurrency($selected = '', $htmlname = 'currency_id') + public function selectCurrency($selected = '', $htmlname = 'currency_id', $mode = 0) { global $conf,$langs,$user; @@ -4805,7 +4806,14 @@ class Form $out.= ''; } $out.= ''; diff --git a/htdocs/langs/en_US/multicurrency.lang b/htdocs/langs/en_US/multicurrency.lang index 68791b41320..4dc04ff2622 100644 --- a/htdocs/langs/en_US/multicurrency.lang +++ b/htdocs/langs/en_US/multicurrency.lang @@ -7,7 +7,7 @@ multicurrency_syncronize_error=Synchronization error: %s MULTICURRENCY_USE_RATE_ON_DOCUMENT_DATE=Use the date of the document to find the currency rate, instead of using the latest known rate multicurrency_useOriginTx=When an object is created from another, keep the original rate from the source object (otherwise use the latest known rate) CurrencyLayerAccount=CurrencyLayer API -CurrencyLayerAccount_help_to_synchronize=You must create an account on website %s to use this functionality.
Get your API key.
If you use a free account you can't change the currency source (USD by default).
If your main currency is not USD you can use the alternate currency source to force your main currency.

You are limited to 1000 synchronizations per month. +CurrencyLayerAccount_help_to_synchronize=You must create an account on website %s to use this functionality.
Get your API key.
If you use a free account, you can't change the source currency (USD by default).
If your main currency is not USD, the application will automatically recalculate it.

You are limited to 1000 synchronizations per month. multicurrency_appId=API key multicurrency_appCurrencySource=Source currency multicurrency_alternateCurrencySource=Alternate source currency diff --git a/htdocs/multicurrency/class/multicurrency.class.php b/htdocs/multicurrency/class/multicurrency.class.php index faf05bdc571..a694b5396d7 100644 --- a/htdocs/multicurrency/class/multicurrency.class.php +++ b/htdocs/multicurrency/class/multicurrency.class.php @@ -603,9 +603,9 @@ class MultiCurrency extends CommonObject { global $conf; - if (!empty($conf->global->MULTICURRENCY_ALTERNATE_SOURCE)) + if ($conf->currency != $conf->global->MULTICURRENCY_APP_SOURCE) { - $alternate_source = 'USD'.$conf->global->MULTICURRENCY_ALTERNATE_SOURCE; + $alternate_source = 'USD'.$conf->currency; if (!empty($TRate->{$alternate_source})) { $coef = $TRate->USDUSD / $TRate->{$alternate_source}; From a75223c850487f55e814f0add4eb15acd80190dc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 2 May 2019 13:53:13 +0200 Subject: [PATCH 116/132] Debug ticket module --- htdocs/langs/en_US/ticket.lang | 2 +- htdocs/ticket/class/ticket.class.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/langs/en_US/ticket.lang b/htdocs/langs/en_US/ticket.lang index c84dc17f087..030858eecce 100644 --- a/htdocs/langs/en_US/ticket.lang +++ b/htdocs/langs/en_US/ticket.lang @@ -60,7 +60,7 @@ NotRead=Not read Read=Read Assigned=Assigned InProgress=In progress -NeedMoreInformation=Waiting more information +NeedMoreInformation=Waiting for information Answered=Answered Waiting=Waiting Closed=Closed diff --git a/htdocs/ticket/class/ticket.class.php b/htdocs/ticket/class/ticket.class.php index bae523b1819..c049712d623 100644 --- a/htdocs/ticket/class/ticket.class.php +++ b/htdocs/ticket/class/ticket.class.php @@ -194,7 +194,7 @@ class Ticket extends CommonObject 'datec' => array('type'=>'datetime', 'label'=>'DateCreation', 'visible'=>1, 'enabled'=>1, 'position'=>500, 'notnull'=>1), 'date_read' => array('type'=>'datetime', 'label'=>'TicketReadOn', 'visible'=>1, 'enabled'=>1, 'position'=>500, 'notnull'=>1), 'fk_user_assign' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'AssignedTo', 'visible'=>1, 'enabled'=>1, 'position'=>505, 'notnull'=>1), - 'date_close' => array('type'=>'datetime', 'label'=>'TicketCloseOn', 'visible'=>1, 'enabled'=>1, 'position'=>510, 'notnull'=>1), + 'date_close' => array('type'=>'datetime', 'label'=>'TicketCloseOn', 'visible'=>-1, 'enabled'=>1, 'position'=>510, 'notnull'=>1), 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'visible'=>-1, 'enabled'=>1, 'position'=>520, 'notnull'=>1), 'message' => array('type'=>'text', 'label'=>'Message', 'visible'=>-2, 'enabled'=>1, 'position'=>540, 'notnull'=>-1,), 'progress' => array('type'=>'varchar(100)', 'label'=>'Progression', 'visible'=>-1, 'enabled'=>1, 'position'=>540, 'notnull'=>-1, 'css'=>'right', 'help'=>""), From 263b6cafbcb4748dfd1dd13492f73aae14d6be5b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 2 May 2019 14:03:35 +0200 Subject: [PATCH 117/132] Fix var --- htdocs/core/actions_massactions.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index 973dae1bbee..4d0a3c878db 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -216,7 +216,7 @@ if (! $error && $massaction == 'confirm_presend') $resaction.='
'.$langs->trans('ErrorOnlyProposalNotDraftCanBeSentInMassAction', $objectobj->ref).'

'; continue; // Payment done or started or canceled } - if ($objectclass == 'Commande' && $objectoj->statut == Commande::STATUS_DRAFT) + if ($objectclass == 'Commande' && $objectojb->statut == Commande::STATUS_DRAFT) { $langs->load("errors"); $nbignored++; From cbe23741ebe62ca978c516f70e1257587b921a44 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Thu, 2 May 2019 14:06:55 +0200 Subject: [PATCH 118/132] FIX Massive debug in lettering function --- .../thirdparty_lettering_customer.php | 155 +++++++++++------- .../thirdparty_lettering_supplier.php | 151 ++++++++++------- htdocs/accountancy/class/lettering.class.php | 20 +-- htdocs/langs/en_US/accountancy.lang | 1 + 4 files changed, 195 insertions(+), 132 deletions(-) diff --git a/htdocs/accountancy/bookkeeping/thirdparty_lettering_customer.php b/htdocs/accountancy/bookkeeping/thirdparty_lettering_customer.php index 1d370176613..fed41d70b53 100644 --- a/htdocs/accountancy/bookkeeping/thirdparty_lettering_customer.php +++ b/htdocs/accountancy/bookkeeping/thirdparty_lettering_customer.php @@ -3,8 +3,8 @@ * Copyright (C) 2005 Laurent Destailleur * Copyright (C) 2013 Olivier Geffroy * Copyright (C) 2013 Florian Henry - * Copyright (C) 2013-2018 Alexandre Spangaro - * Copyright (C) 2018 Frédéric France + * Copyright (C) 2013-2019 Alexandre Spangaro + * Copyright (C) 2018 Frédéric France * * 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 @@ -30,6 +30,7 @@ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT . '/core/class/html.formaccounting.class.php'; require_once DOL_DOCUMENT_ROOT . '/accountancy/class/bookkeeping.class.php'; require_once DOL_DOCUMENT_ROOT . '/accountancy/class/lettering.class.php'; +require_once DOL_DOCUMENT_ROOT . '/accountancy/class/accountingjournal.class.php'; require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php'; @@ -53,26 +54,31 @@ $offset = $limit * $page; $pageprev = $page - 1; $pagenext = $page + 1; if ($sortorder == "") - $sortorder = "DESC"; + $sortorder = "ASC"; if ($sortfield == "") $sortfield = "bk.doc_date"; -$search_year = GETPOST("search_year", 'int'); -$search_doc_type = GETPOST("search_doc_type", 'alpha'); +/* +$search_date_start = dol_mktime(0, 0, 0, GETPOST('date_startmonth', 'int'), GETPOST('date_startday', 'int'), GETPOST('date_startyear', 'int')); +$search_date_end = dol_mktime(0, 0, 0, GETPOST('date_endmonth', 'int'), GETPOST('date_endday', 'int'), GETPOST('date_endyear', 'int')); +//$search_doc_type = GETPOST("search_doc_type", 'alpha'); $search_doc_ref = GETPOST("search_doc_ref", 'alpha'); +*/ $lettering = GETPOST('lettering', 'alpha'); if (! empty($lettering)) { $action = $lettering; } -// Did we click on purge search criteria ? -// All tests are required to be compatible with all browsers -if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { - $search_year = ''; - $search_doc_type = ''; +/* +if (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha')) // All tests are required to be compatible with all browsers +{ + $search_date_start = ''; + $search_date_end = ''; + //$search_doc_type = ''; $search_doc_ref = ''; } +*/ // Security check $socid = GETPOST("socid", 'int'); @@ -102,6 +108,7 @@ if ($action == 'lettering') { } } +/* if ($action == 'autolettrage') { $result = $lettering->letteringThirdparty($socid); @@ -111,9 +118,9 @@ if ($action == 'autolettrage') { $error++; } } +*/ - - /* +/* * View */ @@ -136,19 +143,17 @@ dol_banner_tab($object, 'socid', $linkback, ($user->societe_id?0:1), 'rowid', 'n dol_fiche_end(); -print '
'; - $sql = "SELECT bk.rowid, bk.doc_date, bk.doc_type, bk.doc_ref, "; $sql .= " bk.subledger_account, bk.numero_compte , bk.label_compte, bk.debit, "; $sql .= " bk.credit, bk.montant , bk.sens , bk.code_journal , bk.piece_num, bk.lettering_code "; $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as bk"; $sql .= " WHERE (bk.subledger_account = '" . $object->code_compta . "' AND bk.numero_compte = '" . $conf->global->ACCOUNTING_ACCOUNT_CUSTOMER . "' )"; -if (dol_strlen($search_year)) { - $date_start = dol_mktime(0, 0, 0, 1, 1, $search_year); - $date_end = dol_mktime(23, 59, 59, 12, 31, $search_year); - $sql .= " AND ( bk.doc_date BETWEEN '" . $db->idate($date_start) . "' AND '" . $db->idate($date_end) . "' )"; +/* +if (dol_strlen($search_date_start) || dol_strlen($search_date_end)) { + $sql .= " AND ( bk.doc_date BETWEEN '" . $db->idate($search_date_start) . "' AND '" . $db->idate($search_date_end) . "' )"; } +*/ $sql.= ' AND bk.entity IN ('.getEntity('accountingbookkeeping').')'; $sql .= $db->order($sortfield, $sortorder); @@ -190,34 +195,57 @@ if ($resql) { print '
'; print ''; - print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_companies', 0, '', '', $limit); + $letteringbutton = ''; + //$letteringbutton = '' . $langs->trans("Lettering") . ''; + + print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_companies', 0, $letteringbutton, '', $limit); print ""; + + /* + print ''; + //print ''; + + // Date + print ''; + + // Piece + print ''; + + print ''; + print ''; + print ''; + */ + print ''; - print_liste_field_titre("Doctype", $_SERVER["PHP_SELF"], "bk.doc_type", "", $param, "", $sortfield, $sortorder); - print_liste_field_titre("Docdate", $_SERVER["PHP_SELF"], "bk.doc_date", "", $param, "", $sortfield, $sortorder); - print_liste_field_titre("Docref", $_SERVER["PHP_SELF"], "bk.doc_ref", "", $param, "", $sortfield, $sortorder); + //print_liste_field_titre("Doctype", $_SERVER["PHP_SELF"], "bk.doc_type", "", $param, "", $sortfield, $sortorder); + print_liste_field_titre("Docdate", $_SERVER["PHP_SELF"], "bk.doc_date", "", $param, "", $sortfield, $sortorder, 'center '); + print_liste_field_titre("Piece", $_SERVER["PHP_SELF"], "bk.doc_ref", "", $param, "", $sortfield, $sortorder); print_liste_field_titre("LabelAccount", $_SERVER["PHP_SELF"], "bk.label_compte", "", $param, "", $sortfield, $sortorder); print_liste_field_titre("Debit", $_SERVER["PHP_SELF"], "bk.debit", "", $param, "", $sortfield, $sortorder); print_liste_field_titre("Credit", $_SERVER["PHP_SELF"], "bk.credit", "", $param, "", $sortfield, $sortorder); print_liste_field_titre("Balancing", $_SERVER["PHP_SELF"], "", "", $param, "", $sortfield, $sortorder); - print_liste_field_titre("Codejournal", $_SERVER["PHP_SELF"], "bk.code_journal", "", $param, "", $sortfield, $sortorder); - print_liste_field_titre("LetteringCode", $_SERVER["PHP_SELF"], "bk.lettering_code", "", $param, "", $sortfield, $sortorder); + print_liste_field_titre("Codejournal", $_SERVER["PHP_SELF"], "bk.code_journal", "", $param, "", $sortfield, $sortorder, 'center '); + print_liste_field_titre("LetteringCode", $_SERVER["PHP_SELF"], "bk.lettering_code", "", $param, "", $sortfield, $sortorder, 'center '); + print_liste_field_titre("", "","",'','',"",$sortfield,$sortorder,'maxwidthsearch center '); print "\n"; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - $solde = 0; $tmp = ''; + + if (empty($obj->lettering_code)) $rowaction++; while ( $obj = $db->fetch_object($resql) ) { if ($tmp != $obj->lettering_code || empty($tmp)) $tmp = $obj->lettering_code; @@ -225,48 +253,53 @@ if ($resql) { print ''; - if (empty($obj->lettering_code)) { - print '' . "\n"; - } else { - print '' . "\n"; - } - - print ''; + //print '' . "\n"; + print ''; print ''; print ''; - print ''; - print ''; - print ''; - print ''; + print ''; + print ''; + print ''; - if (empty($obj->lettering_code)) { - print ''; - } else - print ''; + // Journal + $accountingjournal = new AccountingJournal($db); + $result = $accountingjournal->fetch('',$obj->code_journal); + $journaltoshow = (($result > 0)?$accountingjournal->getNomUrl(0,0,0,'',0) : $obj->code_journal); + print ''; + + if (empty($obj->lettering_code)) { + print ''; + print '' . "\n"; + } else { + print ''; + print ''; + } print "\n"; } print ''; - print '' . "\n"; - print ''; - print ''; - print ''; + print '' . "\n"; + print ''; + print ''; + print ''; print "\n"; print ''; - print '' . "\n"; + print '' . "\n"; print ''; - print ''; - print ''; + print ''; + print ''; print "\n"; print "
'; + print '
'; + print $langs->trans('From') . ' '; + print $form->selectDate($search_date_start, 'date_creation_start', 0, 0, 1); + print '
'; + print '
'; + print $langs->trans('to') . ' '; + print $form->selectDate($search_date_end, 'date_creation_end', 0, 0, 1); + print '
'; + print '
 '; + $searchpicto = $form->showFilterButtons(); + print $searchpicto; + print '
 '; - $searchpicto = $form->showFilterButtons(); - print $searchpicto; - print '
'; - print img_edit(); - print ' ' . $obj->doc_type . '' . $obj->doc_type . '' . dol_print_date($db->jdate($obj->doc_date), 'day') . '' . $obj->doc_type . '' . dol_print_date($db->jdate($obj->doc_date), 'day') . '' . $obj->doc_ref . '' . $obj->label_compte . '' . price($obj->debit) . '' . price($obj->credit) . '' . price(round($solde, 2)) . '' . $obj->code_journal . '' . price($obj->debit) . '' . price($obj->credit) . '' . price(round($solde, 2)) . '' . $obj->lettering_code . '' . $journaltoshow . ''; + print img_edit(); + print '' . $obj->lettering_code . '
'.$langs->trans("Total").':' . price($debit) . '' . price($credit) . ''.$langs->trans("Total").':' . price($debit) . '' . price($credit) . '
'.$langs->trans("Balancing").':'.$langs->trans("Balancing").': ' . price($credit - $debit) . '' . price($credit - $debit) . '
"; - print ''; - //print '' . $langs->trans('AccountancyAutoLettering') . ''; + print '
'."\n"; + print $letteringbutton; + print '
'; + print "
"; $db->free($resql); } else { diff --git a/htdocs/accountancy/bookkeeping/thirdparty_lettering_supplier.php b/htdocs/accountancy/bookkeeping/thirdparty_lettering_supplier.php index 1d80bda7710..3795099c78d 100644 --- a/htdocs/accountancy/bookkeeping/thirdparty_lettering_supplier.php +++ b/htdocs/accountancy/bookkeeping/thirdparty_lettering_supplier.php @@ -3,8 +3,8 @@ * Copyright (C) 2005 Laurent Destailleur * Copyright (C) 2013 Olivier Geffroy * Copyright (C) 2013 Florian Henry - * Copyright (C) 2013-2018 Alexandre Spangaro - * Copyright (C) 2018 Frédéric France + * Copyright (C) 2013-2019 Alexandre Spangaro + * Copyright (C) 2018 Frédéric France * * 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 @@ -30,6 +30,7 @@ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT . '/core/class/html.formaccounting.class.php'; require_once DOL_DOCUMENT_ROOT . '/accountancy/class/bookkeeping.class.php'; require_once DOL_DOCUMENT_ROOT . '/accountancy/class/lettering.class.php'; +require_once DOL_DOCUMENT_ROOT . '/accountancy/class/accountingjournal.class.php'; require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php'; @@ -53,27 +54,31 @@ $offset = $limit * $page; $pageprev = $page - 1; $pagenext = $page + 1; if ($sortorder == "") - $sortorder = "DESC"; + $sortorder = "ASC"; if ($sortfield == "") $sortfield = "bk.doc_date"; -$search_year = GETPOST("search_year",'int'); -$search_doc_type = GETPOST("search_doc_type",'alpha'); +/* +$search_date_start = dol_mktime(0, 0, 0, GETPOST('date_startmonth', 'int'), GETPOST('date_startday', 'int'), GETPOST('date_startyear', 'int')); +$search_date_end = dol_mktime(0, 0, 0, GETPOST('date_endmonth', 'int'), GETPOST('date_endday', 'int'), GETPOST('date_endyear', 'int')); +//$search_doc_type = GETPOST("search_doc_type",'alpha'); $search_doc_ref = GETPOST("search_doc_ref",'alpha'); +*/ $lettering = GETPOST('lettering', 'alpha'); if (!empty($lettering)) { $action=$lettering; } -// Did we click on purge search criteria ? -// All tests are required to be compatible with all browsers -if (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha')) +/* +if (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha')) // All tests are required to be compatible with all browsers { - $search_year=''; - $search_doc_type=''; + $search_date_start = ''; + $search_date_end = ''; + //$search_doc_type=''; $search_doc_ref=''; } +*/ // Security check @@ -103,6 +108,7 @@ if ($action == 'lettering') { } } +/* if ($action == 'autolettrage') { $result = $lettering->letteringThirdparty($socid); @@ -112,7 +118,7 @@ if ($action == 'autolettrage') { $error++; } } - +*/ /* * View @@ -143,10 +149,8 @@ $sql .= " bk.credit, bk.montant , bk.sens , bk.code_journal , bk.piece_num, bk.l $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as bk"; $sql .= " WHERE (bk.subledger_account = '" . $object->code_compta_fournisseur . "' AND bk.numero_compte = '" . $conf->global->ACCOUNTING_ACCOUNT_SUPPLIER . "' )"; -if (dol_strlen($search_year)) { - $date_start = dol_mktime(0, 0, 0, 1, 1, $search_year); - $date_end = dol_mktime(23, 59, 59, 12, 31, $search_year); - $sql .= " AND ( bk.doc_date BETWEEN '".$db->idate($date_start)."' AND '".$db->idate($date_end)."' )"; +if (dol_strlen($search_date_start) || dol_strlen($search_date_end)) { + $sql .= " AND (bk.doc_date BETWEEN '".$db->idate($search_date_start)."' AND '".$db->idate($search_date_end)."' )"; } $sql.= ' AND bk.entity IN ('.getEntity('accountingbookkeeping').')'; @@ -193,31 +197,51 @@ if ($resql) { print '
'; print ''; - print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_companies', 0, '', '', $limit); + $letteringbutton = '\'; + + print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_companies', 0, $letteringbutton, '', $limit); print ""; - print ''; - print_liste_field_titre("Doctype", $_SERVER["PHP_SELF"], "bk.doc_type","",$param,"",$sortfield,$sortorder); - print_liste_field_titre("Docdate", $_SERVER["PHP_SELF"], "bk.doc_date","",$param,"",$sortfield,$sortorder); - print_liste_field_titre("Docref", $_SERVER["PHP_SELF"], "bk.doc_ref","",$param,"",$sortfield,$sortorder); - print_liste_field_titre("LabelAccount", $_SERVER["PHP_SELF"], "bk.label_compte","",$param,"",$sortfield,$sortorder); - print_liste_field_titre("Debit", $_SERVER["PHP_SELF"], "bk.debit","",$param,"",$sortfield,$sortorder); - print_liste_field_titre("Credit", $_SERVER["PHP_SELF"], "bk.credit","",$param,"",$sortfield,$sortorder); - print_liste_field_titre("Balancing", $_SERVER["PHP_SELF"], "","",$param,"",$sortfield,$sortorder); - print_liste_field_titre("Codejournal", $_SERVER["PHP_SELF"], "bk.code_journal","",$param,"",$sortfield,$sortorder); - print_liste_field_titre("LetteringCode", $_SERVER["PHP_SELF"], "bk.lettering_code", "", $param, "", $sortfield, $sortorder); - print "\n"; + + /* + print ''; + //print ''; + + // Date + print ''; + + // Piece + print ''; + + print ''; + print ''; + print ''; + */ print ''; - print ''; - print ''; - print ''; - print ''; - print ''; - print ''; + //print_liste_field_titre("Doctype", $_SERVER["PHP_SELF"], "bk.doc_type", "", $param, "", $sortfield, $sortorder); + print_liste_field_titre("Docdate", $_SERVER["PHP_SELF"], "bk.doc_date", "", $param, "", $sortfield, $sortorder, 'center '); + print_liste_field_titre("Piece", $_SERVER["PHP_SELF"], "bk.doc_ref", "", $param, "", $sortfield, $sortorder); + print_liste_field_titre("LabelAccount", $_SERVER["PHP_SELF"], "bk.label_compte", "", $param, "", $sortfield, $sortorder); + print_liste_field_titre("Debit", $_SERVER["PHP_SELF"], "bk.debit", "", $param, "", $sortfield, $sortorder); + print_liste_field_titre("Credit", $_SERVER["PHP_SELF"], "bk.credit", "", $param, "", $sortfield, $sortorder); + print_liste_field_titre("Balancing", $_SERVER["PHP_SELF"], "", "", $param, "", $sortfield, $sortorder); + print_liste_field_titre("Codejournal", $_SERVER["PHP_SELF"], "bk.code_journal", "", $param, "", $sortfield, $sortorder, 'center '); + print_liste_field_titre("LetteringCode", $_SERVER["PHP_SELF"], "bk.lettering_code", "", $param, "", $sortfield, $sortorder, 'center '); + print_liste_field_titre("", "","",'','',"",$sortfield,$sortorder,'maxwidthsearch center '); + print "\n"; $solde = 0; $tmp = ''; @@ -228,48 +252,53 @@ if ($resql) { print ''; - if (empty($obj->lettering_code)) { - print '' . "\n"; - } else { - print '' . "\n"; - } - - print ''; + //print '' . "\n"; + print ''; print ''; print ''; - print ''; - print ''; - print ''; - print ''; + print ''; + print ''; + print ''; + + // Journal + $accountingjournal = new AccountingJournal($db); + $result = $accountingjournal->fetch('',$obj->code_journal); + $journaltoshow = (($result > 0)?$accountingjournal->getNomUrl(0,0,0,'',0) : $obj->code_journal); + print ''; if (empty($obj->lettering_code)) { - print ''; - } else - print ''; + print ''; + print '' . "\n"; + } else { + print ''; + print ''; + } print "\n"; } print ''; - print '' . "\n"; - print ''; - print ''; - print ''; + print '' . "\n"; + print ''; + print ''; + print ''; print "\n"; print ''; - print '' . "\n"; + print '' . "\n"; print ''; - print ''; - print ''; + print ''; + print ''; print "\n"; print "
'; + print '
'; + print $langs->trans('From') . ' '; + print $form->selectDate($search_date_start, 'date_creation_start', 0, 0, 1); + print '
'; + print '
'; + print $langs->trans('to') . ' '; + print $form->selectDate($search_date_end, 'date_creation_end', 0, 0, 1); + print '
'; + print '
 '; + $searchpicto = $form->showFilterButtons(); + print $searchpicto; + print '
 '; - $searchpicto=$form->showFilterButtons(); - print $searchpicto; - print '
'; - print img_edit(); - print ' ' . $obj->doc_type . '' . $obj->doc_type . '' . dol_print_date($db->jdate($obj->doc_date), 'day') . '' . $obj->doc_type . '' . dol_print_date($db->jdate($obj->doc_date), 'day') . '' . $obj->doc_ref . '' . $obj->label_compte . '' . price($obj->debit) . '' . price($obj->credit) . '' . price(round($solde, 2)) . '' . $obj->code_journal . '' . price($obj->debit) . '' . price($obj->credit) . '' . price(round($solde, 2)) . '' . $journaltoshow . '' . $obj->lettering_code . ''; + print img_edit(); + print '' . $obj->lettering_code . '
'.$langs->trans("Total").':' . price($debit) . '' . price($credit) . ''.$langs->trans("Total").':' . price($debit) . '' . price($credit) . '
'.$langs->trans("Balancing").':'.$langs->trans("Balancing").': ' . price($credit - $debit) . '' . price($credit - $debit) . '
"; - print ''; - //print ''.$langs->trans('AccountancyAutoLettering').''; + print '
'."\n"; + print $letteringbutton; + print '
'; + print "
"; $db->free($resql); } else { diff --git a/htdocs/accountancy/class/lettering.class.php b/htdocs/accountancy/class/lettering.class.php index b0ad8150ad4..174f5fa42f5 100644 --- a/htdocs/accountancy/class/lettering.class.php +++ b/htdocs/accountancy/class/lettering.class.php @@ -1,7 +1,7 @@ * Copyright (C) 2013 Olivier Geffroy - * Copyright (C) 2013-2018 Alexandre Spangaro + * Copyright (C) 2013-2019 Alexandre Spangaro * Copyright (C) 2018 Frédéric France * * This program is free software; you can redistribute it and/or modify @@ -66,13 +66,13 @@ class Lettering extends BookKeeping $sql .= " , bk.sens , bk.code_journal , bk.piece_num, bk.date_lettering, bu.url_id , bu.type "; $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as bk"; $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "bank_url as bu ON(bk.fk_doc = bu.fk_bank AND bu.type IN ('payment', 'payment_supplier') ) "; - $sql .= " WHERE ( "; + $sql .= " WHERE ( "; if (! empty($object->code_compta)) - $sql .= " bk.subledger_account = '" . $object->code_compta . "' "; + $sql .= " bk.subledger_account = '" . $object->code_compta . "' "; if (! empty($object->code_compta) && ! empty($object->code_compta_fournisseur)) - $sql .= " OR "; + $sql .= " OR "; if (! empty($object->code_compta_fournisseur)) - $sql .= " bk.subledger_account = '" . $object->code_compta_fournisseur . "' "; + $sql .= " bk.subledger_account = '" . $object->code_compta_fournisseur . "' "; $sql .= " ) AND (bk.date_lettering ='' OR bk.date_lettering IS NULL) "; $sql .= " AND (bk.lettering_code != '' OR bk.lettering_code IS NULL) "; @@ -128,15 +128,15 @@ class Lettering extends BookKeeping $sql .= " AND facf.entity = ".$conf->entity; $sql .= " AND ( "; if (! empty($object->code_compta)) { - $sql .= " bk.subledger_account = '" . $object->code_compta . "' "; + $sql .= " bk.subledger_account = '" . $object->code_compta . "' "; } if (! empty($object->code_compta) && ! empty($object->code_compta_fournisseur)) { - $sql .= " OR "; + $sql .= " OR "; } if (! empty($object->code_compta_fournisseur)) { - $sql .= " bk.subledger_account = '" . $object->code_compta_fournisseur . "' "; + $sql .= " bk.subledger_account = '" . $object->code_compta_fournisseur . "' "; } - $sql .= " ) "; + $sql .= ") "; $resql2 = $this->db->query($sql); if ($resql2) { @@ -253,7 +253,7 @@ class Lettering extends BookKeeping $error++; } - $sql = "SELECT SUM(ABS(debit)) as deb, SUM(ABS(credit)) as cred FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping WHERE "; + $sql = "SELECT SUM(ABS(debit)) as deb, SUM(ABS(credit)) as cred FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping WHERE "; $sql .= " rowid IN (" . implode(',', $ids) . ") "; $result = $this->db->query($sql); if ($result) { diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index 31f3d5e264a..c7e9baa04ac 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -161,6 +161,7 @@ LabelAccount=Label account LabelOperation=Label operation Sens=Sens LetteringCode=Lettering code +Lettering=Lettering Codejournal=Journal NumPiece=Piece number TransactionNumShort=Num. transaction From 7bd99c0eee588e8135a9b671ddfabc69cb23fbdd Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Thu, 2 May 2019 14:08:28 +0200 Subject: [PATCH 119/132] fix --- .../accountancy/bookkeeping/thirdparty_lettering_customer.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/htdocs/accountancy/bookkeeping/thirdparty_lettering_customer.php b/htdocs/accountancy/bookkeeping/thirdparty_lettering_customer.php index fed41d70b53..87377a189a6 100644 --- a/htdocs/accountancy/bookkeeping/thirdparty_lettering_customer.php +++ b/htdocs/accountancy/bookkeeping/thirdparty_lettering_customer.php @@ -245,8 +245,7 @@ if ($resql) { $solde = 0; $tmp = ''; - if (empty($obj->lettering_code)) $rowaction++; - while ( $obj = $db->fetch_object($resql) ) { + while ( $obj = $db->fetch_object($resql) ) { if ($tmp != $obj->lettering_code || empty($tmp)) $tmp = $obj->lettering_code; /*if ($tmp != $obj->lettering_code || empty($obj->lettering_code))*/ $solde += ($obj->credit - $obj->debit); From 8e936fda4f2b0d300a803787412df676965cccd3 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Thu, 2 May 2019 14:19:50 +0200 Subject: [PATCH 120/132] FIX : typo error --- htdocs/takepos/takepos.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/takepos/takepos.php b/htdocs/takepos/takepos.php index 143c6abf063..d5d81880a4e 100644 --- a/htdocs/takepos/takepos.php +++ b/htdocs/takepos/takepos.php @@ -55,7 +55,7 @@ if ($conf->browser->layout == 'phone') $maxproductbydefaultforthisdevice=16; } $MAXCATEG = (empty($conf->global->TAKEPOS_NB_MAXCATEG)?$maxcategbydefaultforthisdevice:$conf->global->TAKEPOS_NB_MAXCATEG); -$MAXPRODUCT = (empty($conf->global->TAKEPOS_NB_MAXPRODUCT)?$maxproductbydefaultforthisdevice:$conf->global->TAKEPOS_NB_MAXPRODUCT);; +$MAXPRODUCT = (empty($conf->global->TAKEPOS_NB_MAXPRODUCT)?$maxproductbydefaultforthisdevice:$conf->global->TAKEPOS_NB_MAXPRODUCT); /* From bcd96ba8d6793977b0fc04418e6d198d408b36e4 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Thu, 2 May 2019 14:42:02 +0200 Subject: [PATCH 121/132] inactive a var_dump --- htdocs/compta/cashcontrol/cashcontrol_card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/cashcontrol/cashcontrol_card.php b/htdocs/compta/cashcontrol/cashcontrol_card.php index 80572b40efc..76a265e842e 100644 --- a/htdocs/compta/cashcontrol/cashcontrol_card.php +++ b/htdocs/compta/cashcontrol/cashcontrol_card.php @@ -200,7 +200,7 @@ if ($action == 'confirm_delete' && ! empty($permissiontodelete)) } $result=$object->delete($user); - var_dump($result); + //var_dump($result); if ($result > 0) { // Delete OK From 8d7f24a6d9b52e321f797632b583bbdc6a3657f3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 2 May 2019 15:34:29 +0200 Subject: [PATCH 122/132] FIX Default value on form to send email --- htdocs/core/class/html.formmail.class.php | 4 ++-- htdocs/core/lib/functions.lib.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index bf03477643b..d455d1058fc 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -711,7 +711,7 @@ class FormMail extends Form } else { - $out.= 'withtocc) : (isset($_POST["sendtocc"])?$_POST["sendtocc"]:"") ).'" />'; + $out.= 'withtocc) && ! is_numeric($this->withtocc)) ? $this->withtocc : '')).'" />'; if (! empty($this->withtocc) && is_array($this->withtocc)) { $out.= " ".$langs->trans("and")."/".$langs->trans("or")." "; @@ -762,7 +762,7 @@ class FormMail extends Form } else { - $out.= 'withtoccc) : (isset($_POST["sendtoccc"])?$_POST["sendtoccc"]:"") ).'" />'; + $out.= 'withtoccc) && ! is_numeric($this->withtoccc)) ? $this->withtoccc : '')).'" />'; if (! empty($this->withtoccc) && is_array($this->withtoccc)) { $out.= " ".$langs->trans("and")."/".$langs->trans("or")." "; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 8c3393dd08e..570d00ef2bd 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -349,7 +349,7 @@ function GETPOST($paramname, $check='none', $method=0, $filter=null, $options=nu } if (! empty($conf->global->MAIN_ENABLE_DEFAULT_VALUES)) { - if (! empty($_GET['action']) && $_GET['action'] == 'create' && ! isset($_GET[$paramname]) && ! isset($_POST[$paramname])) + if (! empty($_GET['action']) && (preg_match('/^create/', $_GET['action']) || preg_match('/^presend/', $_GET['action'])) && ! isset($_GET[$paramname]) && ! isset($_POST[$paramname])) { // Now search in setup to overwrite default values if (! empty($user->default_values)) // $user->default_values defined from menu 'Setup - Default values' From 2839eedbbfacd2a504711d0c3caef6451876bc20 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 2 May 2019 16:06:14 +0200 Subject: [PATCH 123/132] Fix error on emailcollector for tickets --- htdocs/emailcollector/class/emailcollector.class.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 710afc05cec..e52b1bf156e 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -1613,7 +1613,7 @@ class EmailCollector extends CommonObject if ($savesocid != $projecttocreate->socid) { $errorforactions++; - setEventMessages('You loaded a thirdparty (id='.$savesocid.') and you force another thirdparty id (id='.$projecttocreate->socid.') by setting socid in operation with a different value'); + setEventMessages('You loaded a thirdparty (id='.$savesocid.') and you force another thirdparty id (id='.$projecttocreate->socid.') by setting socid in operation with a different value', null, 'errors'); } } else { @@ -1721,14 +1721,14 @@ class EmailCollector extends CommonObject if ($filefound) { $result=dol_include_once($reldir."core/modules/ticket/".$modele.'.php'); - $modProject = new $classname; + $modTicket = new $classname; if ($savesocid > 0) { if ($savesocid != $tickettocreate->socid) { $errorforactions++; - setEventMessages('You loaded a thirdparty (id='.$savesocid.') and you force another thirdparty id (id='.$tickettocreate->socid.') by setting socid in operation with a different value'); + setEventMessages('You loaded a thirdparty (id='.$savesocid.') and you force another thirdparty id (id='.$tickettocreate->socid.') by setting socid in operation with a different value', null, 'errors'); } } else { @@ -1738,7 +1738,7 @@ class EmailCollector extends CommonObject } } - $defaultref = $modTicket->getNextValue(($thirdpartystatic->id > 0 ? $thirdpartystatic : null), $projecttocreate); + $defaultref = $modTicket->getNextValue(($thirdpartystatic->id > 0 ? $thirdpartystatic : null), $tickettocreate); } $tickettocreate->ref = $defaultref; } From a764a79c1f1eeb4f5c82eef877b480c2a27b9257 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 2 May 2019 16:08:58 +0200 Subject: [PATCH 124/132] Fix scrutinizer error --- htdocs/categories/class/api_categories.class.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/htdocs/categories/class/api_categories.class.php b/htdocs/categories/class/api_categories.class.php index 9b59e1f001b..c82d803f31c 100644 --- a/htdocs/categories/class/api_categories.class.php +++ b/htdocs/categories/class/api_categories.class.php @@ -391,8 +391,11 @@ class Categories extends DolibarrApi } elseif ($type == 'contact') { $objects_api = new Contacts(); } - foreach ($objects as $obj) { - $cleaned_objects[] = $objects_api->_cleanObjectDatas($obj); + if (is_object($objects_api)) + { + foreach ($objects as $obj) { + $cleaned_objects[] = $objects_api->_cleanObjectDatas($obj); + } } return $cleaned_objects; From 4899d03ff8a164f6b2c409f13f637c26cf8c43c0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 2 May 2019 17:15:24 +0200 Subject: [PATCH 125/132] FIX Confusion between expired and late --- htdocs/contrat/class/contrat.class.php | 27 ++++++++++++++++++++++---- htdocs/index.php | 8 ++++---- htdocs/langs/en_US/contracts.lang | 3 ++- htdocs/langs/fr_FR/main.lang | 2 +- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 0059609d071..4fdccd10883 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -2108,7 +2108,7 @@ class Contrat extends CommonObject $this->from.= ", ".MAIN_DB_PREFIX."societe as s"; if (!$user->rights->societe->client->voir && !$user->societe_id) $this->from.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; - if ($mode == 'inactives') + if ($mode == 'inactive') { $sql = "SELECT cd.rowid, cd.date_ouverture_prevue as datefin"; $sql.= $this->from; @@ -2123,25 +2123,44 @@ class Contrat extends CommonObject $sql.= " WHERE c.statut = 1"; $sql.= " AND c.rowid = cd.fk_contrat"; $sql.= " AND cd.statut = 4"; - $sql.= " AND cd.date_fin_validite < '".$this->db->idate(time())."'"; + $sql.= " AND cd.date_fin_validite < '".$this->db->idate(dol_now())."'"; + } + elseif ($mode == 'active') + { + $sql = "SELECT cd.rowid, cd.date_fin_validite as datefin"; + $sql.= $this->from; + $sql.= " WHERE c.statut = 1"; + $sql.= " AND c.rowid = cd.fk_contrat"; + $sql.= " AND cd.statut = 4"; + //$datetouse = dol_now(); + //$sql.= " AND cd.date_fin_validite < '".$this->db->idate($datetouse)."'"; } $sql.= " AND c.fk_soc = s.rowid"; $sql.= " AND c.entity = ".$conf->entity; if ($user->societe_id) $sql.=" AND c.fk_soc = ".$user->societe_id; if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= " AND c.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id; + + var_dump($sql); $resql=$this->db->query($sql); if ($resql) { $langs->load("contracts"); $now=dol_now(); - if ($mode == 'inactives') { + if ($mode == 'inactive') { $warning_delay = $conf->contrat->services->inactifs->warning_delay; $label = $langs->trans("BoardNotActivatedServices"); $url = DOL_URL_ROOT.'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&mode=0'; + } + elseif ($mode == 'expired') { + $warning_delay = $conf->contrat->services->expires->warning_delay; + $url = DOL_URL_ROOT.'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&mode=4&filter=expired'; + $label = $langs->trans("BoardExpiredServices"); } else { $warning_delay = $conf->contrat->services->expires->warning_delay; - $url = DOL_URL_ROOT.'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&mode=4&filter=expired'; + $url = DOL_URL_ROOT.'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&mode=4'; + //$url.= '&op2day='.$arraydatetouse['mday'].'&op2month='.$arraydatetouse['mon'].'&op2year='.$arraydatetouse['year']; + //if ($warning_delay >= 0) $url.='&filter=expired'; $label = $langs->trans("BoardRunningServices"); } diff --git a/htdocs/index.php b/htdocs/index.php index 1ef48ea9bae..81503139d88 100644 --- a/htdocs/index.php +++ b/htdocs/index.php @@ -432,9 +432,9 @@ if (! empty($conf->contrat->enabled) && $user->rights->contrat->lire) { include_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php'; $board=new Contrat($db); - $dashboardlines[] = $board->load_board($user,"inactives"); + $dashboardlines[] = $board->load_board($user, "inactive"); // Number of active services (expired) - $dashboardlines[] = $board->load_board($user,"expired"); + $dashboardlines[] = $board->load_board($user, "active"); } // Number of invoices customers (has paid) if (! empty($conf->facture->enabled) && $user->rights->facture->lire) @@ -553,7 +553,7 @@ $nbworkboardempty=0; if (! empty($valid_dashboardlines)) { $boxwork.='
'; - + foreach($valid_dashboardlines as $board) { if (empty($board->nbtodo)) $nbworkboardempty++; @@ -593,7 +593,7 @@ if (! empty($valid_dashboardlines)) $boxwork .='
'; $boxwork .='
'; $boxwork .='
'; - + $boxwork .='
'; $boxwork .=''; } diff --git a/htdocs/langs/en_US/contracts.lang b/htdocs/langs/en_US/contracts.lang index b4e8d7c96d9..efe6cae4667 100644 --- a/htdocs/langs/en_US/contracts.lang +++ b/htdocs/langs/en_US/contracts.lang @@ -64,7 +64,8 @@ DateStartRealShort=Real start date DateEndReal=Real end date DateEndRealShort=Real end date CloseService=Close service -BoardRunningServices=Expired running services +BoardRunningServices=Services running +BoardExpiredServices=Services expired ServiceStatus=Status of service DraftContracts=Drafts contracts CloseRefusedBecauseOneServiceActive=Contract can't be closed as there is at least one open service on it diff --git a/htdocs/langs/fr_FR/main.lang b/htdocs/langs/fr_FR/main.lang index c36882a2ad1..f17cbaed86c 100644 --- a/htdocs/langs/fr_FR/main.lang +++ b/htdocs/langs/fr_FR/main.lang @@ -456,7 +456,7 @@ Duration=Durée TotalDuration=Durée totale Summary=Résumé DolibarrStateBoard=Statistiques de la base -DolibarrWorkBoard=Éléments en attente +DolibarrWorkBoard=Tableau de bord des éléments ouverts NoOpenedElementToProcess=Aucun élément ouvert à traiter Available=Disponible NotYetAvailable=Pas encore disponible From 9b21c827c3ffc58a8e6ee28a087d1cde3e0c3be6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 2 May 2019 17:17:52 +0200 Subject: [PATCH 126/132] Fix remove var_dump --- htdocs/contrat/class/contrat.class.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 4fdccd10883..545cd9716f0 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -2140,7 +2140,6 @@ class Contrat extends CommonObject if ($user->societe_id) $sql.=" AND c.fk_soc = ".$user->societe_id; if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= " AND c.fk_soc = sc.fk_soc AND sc.fk_user = " .$user->id; - var_dump($sql); $resql=$this->db->query($sql); if ($resql) { From 4e94d92b703719d5d2dc373eb49d981509cb59f0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 2 May 2019 17:24:05 +0200 Subject: [PATCH 127/132] Fix link --- htdocs/contrat/class/contrat.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 545cd9716f0..f21e7c06b65 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -2149,15 +2149,15 @@ class Contrat extends CommonObject if ($mode == 'inactive') { $warning_delay = $conf->contrat->services->inactifs->warning_delay; $label = $langs->trans("BoardNotActivatedServices"); - $url = DOL_URL_ROOT.'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&mode=0'; + $url = DOL_URL_ROOT.'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&mode=0&sortfield=cd.date_fin_validite&sortorder=asc'; } elseif ($mode == 'expired') { $warning_delay = $conf->contrat->services->expires->warning_delay; - $url = DOL_URL_ROOT.'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&mode=4&filter=expired'; + $url = DOL_URL_ROOT.'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&mode=4&filter=expired&sortfield=cd.date_fin_validite&sortorder=asc'; $label = $langs->trans("BoardExpiredServices"); } else { $warning_delay = $conf->contrat->services->expires->warning_delay; - $url = DOL_URL_ROOT.'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&mode=4'; + $url = DOL_URL_ROOT.'/contrat/services_list.php?mainmenu=commercial&leftmenu=contracts&mode=4&sortfield=cd.date_fin_validite&sortorder=asc'; //$url.= '&op2day='.$arraydatetouse['mday'].'&op2month='.$arraydatetouse['mon'].'&op2year='.$arraydatetouse['year']; //if ($warning_delay >= 0) $url.='&filter=expired'; $label = $langs->trans("BoardRunningServices"); From 10d853cdb3d1be96921ad9886a05b52347a66d41 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 2 May 2019 21:54:28 +0200 Subject: [PATCH 128/132] Work on stripe payment using intent with option STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION --- htdocs/langs/en_US/paypal.lang | 3 +- htdocs/public/payment/newpayment.php | 265 +++++++++++++++++++++++++-- htdocs/stripe/class/stripe.class.php | 235 ++++++++++++------------ 3 files changed, 375 insertions(+), 128 deletions(-) diff --git a/htdocs/langs/en_US/paypal.lang b/htdocs/langs/en_US/paypal.lang index 51e98ccc8a2..1f8a9c2bd35 100644 --- a/htdocs/langs/en_US/paypal.lang +++ b/htdocs/langs/en_US/paypal.lang @@ -1,7 +1,7 @@ # Dolibarr language file - Source file is en_US - paypal PaypalSetup=PayPal module setup PaypalDesc=This module allows payment by customers via PayPal. This can be used for a ad-hoc payment or for a payment related to a Dolibarr object (invoice, order, ...) -PaypalOrCBDoPayment=Pay with PayPal (Credit Card or PayPal) +PaypalOrCBDoPayment=Pay with PayPal (Card or PayPal) PaypalDoPayment=Pay with PayPal PAYPAL_API_SANDBOX=Mode test/sandbox PAYPAL_API_USER=API username @@ -33,3 +33,4 @@ PaypalImportPayment=Import PayPal payments PostActionAfterPayment=Post actions after payments ARollbackWasPerformedOnPostActions=A rollback was performed on all Post actions. You must complete post actions manually if they are necessary. ValidationOfPaymentFailed=Validation of payment has failed +CardOwner=Card owner diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index f06228291ef..8489f0ef071 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -803,6 +803,28 @@ if (! $source) print ''; print ''."\n"; + if (! empty($conf->stripe->enabled) && $paymentmethod == 'stripe' && ! empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) + { + require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; + + $service = 'StripeLive'; + $servicestatus = 1; + + if (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha')) + { + $service = 'StripeTest'; + $servicestatus = 0; + } + $stripe = new Stripe($db); + $stripeacc = $stripe->getStripeAccount($service); + $stripecu = null; + // for dev only + print ''.$langs->trans("PaymentIntent"); + print ''; + $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, $object, $stripecu, $stripeacc, $servicestatus); + print ''.$paymentintent->id.''; + print ''."\n"; + } // We do not add fields shipToName, shipToStreet, shipToCity, shipToState, shipToCountryCode, shipToZip, shipToStreet2, phoneNum // as they don't exists (buyer is unknown, tag is free). } @@ -896,6 +918,29 @@ if ($source == 'order') print ''; print ''."\n"; + if (! empty($conf->stripe->enabled) && $paymentmethod == 'stripe' && empty($order->billed) && ! empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) + { + require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; + + $service = 'StripeLive'; + $servicestatus = 1; + + if (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha')) + { + $service = 'StripeTest'; + $servicestatus = 0; + } + $stripe = new Stripe($db); + $stripeacc = $stripe->getStripeAccount($service); + $stripecu = $stripe->customerStripe($order->thirdparty, $stripeacc, $servicestatus, 1); + // for dev only + print ''.$langs->trans("PaymentIntent"); + print ''; + $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, $object, $stripecu, $stripeacc, $servicestatus); + print ''.$paymentintent->id.''; + print ''."\n"; + } + // Shipping address $shipToName=$order->thirdparty->name; $shipToStreet=$order->thirdparty->address; @@ -1007,14 +1052,14 @@ if ($source == 'invoice') print ''; print ''; } - // Currency - print ' '.$langs->trans("Currency".$currency).''; - print ''; } else { - print price($object->total_ttc, 1, $langs); + print ''.price($object->total_ttc, 1, $langs).''; } + // Currency + print ' '.$langs->trans("Currency".$currency).''; + print ''; print ''."\n"; // Tag @@ -1024,6 +1069,28 @@ if ($source == 'invoice') print ''; print ''."\n"; + if (! empty($conf->stripe->enabled) && ($paymentmethod == 'stripe') && empty($object->paye) && ! empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) + { + require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; + + $service = 'StripeLive'; + $servicestatus = 1; + if (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha')) + { + $service = 'StripeTest'; + $servicestatus = 0; + } + $stripe = new Stripe($db); + $stripeacc = $stripe->getStripeAccount($service); + $stripecu = $stripe->customerStripe($invoice->thirdparty, $stripeacc, $servicestatus, 1); + // for dev only + print ''.$langs->trans("PaymentIntent"); + print ''; + $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, $object, $stripecu, $stripeacc, $servicestatus); + print ''.$paymentintent->id.''; + print ''."\n"; + } + // Shipping address $shipToName=$invoice->thirdparty->name; $shipToStreet=$invoice->thirdparty->address; @@ -1149,6 +1216,7 @@ if ($source == 'contractline') // Debitor print ''.$langs->trans("ThirdParty"); print ''.$contract->thirdparty->name.''; + print ''."\n"; // Object $text=''.$langs->trans("PaymentRenewContractId", $contract->ref, $contractline->ref).''; @@ -1234,6 +1302,29 @@ if ($source == 'contractline') print ''; print ''."\n"; + if (! empty($conf->stripe->enabled) && $paymentmethod == 'stripe' && ! empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) + { + require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; + + $service = 'StripeLive'; + $servicestatus = 1; + + if (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha')) + { + $service = 'StripeTest'; + $servicestatus = 0; + } + $stripe = new Stripe($db); + $stripeacc = $stripe->getStripeAccount($service); + $stripecu = null; + // for dev only + print ''.$langs->trans("PaymentIntent"); + print ''; + $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, $object, $stripecu, $stripeacc, $servicestatus); + print ''.$paymentintent->id.''; + print ''."\n"; + } + // Shipping address $shipToName=$contract->thirdparty->name; $shipToStreet=$contract->thirdparty->address; @@ -1400,6 +1491,29 @@ if ($source == 'membersubscription') print ''; print ''."\n"; + if (! empty($conf->stripe->enabled) && $paymentmethod == 'stripe' && ! empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) + { + require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; + + $service = 'StripeLive'; + $servicestatus = 1; + + if (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha')) + { + $service = 'StripeTest'; + $servicestatus = 0; + } + $stripe = new Stripe($db); + $stripeacc = $stripe->getStripeAccount($service); + $stripecu = null; + // for dev only + print ''.$langs->trans("PaymentIntent"); + print ''; + $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, $object, $stripecu, $stripeacc, $servicestatus); + print ''.$paymentintent->id.''; + print ''."\n"; + } + // Shipping address $shipToName=$member->getFullName($langs); $shipToStreet=$member->address; @@ -1541,6 +1655,29 @@ if ($source == 'donation') print ''; print ''."\n"; + if (! empty($conf->stripe->enabled) && ($paymentmethod == 'stripe') && empty($object->paid) && ! empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) + { + require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; + + $service = 'StripeLive'; + $servicestatus = 1; + + if (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha')) + { + $service = 'StripeTest'; + $servicestatus = 0; + } + $stripe = new Stripe($db); + $stripeacc = $stripe->getStripeAccount($service); + $stripecu = $stripe->customerStripe($don->thirdparty, $stripeacc, $servicestatus, 1); + // for dev only + print ''.$langs->trans("PaymentIntent"); + print ''; + $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, $object, $stripecu, $stripeacc, $servicestatus); + print ''.$paymentintent->id.''; + print ''."\n"; + } + // Shipping address $shipToName=$don->getFullName($langs); $shipToStreet=$don->address; @@ -1724,25 +1861,38 @@ if (preg_match('/^dopayment/', $action)) print ''; print ' - - +
+ +
'; -
+ if (! empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) + { + print '
'; + } - -
+ print ' +
+ + '; + + if (! empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) + { + print '
'; + } + + print '
-
+
'; -
- + print '
+ -
+
'."\n"; @@ -1750,8 +1900,94 @@ if (preg_match('/^dopayment/', $action)) // Code to ask the credit card. This use the default "API version". No way to force API version when using JS code. print ''; } } diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index d604dcdd3f2..1f2f39719a8 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -140,7 +140,7 @@ class Stripe extends CommonObject if (empty($object->id)) { - dol_syslog("customerStripe is called with param object not loaded"); + dol_syslog("customerStripe is called with the parameter object that is not loaded"); return null; } @@ -240,6 +240,9 @@ class Stripe extends CommonObject /** * Get the Stripe payment intent. Create it with confirm=false * + * @param double $amount Amount + * @param string $currency_code Currency code + * @param string $tag Tag * @param Societe $object Object to pay with Stripe * @param string $customer Stripe customer ref 'cus_xxxxxxxxxxxxx' via customerStripe() * @param string $key ''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect @@ -249,127 +252,133 @@ class Stripe extends CommonObject * @param boolean $confirmnow false=default, true=try to confirm immediatly after create (if conditions are ok) * @return \Stripe\PaymentIntent|null Stripe PaymentIntent or null if not found */ - public function getPaymentIntent($object, $customer, $key = null, $status = 0, $usethirdpartyemailforreceiptemail = 0, $mode = 'automatic', $confirmnow = false) + public function getPaymentIntent($amount, $currency_code, $tag, $object = null, $customer = null, $key = null, $status = 0, $usethirdpartyemailforreceiptemail = 0, $mode = 'automatic', $confirmnow = false) { global $conf, $user, $mysoc; - if (empty($object->id)) - { - dol_syslog("object not loaded"); - return null; - } - - $error = 0; - if (empty($status)) $service = 'StripeTest'; else $service = 'StripeLive'; + $arrayzerounitcurrency=array('BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF'); + if (! in_array($currency_code, $arrayzerounitcurrency)) $stripeamount = $amount * 100; + else $stripeamount = $amount; + + $fee = round(($$stripeamount * ($conf->global->STRIPE_APPLICATION_FEE_PERCENT / 100) + $conf->global->STRIPE_APPLICATION_FEE) * 100); + if ($fee >= ($conf->global->STRIPE_APPLICATION_FEE_MAXIMAL * 100) && $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL>$conf->global->STRIPE_APPLICATION_FEE_MINIMAL) { + $fee = round($conf->global->STRIPE_APPLICATION_FEE_MAXIMAL * 100); + } elseif ($fee < ($conf->global->STRIPE_APPLICATION_FEE_MINIMAL * 100)) { + $fee = round($conf->global->STRIPE_APPLICATION_FEE_MINIMAL * 100); + } + $paymentintent = null; - $sql = "SELECT pi.ext_payment_id, pi.entity, pi.fk_facture, pi.sourcetype, pi.ext_payment_site"; - $sql.= " FROM " . MAIN_DB_PREFIX . "prelevement_facture_demande as pi"; - $sql.= " WHERE pi.fk_facture = " . $object->id; - $sql.= " AND pi.sourcetype = '" . $object->element . "'"; - $sql.= " AND pi.entity IN (".getEntity('societe').")"; - $sql.= " AND pi.ext_payment_site = '" . $service . "'"; - - dol_syslog(get_class($this) . "::getPaymentIntent search stripe customer id for thirdparty id=".$object->id, LOG_DEBUG); - $resql = $this->db->query($sql); - if ($resql) { - $num = $this->db->num_rows($resql); - if ($num) - { - $obj = $this->db->fetch_object($resql); - $intent = $obj->ext_payment_id; - - dol_syslog(get_class($this) . "::getPaymentIntent found existing payment intent record"); - - // Force to use the correct API key - global $stripearrayofkeysbyenv; - \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']); - - try { - if (empty($key)) { // If the Stripe connect account not set, we use common API usage - $paymentintent = \Stripe\PaymentIntent::retrieve($intent); - } else { - $paymentintent = \Stripe\PaymentIntent::retrieve($intent, array("stripe_account" => $key)); - } - } - catch(Exception $e) - { - $this->error = $e->getMessage(); - } - } - else //if ($createifnotlinkedtostripe) - { - $arrayzerounitcurrency=array('BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF'); - if (! in_array($object->multicurrency_code, $arrayzerounitcurrency)) $stripeamount=$object->multicurrency_total_ttc * 100; - else $stripeamount = $object->multicurrency_total_ttc; - - $fee = round(($object->total_ttc * ($conf->global->STRIPE_APPLICATION_FEE_PERCENT / 100) + $conf->global->STRIPE_APPLICATION_FEE) * 100); - if ($fee >= ($conf->global->STRIPE_APPLICATION_FEE_MAXIMAL * 100) && $conf->global->STRIPE_APPLICATION_FEE_MAXIMAL>$conf->global->STRIPE_APPLICATION_FEE_MINIMAL) { - $fee = round($conf->global->STRIPE_APPLICATION_FEE_MAXIMAL * 100); - } elseif ($fee < ($conf->global->STRIPE_APPLICATION_FEE_MINIMAL * 100)) { - $fee = round($conf->global->STRIPE_APPLICATION_FEE_MINIMAL * 100); - } - - $ipaddress=getUserRemoteIP(); - // Not enough space for a ref so we store id. Also with multicompany we can have same ref for 2 different - // object and we need a unique (this is used later as idempotency_key) - $description=$object->element.$object->id; - - $dataforintent = array( - "confirm" => $confirmnow, // Do not confirm immediatly during creation of intent - "confirmation_method" => $mode, - "amount" => $stripeamount, - "currency" => $object->multicurrency_code, - "customer" => $customer, - "allowed_source_types" => ["card"], - "statement_descriptor" => dol_trunc($description, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description) - "metadata" => array('dol_type'=>$object->element, 'dol_id'=>$object->id, 'dol_version'=>DOL_VERSION, 'dol_entity'=>$conf->entity, 'ipaddress'=>$ipaddress) - ); - // save_payment_method = true, - // payment_method_types = - // payment_method = - - if ($conf->entity!=$conf->global->STRIPECONNECT_PRINCIPAL && $fee>0) - { - $dataforintent["application_fee"] = $fee; - } - if ($usethirdpartyemailforreceiptemail && $object->thirdparty->email) - { - $dataforintent["receipt_email"] = $object->thirdparty->email; - } - - try { - // Force to use the correct API key - global $stripearrayofkeysbyenv; - \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']); - - if (empty($key)) { // If the Stripe connect account not set, we use common API usage - $paymentintent = \Stripe\PaymentIntent::create($dataforintent, array("idempotency_key" => "$description")); - } else { - $paymentintent = \Stripe\PaymentIntent::create($dataforintent, array("idempotency_key" => "$description","stripe_account" => $key)); - } - $now=dol_now(); - $sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement_facture_demande (fk_soc, date_demande, fk_user_demande, ext_payment_id, fk_facture, sourcetype, entity, ext_payment_site)"; - $sql .= " VALUES ('".$object->socid."','".$this->db->idate($now)."', '0', '".$this->db->escape($paymentintent->id)."', ".$object->id.", '".$this->db->escape($object->element)."', " . $conf->entity . ", '" . $service . "')"; - $resql = $this->db->query($sql); - if (! $resql) - { - $this->error = $this->db->lasterror(); - dol_syslog(get_class($this) . "::PaymentIntent failed to insert paymentintent with id=".$paymentintent->id." into database."); - } - } - catch(Exception $e) - { - $this->error = $e->getMessage(); - } - } - } - else + if (is_object($object)) { - dol_print_error($this->db); + $sql = "SELECT pi.ext_payment_id, pi.entity, pi.fk_facture, pi.sourcetype, pi.ext_payment_site"; + $sql.= " FROM " . MAIN_DB_PREFIX . "prelevement_facture_demande as pi"; + $sql.= " WHERE pi.fk_facture = " . $object->id; + $sql.= " AND pi.sourcetype = '" . $object->element . "'"; + $sql.= " AND pi.entity IN (".getEntity('societe').")"; + $sql.= " AND pi.ext_payment_site = '" . $service . "'"; + + dol_syslog(get_class($this) . "::getPaymentIntent search stripe payment intent for object id = ".$object->id, LOG_DEBUG); + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + if ($num) + { + $obj = $this->db->fetch_object($resql); + $intent = $obj->ext_payment_id; + + dol_syslog(get_class($this) . "::getPaymentIntent found existing payment intent record"); + + // Force to use the correct API key + global $stripearrayofkeysbyenv; + \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']); + + try { + if (empty($key)) { // If the Stripe connect account not set, we use common API usage + $paymentintent = \Stripe\PaymentIntent::retrieve($intent); + } else { + $paymentintent = \Stripe\PaymentIntent::retrieve($intent, array("stripe_account" => $key)); + } + } + catch(Exception $e) + { + $this->error = $e->getMessage(); + } + } + } + } + + if (empty($paymentintent)) + { + $ipaddress=getUserRemoteIP(); + // Not enough space for a ref so we store id. Also with multicompany we can have same ref for 2 different + // object and we need a unique (this is used later as idempotency_key) + $description=$tag; + $metadata = array('dol_version'=>DOL_VERSION, 'dol_entity'=>$conf->entity, 'ipaddress'=>$ipaddress); + if (is_object($object)) + { + $metadata['dol_type'] = $object->element; + $metadata['dol_id'] = $object->id; + } + + $dataforintent = array( + "confirm" => $confirmnow, // Do not confirm immediatly during creation of intent + "confirmation_method" => $mode, + "amount" => $stripeamount, + "currency" => $currency_code, + "payment_method_types" => ["card"], + "statement_descriptor" => dol_trunc($description, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description) + "metadata" => $metadata + ); + if (! is_null($customer)) $dataforintent["customer"]=$customer; + // save_payment_method = true, + // payment_method = + + if ($conf->entity!=$conf->global->STRIPECONNECT_PRINCIPAL && $fee>0) + { + $dataforintent["application_fee"] = $fee; + } + if ($usethirdpartyemailforreceiptemail && is_object($object) && $object->thirdparty->email) + { + $dataforintent["receipt_email"] = $object->thirdparty->email; + } + + try { + // Force to use the correct API key + global $stripearrayofkeysbyenv; + \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']); + + if (empty($key)) { // If the Stripe connect account not set, we use common API usage + $paymentintent = \Stripe\PaymentIntent::create($dataforintent, array("idempotency_key" => "$description")); + } else { + $paymentintent = \Stripe\PaymentIntent::create($dataforintent, array("idempotency_key" => "$description", "stripe_account" => $key)); + } + + // Store the payment intent + if (is_object($object)) + { + $now=dol_now(); + $sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement_facture_demande (fk_soc, date_demande, fk_user_demande, ext_payment_id, fk_facture, sourcetype, entity, ext_payment_site)"; + $sql .= " VALUES ('".$object->socid."','".$this->db->idate($now)."', '0', '".$this->db->escape($paymentintent->id)."', ".$object->id.", '".$this->db->escape($object->element)."', " . $conf->entity . ", '" . $service . "')"; + $resql = $this->db->query($sql); + if (! $resql) + { + $this->error = $this->db->lasterror(); + dol_syslog(get_class($this) . "::PaymentIntent failed to insert paymentintent with id=".$paymentintent->id." into database."); + } + } + else + { + $_SESSION["stripe_payment_intent"] = $paymentintent; + } + } + catch(Exception $e) + { + $this->error = $e->getMessage(); + } } return $paymentintent; From eab49d4300983e97e8f658ff2e017485064351f7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 3 May 2019 02:22:27 +0200 Subject: [PATCH 129/132] NEW Update Stripe library to 6.34.3 --- htdocs/core/lib/payments.lib.php | 2 +- htdocs/includes/stripe/.coveralls.yml | 4 - htdocs/includes/stripe/.travis.yml | 40 -- htdocs/includes/stripe/CHANGELOG.md | 216 ++++++ htdocs/includes/stripe/LICENSE | 2 +- htdocs/includes/stripe/README.md | 17 +- htdocs/includes/stripe/VERSION | 2 +- htdocs/includes/stripe/build.php | 2 +- htdocs/includes/stripe/composer.json | 5 +- htdocs/includes/stripe/init.php | 36 + htdocs/includes/stripe/lib/Account.php | 165 ++++- htdocs/includes/stripe/lib/AccountLink.php | 21 + htdocs/includes/stripe/lib/AlipayAccount.php | 3 + .../includes/stripe/lib/ApiOperations/All.php | 2 +- .../lib/ApiOperations/NestedResource.php | 3 + .../stripe/lib/ApiOperations/Request.php | 3 +- .../stripe/lib/ApiOperations/Retrieve.php | 2 +- htdocs/includes/stripe/lib/ApiRequestor.php | 187 ++++- htdocs/includes/stripe/lib/ApiResource.php | 28 +- htdocs/includes/stripe/lib/ApplePayDomain.php | 3 + htdocs/includes/stripe/lib/ApplicationFee.php | 24 +- .../stripe/lib/ApplicationFeeRefund.php | 3 + htdocs/includes/stripe/lib/Balance.php | 4 + .../stripe/lib/BalanceTransaction.php | 3 + htdocs/includes/stripe/lib/BankAccount.php | 3 + .../includes/stripe/lib/BitcoinReceiver.php | 3 + .../stripe/lib/BitcoinTransaction.php | 1 + htdocs/includes/stripe/lib/Card.php | 37 +- htdocs/includes/stripe/lib/Charge.php | 62 ++ .../includes/stripe/lib/Checkout/Session.php | 30 + htdocs/includes/stripe/lib/Collection.php | 14 +- htdocs/includes/stripe/lib/CountrySpec.php | 15 +- htdocs/includes/stripe/lib/Coupon.php | 6 +- htdocs/includes/stripe/lib/CreditNote.php | 73 ++ htdocs/includes/stripe/lib/Customer.php | 90 ++- htdocs/includes/stripe/lib/Discount.php | 21 + htdocs/includes/stripe/lib/Dispute.php | 6 +- htdocs/includes/stripe/lib/EphemeralKey.php | 14 +- .../stripe/lib/Error/OAuth/OAuthBase.php | 4 +- htdocs/includes/stripe/lib/Event.php | 227 ++++--- htdocs/includes/stripe/lib/ExchangeRate.php | 14 +- htdocs/includes/stripe/lib/File.php | 62 ++ htdocs/includes/stripe/lib/FileLink.php | 29 + htdocs/includes/stripe/lib/FileUpload.php | 30 +- .../stripe/lib/HttpClient/ClientInterface.php | 7 +- .../stripe/lib/HttpClient/CurlClient.php | 150 +++- htdocs/includes/stripe/lib/Invoice.php | 131 +++- htdocs/includes/stripe/lib/InvoiceItem.php | 5 + .../includes/stripe/lib/InvoiceLineItem.php | 32 + .../includes/stripe/lib/IssuerFraudRecord.php | 25 + .../stripe/lib/Issuing/Authorization.php | 68 ++ htdocs/includes/stripe/lib/Issuing/Card.php | 51 ++ .../stripe/lib/Issuing/CardDetails.php | 21 + .../stripe/lib/Issuing/Cardholder.php | 30 + .../includes/stripe/lib/Issuing/Dispute.php | 30 + .../stripe/lib/Issuing/Transaction.php | 33 + htdocs/includes/stripe/lib/LoginLink.php | 5 + htdocs/includes/stripe/lib/OAuth.php | 2 +- htdocs/includes/stripe/lib/Order.php | 5 +- htdocs/includes/stripe/lib/OrderItem.php | 22 + htdocs/includes/stripe/lib/OrderReturn.php | 24 +- htdocs/includes/stripe/lib/PaymentIntent.php | 94 +++ htdocs/includes/stripe/lib/PaymentMethod.php | 60 ++ htdocs/includes/stripe/lib/Payout.php | 52 +- htdocs/includes/stripe/lib/Person.php | 108 +++ htdocs/includes/stripe/lib/Plan.php | 10 + htdocs/includes/stripe/lib/Product.php | 14 +- .../includes/stripe/lib/Radar/ValueList.php | 32 + .../stripe/lib/Radar/ValueListItem.php | 26 + htdocs/includes/stripe/lib/Recipient.php | 18 + .../includes/stripe/lib/RecipientTransfer.php | 1 + htdocs/includes/stripe/lib/Refund.php | 37 +- .../stripe/lib/Reporting/ReportRun.php | 28 + .../stripe/lib/Reporting/ReportType.php | 24 + .../includes/stripe/lib/RequestTelemetry.php | 27 + htdocs/includes/stripe/lib/Review.php | 57 ++ htdocs/includes/stripe/lib/SKU.php | 3 + .../stripe/lib/Sigma/ScheduledQueryRun.php | 33 + .../stripe/lib/SingletonApiResource.php | 4 +- htdocs/includes/stripe/lib/Source.php | 46 +- .../includes/stripe/lib/SourceTransaction.php | 10 + htdocs/includes/stripe/lib/Stripe.php | 32 +- htdocs/includes/stripe/lib/StripeObject.php | 90 ++- htdocs/includes/stripe/lib/Subscription.php | 37 +- .../includes/stripe/lib/SubscriptionItem.php | 19 +- .../stripe/lib/SubscriptionSchedule.php | 111 +++ .../lib/SubscriptionScheduleRevision.php | 77 +++ htdocs/includes/stripe/lib/TaxId.php | 80 +++ htdocs/includes/stripe/lib/TaxRate.php | 31 + .../stripe/lib/Terminal/ConnectionToken.php | 17 + .../includes/stripe/lib/Terminal/Location.php | 25 + .../includes/stripe/lib/Terminal/Reader.php | 30 + htdocs/includes/stripe/lib/ThreeDSecure.php | 3 + htdocs/includes/stripe/lib/Token.php | 16 +- htdocs/includes/stripe/lib/Topup.php | 28 + htdocs/includes/stripe/lib/Transfer.php | 23 +- .../includes/stripe/lib/TransferReversal.php | 5 + htdocs/includes/stripe/lib/UsageRecord.php | 44 ++ .../stripe/lib/UsageRecordSummary.php | 22 + .../stripe/lib/Util/CaseInsensitiveArray.php | 62 ++ .../stripe/lib/Util/RequestOptions.php | 17 +- htdocs/includes/stripe/lib/Util/Util.php | 253 +++++-- .../includes/stripe/lib/WebhookEndpoint.php | 29 + .../includes/stripe/phpunit.no_autoload.xml | 15 - htdocs/includes/stripe/phpunit.xml | 15 - .../stripe/tests/Stripe/AccountTest.php | 365 ---------- .../stripe/tests/Stripe/AlipayAccountTest.php | 76 --- .../stripe/tests/Stripe/ApiRequestorTest.php | 572 ---------------- .../tests/Stripe/ApplePayDomainTest.php | 52 -- .../tests/Stripe/ApplicationFeeRefundTest.php | 21 - .../tests/Stripe/ApplicationFeeTest.php | 83 --- .../stripe/tests/Stripe/BalanceTest.php | 16 - .../tests/Stripe/BalanceTransactionTest.php | 29 - .../stripe/tests/Stripe/BankAccountTest.php | 99 --- .../tests/Stripe/BitcoinReceiverTest.php | 62 -- .../includes/stripe/tests/Stripe/CardTest.php | 94 --- .../stripe/tests/Stripe/ChargeTest.php | 140 ---- .../stripe/tests/Stripe/CollectionTest.php | 147 ---- .../stripe/tests/Stripe/CountrySpecTest.php | 29 - .../stripe/tests/Stripe/CouponTest.php | 79 --- .../stripe/tests/Stripe/CustomerTest.php | 269 -------- .../stripe/tests/Stripe/DisputeTest.php | 65 -- .../stripe/tests/Stripe/EphemeralKeyTest.php | 43 -- .../stripe/tests/Stripe/Error/BaseTest.php | 36 - .../Error/SignatureVerificationTest.php | 12 - .../stripe/tests/Stripe/EventTest.php | 29 - .../stripe/tests/Stripe/ExchangeRateTest.php | 54 -- .../stripe/tests/Stripe/FileUploadTest.php | 104 --- .../Stripe/HttpClient/CurlClientTest.php | 228 ------- .../stripe/tests/Stripe/InvoiceItemTest.php | 78 --- .../stripe/tests/Stripe/InvoiceTest.php | 87 --- .../stripe/tests/Stripe/OAuthTest.php | 97 --- .../stripe/tests/Stripe/OrderReturnTest.php | 29 - .../stripe/tests/Stripe/OrderTest.php | 87 --- .../stripe/tests/Stripe/PayoutTest.php | 77 --- .../includes/stripe/tests/Stripe/PlanTest.php | 80 --- .../stripe/tests/Stripe/ProductTest.php | 77 --- .../stripe/tests/Stripe/RecipientTest.php | 90 --- .../stripe/tests/Stripe/RefundTest.php | 65 -- .../includes/stripe/tests/Stripe/SKUTest.php | 82 --- .../stripe/tests/Stripe/SourceTest.php | 134 ---- .../stripe/tests/Stripe/StripeObjectTest.php | 453 ------------ .../stripe/tests/Stripe/StripeTest.php | 30 - .../tests/Stripe/SubscriptionItemTest.php | 77 --- .../stripe/tests/Stripe/SubscriptionTest.php | 115 ---- .../stripe/tests/Stripe/ThreeDSecureTest.php | 32 - .../stripe/tests/Stripe/TokenTest.php | 28 - .../stripe/tests/Stripe/TopupTest.php | 69 -- .../tests/Stripe/TransferReversalTest.php | 21 - .../stripe/tests/Stripe/TransferTest.php | 140 ---- .../tests/Stripe/Util/DefaultLoggerTest.php | 28 - .../tests/Stripe/Util/RequestOptionsTest.php | 81 --- .../stripe/tests/Stripe/Util/UtilTest.php | 90 --- .../stripe/tests/Stripe/WebhookTest.php | 110 --- htdocs/includes/stripe/tests/TestCase.php | 177 ----- .../stripe/tests/bootstrap.no_autoload.php | 5 - htdocs/includes/stripe/tests/bootstrap.php | 43 -- htdocs/includes/stripe/tests/data/test.png | Bin 95 -> 0 bytes htdocs/langs/en_US/paypal.lang | 2 +- htdocs/paypal/lib/paypal.lib.php | 2 +- htdocs/public/payment/newpayment.php | 642 ++++++++++-------- htdocs/public/payment/paymentok.php | 10 +- htdocs/stripe/class/stripe.class.php | 27 +- htdocs/stripe/lib/stripe.lib.php | 4 +- htdocs/theme/eldy/global.inc.php | 21 +- htdocs/theme/md/style.css.php | 14 +- 166 files changed, 3851 insertions(+), 5981 deletions(-) delete mode 100644 htdocs/includes/stripe/.coveralls.yml delete mode 100644 htdocs/includes/stripe/.travis.yml create mode 100644 htdocs/includes/stripe/lib/AccountLink.php create mode 100644 htdocs/includes/stripe/lib/Checkout/Session.php create mode 100644 htdocs/includes/stripe/lib/CreditNote.php create mode 100644 htdocs/includes/stripe/lib/Discount.php create mode 100644 htdocs/includes/stripe/lib/File.php create mode 100644 htdocs/includes/stripe/lib/FileLink.php create mode 100644 htdocs/includes/stripe/lib/InvoiceLineItem.php create mode 100644 htdocs/includes/stripe/lib/IssuerFraudRecord.php create mode 100644 htdocs/includes/stripe/lib/Issuing/Authorization.php create mode 100644 htdocs/includes/stripe/lib/Issuing/Card.php create mode 100644 htdocs/includes/stripe/lib/Issuing/CardDetails.php create mode 100644 htdocs/includes/stripe/lib/Issuing/Cardholder.php create mode 100644 htdocs/includes/stripe/lib/Issuing/Dispute.php create mode 100644 htdocs/includes/stripe/lib/Issuing/Transaction.php create mode 100644 htdocs/includes/stripe/lib/OrderItem.php create mode 100644 htdocs/includes/stripe/lib/PaymentIntent.php create mode 100644 htdocs/includes/stripe/lib/PaymentMethod.php create mode 100644 htdocs/includes/stripe/lib/Person.php create mode 100644 htdocs/includes/stripe/lib/Radar/ValueList.php create mode 100644 htdocs/includes/stripe/lib/Radar/ValueListItem.php create mode 100644 htdocs/includes/stripe/lib/Reporting/ReportRun.php create mode 100644 htdocs/includes/stripe/lib/Reporting/ReportType.php create mode 100644 htdocs/includes/stripe/lib/RequestTelemetry.php create mode 100644 htdocs/includes/stripe/lib/Review.php create mode 100644 htdocs/includes/stripe/lib/Sigma/ScheduledQueryRun.php create mode 100644 htdocs/includes/stripe/lib/SubscriptionSchedule.php create mode 100644 htdocs/includes/stripe/lib/SubscriptionScheduleRevision.php create mode 100644 htdocs/includes/stripe/lib/TaxId.php create mode 100644 htdocs/includes/stripe/lib/TaxRate.php create mode 100644 htdocs/includes/stripe/lib/Terminal/ConnectionToken.php create mode 100644 htdocs/includes/stripe/lib/Terminal/Location.php create mode 100644 htdocs/includes/stripe/lib/Terminal/Reader.php create mode 100644 htdocs/includes/stripe/lib/UsageRecord.php create mode 100644 htdocs/includes/stripe/lib/UsageRecordSummary.php create mode 100644 htdocs/includes/stripe/lib/Util/CaseInsensitiveArray.php create mode 100644 htdocs/includes/stripe/lib/WebhookEndpoint.php delete mode 100644 htdocs/includes/stripe/phpunit.no_autoload.xml delete mode 100644 htdocs/includes/stripe/phpunit.xml delete mode 100644 htdocs/includes/stripe/tests/Stripe/AccountTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/AlipayAccountTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/ApiRequestorTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/ApplePayDomainTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/ApplicationFeeRefundTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/ApplicationFeeTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/BalanceTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/BalanceTransactionTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/BankAccountTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/BitcoinReceiverTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/CardTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/ChargeTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/CollectionTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/CountrySpecTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/CouponTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/CustomerTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/DisputeTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/EphemeralKeyTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/Error/BaseTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/Error/SignatureVerificationTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/EventTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/ExchangeRateTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/FileUploadTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/HttpClient/CurlClientTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/InvoiceItemTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/InvoiceTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/OAuthTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/OrderReturnTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/OrderTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/PayoutTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/PlanTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/ProductTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/RecipientTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/RefundTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/SKUTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/SourceTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/StripeObjectTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/StripeTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/SubscriptionItemTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/SubscriptionTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/ThreeDSecureTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/TokenTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/TopupTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/TransferReversalTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/TransferTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/Util/DefaultLoggerTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/Util/RequestOptionsTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/Util/UtilTest.php delete mode 100644 htdocs/includes/stripe/tests/Stripe/WebhookTest.php delete mode 100644 htdocs/includes/stripe/tests/TestCase.php delete mode 100644 htdocs/includes/stripe/tests/bootstrap.no_autoload.php delete mode 100644 htdocs/includes/stripe/tests/bootstrap.php delete mode 100644 htdocs/includes/stripe/tests/data/test.png diff --git a/htdocs/core/lib/payments.lib.php b/htdocs/core/lib/payments.lib.php index 5d88f3e26ea..db5740d277b 100644 --- a/htdocs/core/lib/payments.lib.php +++ b/htdocs/core/lib/payments.lib.php @@ -150,7 +150,7 @@ function showOnlinePaymentUrl($type, $ref) * @param string $localorexternal 0=Url for browser, 1=Url for external access * @return string Url string */ -function getOnlinePaymentUrl($mode, $type, $ref = '', $amount = '9.99', $freetag = 'your_free_tag', $localorexternal = 0) +function getOnlinePaymentUrl($mode, $type, $ref = '', $amount = '9.99', $freetag = 'your_tag', $localorexternal = 0) { global $conf, $dolibarr_main_url_root; diff --git a/htdocs/includes/stripe/.coveralls.yml b/htdocs/includes/stripe/.coveralls.yml deleted file mode 100644 index a343c9a7466..00000000000 --- a/htdocs/includes/stripe/.coveralls.yml +++ /dev/null @@ -1,4 +0,0 @@ -service_name: travis-ci -src_dir: . -coverage_clover: clover.xml -json_path: coveralls-upload.json diff --git a/htdocs/includes/stripe/.travis.yml b/htdocs/includes/stripe/.travis.yml deleted file mode 100644 index d575ed51a7d..00000000000 --- a/htdocs/includes/stripe/.travis.yml +++ /dev/null @@ -1,40 +0,0 @@ -sudo: false - -language: php - -php: - - 5.4 - - 5.5 - - 5.6 - - 7.0 - - 7.1 - - 7.2 - - hhvm - -env: - global: - - STRIPE_MOCK_VERSION=0.8.0 - matrix: - - AUTOLOAD=1 - - AUTOLOAD=0 - -cache: - directories: - - $HOME/.composer/cache/files - - stripe-mock - -before_install: - # Unpack and start stripe-mock so that the test suite can talk to it - - | - if [ ! -d "stripe-mock/stripe-mock_${STRIPE_MOCK_VERSION}" ]; then - mkdir -p stripe-mock/stripe-mock_${STRIPE_MOCK_VERSION}/ - curl -L "https://github.com/stripe/stripe-mock/releases/download/v${STRIPE_MOCK_VERSION}/stripe-mock_${STRIPE_MOCK_VERSION}_linux_amd64.tar.gz" -o "stripe-mock/stripe-mock_${STRIPE_MOCK_VERSION}_linux_amd64.tar.gz" - tar -zxf "stripe-mock/stripe-mock_${STRIPE_MOCK_VERSION}_linux_amd64.tar.gz" -C "stripe-mock/stripe-mock_${STRIPE_MOCK_VERSION}/" - fi - - | - stripe-mock/stripe-mock_${STRIPE_MOCK_VERSION}/stripe-mock > /dev/null & - STRIPE_MOCK_PID=$! - -script: ./build.php ${AUTOLOAD} - -after_script: ./vendor/bin/coveralls -v diff --git a/htdocs/includes/stripe/CHANGELOG.md b/htdocs/includes/stripe/CHANGELOG.md index 3f0fdfce153..727ac3d1b43 100644 --- a/htdocs/includes/stripe/CHANGELOG.md +++ b/htdocs/includes/stripe/CHANGELOG.md @@ -1,5 +1,221 @@ # Changelog +## 6.34.3 - 2019-05-01 +* [#644](https://github.com/stripe/stripe-php/pull/644) Update return type to `static` to improve static analysis +* [#645](https://github.com/stripe/stripe-php/pull/645) Fix constant for `payment_intent.payment_failed` + +## 6.34.2 - 2019-04-26 +* [#642](https://github.com/stripe/stripe-php/pull/642) Fix an issue where existing idempotency keys would be overwritten when using automatic retries + +## 6.34.1 - 2019-04-25 +* [#640](https://github.com/stripe/stripe-php/pull/640) Add missing phpdocs + +## 6.34.0 - 2019-04-24 +* [#626](https://github.com/stripe/stripe-php/pull/626) Add support for the `TaxRate` resource and APIs +* [#639](https://github.com/stripe/stripe-php/pull/639) Fix multiple phpdoc issues + +## 6.33.0 - 2019-04-22 +* [#630](https://github.com/stripe/stripe-php/pull/630) Add support for the `TaxId` resource and APIs + +## 6.32.1 - 2019-04-19 +* [#636](https://github.com/stripe/stripe-php/pull/636) Correct type of `$personId` in PHPDoc + +## 6.32.0 - 2019-04-18 +* [#621](https://github.com/stripe/stripe-php/pull/621) Add support for `CreditNote` + +## 6.31.5 - 2019-04-12 +* [#628](https://github.com/stripe/stripe-php/pull/628) Add constants for `person.*` event types +* [#628](https://github.com/stripe/stripe-php/pull/628) Add missing constants for `Account` and `Person` + +## 6.31.4 - 2019-04-05 +* [#624](https://github.com/stripe/stripe-php/pull/624) Fix encoding of nested parameters in multipart requests + +## 6.31.3 - 2019-04-02 +* [#623](https://github.com/stripe/stripe-php/pull/623) Only use HTTP/2 with curl >= 7.60.0 + +## 6.31.2 - 2019-03-25 +* [#619](https://github.com/stripe/stripe-php/pull/619) Fix PHPDoc return types for list methods for nested resources + +## 6.31.1 - 2019-03-22 +* [#612](https://github.com/stripe/stripe-php/pull/612) Add a lot of constants +* [#614](https://github.com/stripe/stripe-php/pull/614) Add missing subscription status constants + +## 6.31.0 - 2019-03-18 +* [#600](https://github.com/stripe/stripe-php/pull/600) Add support for the `PaymentMethod` resource and APIs +* [#606](https://github.com/stripe/stripe-php/pull/606) Add support for retrieving a Checkout `Session` +* [#611](https://github.com/stripe/stripe-php/pull/611) Add support for deleting a Terminal `Location` and `Reader` + +## 6.30.5 - 2019-03-11 +* [#607](https://github.com/stripe/stripe-php/pull/607) Correctly handle case where a metadata key is called `metadata` + +## 6.30.4 - 2019-02-27 +* [#602](https://github.com/stripe/stripe-php/pull/602) Add `subscription_schedule` to `Subscription` for PHPDoc. + +## 6.30.3 - 2019-02-26 +* [#603](https://github.com/stripe/stripe-php/pull/603) Improve PHPDoc on the `Source` object to cover all types of Sources currently supported. + +## 6.30.2 - 2019-02-25 +* [#601](https://github.com/stripe/stripe-php/pull/601) Fix PHPDoc across multiple resources and add support for new events. + +## 6.30.1 - 2019-02-16 +* [#599](https://github.com/stripe/stripe-php/pull/599) Fix PHPDoc for `SubscriptionSchedule` and `SubscriptionScheduleRevision` + +## 6.30.0 - 2019-02-12 +* [#590](https://github.com/stripe/stripe-php/pull/590) Add support for `SubscriptionSchedule` and `SubscriptionScheduleRevision` + +## 6.29.3 - 2019-01-31 +* [#592](https://github.com/stripe/stripe-php/pull/592) Some more PHPDoc fixes + +## 6.29.2 - 2019-01-31 +* [#591](https://github.com/stripe/stripe-php/pull/591) Fix PHPDoc for nested resources + +## 6.29.1 - 2019-01-25 +* [#566](https://github.com/stripe/stripe-php/pull/566) Fix dangling message contents +* [#586](https://github.com/stripe/stripe-php/pull/586) Don't overwrite `CURLOPT_HTTP_VERSION` option + +## 6.29.0 - 2019-01-23 +* [#579](https://github.com/stripe/stripe-php/pull/579) Rename `CheckoutSession` to `Session` and move it under the `Checkout` namespace. This is a breaking change, but we've reached out to affected merchants and all new merchants would use the new approach. + +## 6.28.1 - 2019-01-21 +* [#580](https://github.com/stripe/stripe-php/pull/580) Properly serialize `individual` on `Account` objects + +## 6.28.0 - 2019-01-03 +* [#576](https://github.com/stripe/stripe-php/pull/576) Add support for iterating directly over `Collection` instances + +## 6.27.0 - 2018-12-21 +* [#571](https://github.com/stripe/stripe-php/pull/571) Add support for the `CheckoutSession` resource + +## 6.26.0 - 2018-12-11 +* [#568](https://github.com/stripe/stripe-php/pull/568) Enable persistent connections + +## 6.25.0 - 2018-12-10 +* [#567](https://github.com/stripe/stripe-php/pull/567) Add support for account links + +## 6.24.0 - 2018-11-28 +* [#562](https://github.com/stripe/stripe-php/pull/562) Add support for the Review resource +* [#564](https://github.com/stripe/stripe-php/pull/564) Add event name constants for subscription schedule aborted/expiring + +## 6.23.0 - 2018-11-27 +* [#542](https://github.com/stripe/stripe-php/pull/542) Add support for `ValueList` and `ValueListItem` for Radar + +## 6.22.1 - 2018-11-20 +* [#561](https://github.com/stripe/stripe-php/pull/561) Add cast and some docs to telemetry introduced in 6.22.0/#549 + +## 6.22.0 - 2018-11-15 +* [#549](https://github.com/stripe/stripe-php/pull/549) Add support for client telemetry + +## 6.21.1 - 2018-11-12 +* [#548](https://github.com/stripe/stripe-php/pull/548) Don't mutate `Exception` class properties from `OAuthBase` error + +## 6.21.0 - 2018-11-08 +* [#537](https://github.com/stripe/stripe-php/pull/537) Add new API endpoints for the `Invoice` resource. + +## 6.20.1 - 2018-11-07 +* [#546](https://github.com/stripe/stripe-php/pull/546) Drop files from the Composer package that aren't needed in the release + +## 6.20.0 - 2018-10-30 +* [#536](https://github.com/stripe/stripe-php/pull/536) Add support for the `Person` resource +* [#541](https://github.com/stripe/stripe-php/pull/541) Add support for the `WebhookEndpoint` resource + +## 6.19.5 - 2018-10-17 +* [#539](https://github.com/stripe/stripe-php/pull/539) Fix methods on `\Stripe\PaymentIntent` to properly pass arguments to the API. + +## 6.19.4 - 2018-10-11 +* [#534](https://github.com/stripe/stripe-php/pull/534) Fix PSR-4 autoloading for `\Stripe\FileUpload` class alias + +## 6.19.3 - 2018-10-09 +* [#530](https://github.com/stripe/stripe-php/pull/530) Add constants for `flow` (`FLOW_*`), `status` (`STATUS_*`) and `usage` (`USAGE_*`) on `\Stripe\Source` + +## 6.19.2 - 2018-10-08 +* [#531](https://github.com/stripe/stripe-php/pull/531) Store HTTP response headers in case-insensitive array + +## 6.19.1 - 2018-09-25 +* [#526](https://github.com/stripe/stripe-php/pull/526) Ignore null values in request parameters + +## 6.19.0 - 2018-09-24 +* [#523](https://github.com/stripe/stripe-php/pull/523) Add support for Stripe Terminal + +## 6.18.0 - 2018-09-24 +* [#520](https://github.com/stripe/stripe-php/pull/520) Rename `\Stripe\FileUpload` to `\Stripe\File` + +## 6.17.2 - 2018-09-18 +* [#522](https://github.com/stripe/stripe-php/pull/522) Fix warning when adding a new additional owner to an existing array + +## 6.17.1 - 2018-09-14 +* [#517](https://github.com/stripe/stripe-php/pull/517) Integer-index encode all sequential arrays + +## 6.17.0 - 2018-09-05 +* [#514](https://github.com/stripe/stripe-php/pull/514) Add support for reporting resources + +## 6.16.0 - 2018-08-23 +* [#509](https://github.com/stripe/stripe-php/pull/509) Add support for usage record summaries + +## 6.15.0 - 2018-08-03 +* [#504](https://github.com/stripe/stripe-php/pull/504) Add cancel support for topups + +## 6.14.0 - 2018-08-02 +* [#505](https://github.com/stripe/stripe-php/pull/505) Add support for file links + +## 6.13.0 - 2018-07-31 +* [#502](https://github.com/stripe/stripe-php/pull/502) Add `isDeleted()` method to `\Stripe\StripeObject` + +## 6.12.0 - 2018-07-28 +* [#501](https://github.com/stripe/stripe-php/pull/501) Add support for scheduled query runs (`\Stripe\Sigma\ScheduledQueryRun`) for Sigma + +## 6.11.0 - 2018-07-26 +* [#500](https://github.com/stripe/stripe-php/pull/500) Add support for Stripe Issuing + +## 6.10.4 - 2018-07-19 +* [#498](https://github.com/stripe/stripe-php/pull/498) Internal improvements to the `\Stripe\ApiResource.classUrl()` method + +## 6.10.3 - 2018-07-16 +* [#497](https://github.com/stripe/stripe-php/pull/497) Use HTTP/2 only for HTTPS requests + +## 6.10.2 - 2018-07-11 +* [#494](https://github.com/stripe/stripe-php/pull/494) Enable HTTP/2 support + +## 6.10.1 - 2018-07-10 +* [#493](https://github.com/stripe/stripe-php/pull/493) Add PHPDoc for `auto_advance` on `\Stripe\Invoice` + +## 6.10.0 - 2018-06-28 +* [#488](https://github.com/stripe/stripe-php/pull/488) Add support for `$appPartnerId` to `Stripe::setAppInfo()` + +## 6.9.0 - 2018-06-28 +* [#487](https://github.com/stripe/stripe-php/pull/487) Add support for payment intents + +## 6.8.2 - 2018-06-24 +* [#486](https://github.com/stripe/stripe-php/pull/486) Make `Account.deauthorize()` return the `StripeObject` from the API + +## 6.8.1 - 2018-06-13 +* [#472](https://github.com/stripe/stripe-php/pull/472) Added phpDoc for `ApiRequestor` and others, especially regarding thrown errors + +## 6.8.0 - 2018-06-13 +* [#481](https://github.com/stripe/stripe-php/pull/481) Add new `\Stripe\Discount` and `\Stripe\OrderItem` classes, add more PHPDoc describing object attributes + +## 6.7.4 - 2018-05-29 +* [#480](https://github.com/stripe/stripe-php/pull/480) PHPDoc changes for API version 2018-05-21 and the addition of the new `CHARGE_EXPIRED` event type + +## 6.7.3 - 2018-05-28 +* [#479](https://github.com/stripe/stripe-php/pull/479) Fix unnecessary traits on `\Stripe\InvoiceLineItem` + +## 6.7.2 - 2018-05-28 +* [#471](https://github.com/stripe/stripe-php/pull/471) Add `OBJECT_NAME` constant to all API resource classes, add `\Stripe\InvoiceLineItem` class + +## 6.7.1 - 2018-05-13 +* [#468](https://github.com/stripe/stripe-php/pull/468) Update fields in PHP docs for accuracy + +## 6.7.0 - 2018-05-09 +* [#466](https://github.com/stripe/stripe-php/pull/466) Add support for issuer fraud records + +## 6.6.0 - 2018-04-11 +* [#460](https://github.com/stripe/stripe-php/pull/460) Add support for flexible billing primitives + +## 6.5.0 - 2018-04-05 +* [#461](https://github.com/stripe/stripe-php/pull/461) Don't zero keys on non-`metadata` subobjects + +## 6.4.2 - 2018-03-17 +* [#458](https://github.com/stripe/stripe-php/pull/458) Add PHPDoc for `account` on `\Stripe\Event` + ## 6.4.1 - 2018-03-02 * [#455](https://github.com/stripe/stripe-php/pull/455) Fix namespaces in PHPDoc * [#456](https://github.com/stripe/stripe-php/pull/456) Fix namespaces for some exceptions diff --git a/htdocs/includes/stripe/LICENSE b/htdocs/includes/stripe/LICENSE index a21757e4fcd..847c705ad35 100644 --- a/htdocs/includes/stripe/LICENSE +++ b/htdocs/includes/stripe/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2010-2015 Stripe +Copyright (c) 2010-2019 Stripe, Inc. (https://stripe.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/htdocs/includes/stripe/README.md b/htdocs/includes/stripe/README.md index fa492c45cc4..8dca764d7d1 100644 --- a/htdocs/includes/stripe/README.md +++ b/htdocs/includes/stripe/README.md @@ -62,7 +62,7 @@ Please see https://stripe.com/docs/api for up-to-date documentation. ### PHP 5.3 -If you are using PHP 5.3, you can download v5.8.0 ([zip](https://github.com/stripe/stripe-php/archive/v5.8.0.zip), [tar.gz](https://github.com/stripe/stripe-php/archive/v5.8.0.tar.gz)) from our [releases page](https://github.com/stripe/stripe-php/releases). This version will continue to work with new versions of the Stripe API for all common uses. +If you are using PHP 5.3, you can download v5.9.2 ([zip](https://github.com/stripe/stripe-php/archive/v5.9.2.zip), [tar.gz](https://github.com/stripe/stripe-php/archive/v5.9.2.tar.gz)) from our [releases page](https://github.com/stripe/stripe-php/releases). This version will continue to work with new versions of the Stripe API for all common uses. ### PHP 5.2 @@ -181,9 +181,15 @@ retries are safe. ## Development +Get [Composer][composer]. For example, on Mac OS: + +```bash +brew install composer +``` + Install dependencies: -``` bash +```bash composer install ``` @@ -191,8 +197,10 @@ The test suite depends on [stripe-mock], so make sure to fetch and run it from a background terminal ([stripe-mock's README][stripe-mock] also contains instructions for installing via Homebrew and other methods): - go get -u github.com/stripe/stripe-mock - stripe-mock +```bash +go get -u github.com/stripe/stripe-mock +stripe-mock +``` Install dependencies as mentioned above (which will resolve [PHPUnit](http://packagist.org/packages/phpunit/phpunit)), then you can run the test suite: @@ -226,6 +234,7 @@ The method should be called once, before any request is sent to the API. The sec See the "SSL / TLS compatibility issues" paragraph above for full context. If you want to ensure that your plugin can be used on all systems, you should add a configuration option to let your users choose between different values for `CURLOPT_SSLVERSION`: none (default), `CURL_SSLVERSION_TLSv1` and `CURL_SSLVERSION_TLSv1_2`. +[composer]: https://getcomposer.org/ [connect]: https://stripe.com/connect [curl]: http://curl.haxx.se/docs/caextract.html [psr3]: http://www.php-fig.org/psr/psr-3/ diff --git a/htdocs/includes/stripe/VERSION b/htdocs/includes/stripe/VERSION index 4c77920fd2c..a547a9b46f8 100644 --- a/htdocs/includes/stripe/VERSION +++ b/htdocs/includes/stripe/VERSION @@ -1 +1 @@ -6.4.1 +6.34.3 diff --git a/htdocs/includes/stripe/build.php b/htdocs/includes/stripe/build.php index cd053e2baea..6ce0ca38d11 100644 --- a/htdocs/includes/stripe/build.php +++ b/htdocs/includes/stripe/build.php @@ -13,7 +13,7 @@ if (!$autoload) { file_put_contents('composer.json', json_encode($composer, JSON_PRETTY_PRINT)); } -passthru('composer install', $returnStatus); +passthru('composer update', $returnStatus); if ($returnStatus !== 0) { exit(1); } diff --git a/htdocs/includes/stripe/composer.json b/htdocs/includes/stripe/composer.json index 67473fca421..eb92b76fb31 100644 --- a/htdocs/includes/stripe/composer.json +++ b/htdocs/includes/stripe/composer.json @@ -22,8 +22,9 @@ }, "require-dev": { "phpunit/phpunit": "~4.0", - "satooshi/php-coveralls": "~0.6.1", - "squizlabs/php_codesniffer": "~2.0" + "php-coveralls/php-coveralls": "1.*", + "squizlabs/php_codesniffer": "~2.0", + "symfony/process": "~2.8" }, "autoload": { "psr-4": { "Stripe\\" : "lib/" } diff --git a/htdocs/includes/stripe/init.php b/htdocs/includes/stripe/init.php index 79cf657a7eb..5ccf3327c0b 100644 --- a/htdocs/includes/stripe/init.php +++ b/htdocs/includes/stripe/init.php @@ -5,6 +5,7 @@ require(dirname(__FILE__) . '/lib/Stripe.php'); // Utilities require(dirname(__FILE__) . '/lib/Util/AutoPagingIterator.php'); +require(dirname(__FILE__) . '/lib/Util/CaseInsensitiveArray.php'); require(dirname(__FILE__) . '/lib/Util/LoggerInterface.php'); require(dirname(__FILE__) . '/lib/Util/DefaultLogger.php'); require(dirname(__FILE__) . '/lib/Util/RandomGenerator.php'); @@ -48,6 +49,7 @@ require(dirname(__FILE__) . '/lib/ApiOperations/Update.php'); // Plumbing require(dirname(__FILE__) . '/lib/ApiResponse.php'); +require(dirname(__FILE__) . '/lib/RequestTelemetry.php'); require(dirname(__FILE__) . '/lib/StripeObject.php'); require(dirname(__FILE__) . '/lib/ApiRequestor.php'); require(dirname(__FILE__) . '/lib/ApiResource.php'); @@ -55,6 +57,7 @@ require(dirname(__FILE__) . '/lib/SingletonApiResource.php'); // Stripe API Resources require(dirname(__FILE__) . '/lib/Account.php'); +require(dirname(__FILE__) . '/lib/AccountLink.php'); require(dirname(__FILE__) . '/lib/AlipayAccount.php'); require(dirname(__FILE__) . '/lib/ApplePayDomain.php'); require(dirname(__FILE__) . '/lib/ApplicationFee.php'); @@ -66,40 +69,73 @@ require(dirname(__FILE__) . '/lib/BitcoinReceiver.php'); require(dirname(__FILE__) . '/lib/BitcoinTransaction.php'); require(dirname(__FILE__) . '/lib/Card.php'); require(dirname(__FILE__) . '/lib/Charge.php'); +require(dirname(__FILE__) . '/lib/Checkout/Session.php'); require(dirname(__FILE__) . '/lib/Collection.php'); require(dirname(__FILE__) . '/lib/CountrySpec.php'); require(dirname(__FILE__) . '/lib/Coupon.php'); +require(dirname(__FILE__) . '/lib/CreditNote.php'); require(dirname(__FILE__) . '/lib/Customer.php'); +require(dirname(__FILE__) . '/lib/Discount.php'); require(dirname(__FILE__) . '/lib/Dispute.php'); require(dirname(__FILE__) . '/lib/EphemeralKey.php'); require(dirname(__FILE__) . '/lib/Event.php'); require(dirname(__FILE__) . '/lib/ExchangeRate.php'); +require(dirname(__FILE__) . '/lib/File.php'); +require(dirname(__FILE__) . '/lib/FileLink.php'); require(dirname(__FILE__) . '/lib/FileUpload.php'); require(dirname(__FILE__) . '/lib/Invoice.php'); require(dirname(__FILE__) . '/lib/InvoiceItem.php'); +require(dirname(__FILE__) . '/lib/InvoiceLineItem.php'); +require(dirname(__FILE__) . '/lib/IssuerFraudRecord.php'); +require(dirname(__FILE__) . '/lib/Issuing/Authorization.php'); +require(dirname(__FILE__) . '/lib/Issuing/Card.php'); +require(dirname(__FILE__) . '/lib/Issuing/CardDetails.php'); +require(dirname(__FILE__) . '/lib/Issuing/Cardholder.php'); +require(dirname(__FILE__) . '/lib/Issuing/Dispute.php'); +require(dirname(__FILE__) . '/lib/Issuing/Transaction.php'); require(dirname(__FILE__) . '/lib/LoginLink.php'); require(dirname(__FILE__) . '/lib/Order.php'); +require(dirname(__FILE__) . '/lib/OrderItem.php'); require(dirname(__FILE__) . '/lib/OrderReturn.php'); +require(dirname(__FILE__) . '/lib/PaymentIntent.php'); +require(dirname(__FILE__) . '/lib/PaymentMethod.php'); require(dirname(__FILE__) . '/lib/Payout.php'); +require(dirname(__FILE__) . '/lib/Person.php'); require(dirname(__FILE__) . '/lib/Plan.php'); require(dirname(__FILE__) . '/lib/Product.php'); +require(dirname(__FILE__) . '/lib/Radar/ValueList.php'); +require(dirname(__FILE__) . '/lib/Radar/ValueListItem.php'); require(dirname(__FILE__) . '/lib/Recipient.php'); require(dirname(__FILE__) . '/lib/RecipientTransfer.php'); require(dirname(__FILE__) . '/lib/Refund.php'); +require(dirname(__FILE__) . '/lib/Reporting/ReportRun.php'); +require(dirname(__FILE__) . '/lib/Reporting/ReportType.php'); +require(dirname(__FILE__) . '/lib/Review.php'); require(dirname(__FILE__) . '/lib/SKU.php'); +require(dirname(__FILE__) . '/lib/Sigma/ScheduledQueryRun.php'); require(dirname(__FILE__) . '/lib/Source.php'); require(dirname(__FILE__) . '/lib/SourceTransaction.php'); require(dirname(__FILE__) . '/lib/Subscription.php'); require(dirname(__FILE__) . '/lib/SubscriptionItem.php'); +require(dirname(__FILE__) . '/lib/SubscriptionSchedule.php'); +require(dirname(__FILE__) . '/lib/SubscriptionScheduleRevision.php'); +require(dirname(__FILE__) . '/lib/TaxId.php'); +require(dirname(__FILE__) . '/lib/TaxRate.php'); +require(dirname(__FILE__) . '/lib/Terminal/ConnectionToken.php'); +require(dirname(__FILE__) . '/lib/Terminal/Location.php'); +require(dirname(__FILE__) . '/lib/Terminal/Reader.php'); require(dirname(__FILE__) . '/lib/ThreeDSecure.php'); require(dirname(__FILE__) . '/lib/Token.php'); require(dirname(__FILE__) . '/lib/Topup.php'); require(dirname(__FILE__) . '/lib/Transfer.php'); require(dirname(__FILE__) . '/lib/TransferReversal.php'); +require(dirname(__FILE__) . '/lib/UsageRecord.php'); +require(dirname(__FILE__) . '/lib/UsageRecordSummary.php'); // OAuth require(dirname(__FILE__) . '/lib/OAuth.php'); // Webhooks require(dirname(__FILE__) . '/lib/Webhook.php'); +require(dirname(__FILE__) . '/lib/WebhookEndpoint.php'); require(dirname(__FILE__) . '/lib/WebhookSignature.php'); diff --git a/htdocs/includes/stripe/lib/Account.php b/htdocs/includes/stripe/lib/Account.php index d77d60dedbc..1c10fa2f3a1 100644 --- a/htdocs/includes/stripe/lib/Account.php +++ b/htdocs/includes/stripe/lib/Account.php @@ -7,37 +7,32 @@ namespace Stripe; * * @property string $id * @property string $object - * @property string $business_logo - * @property string $business_name - * @property string $business_primary_color - * @property string $business_url + * @property mixed $business_profile + * @property string $business_type + * @property mixed $capabilities * @property bool $charges_enabled + * @property mixed $company * @property string $country * @property int $created - * @property bool $debit_negative_balances - * @property mixed $decline_charge_on * @property string $default_currency * @property bool $details_submitted - * @property string $display_name * @property string $email - * @property mixed $external_accounts - * @property mixed $legal_entity + * @property Collection $external_accounts + * @property mixed $individual * @property StripeObject $metadata - * @property mixed $payout_schedule - * @property string $payout_statement_descriptor * @property bool $payouts_enabled - * @property string $product_description - * @property string $statement_descriptor - * @property string $support_email - * @property string $support_phone - * @property string $timezone + * @property mixed $requirements + * @property mixed $settings * @property mixed $tos_acceptance - * @property mixed $verification + * @property string $type * * @package Stripe */ class Account extends ApiResource { + + const OBJECT_NAME = "account"; + use ApiOperations\All; use ApiOperations\Create; use ApiOperations\Delete; @@ -47,6 +42,37 @@ class Account extends ApiResource } use ApiOperations\Update; + /** + * Possible string representations of an account's business type. + * @link https://stripe.com/docs/api/accounts/object#account_object-business_type + */ + const BUSINESS_TYPE_COMPANY = 'company'; + const BUSINESS_TYPE_INDIVIDUAL = 'individual'; + + /** + * Possible string representations of an account's capabilities. + * @link https://stripe.com/docs/api/accounts/object#account_object-capabilities + */ + const CAPABILITY_CARD_PAYMENTS = 'card_payments'; + const CAPABILITY_LEGACY_PAYMENTS = 'legacy_payments'; + const CAPABILITY_PLATFORM_PAYMENTS = 'platform_payments'; + + /** + * Possible string representations of an account's capability status. + * @link https://stripe.com/docs/api/accounts/object#account_object-capabilities + */ + const CAPABILITY_STATUS_ACTIVE = 'active'; + const CAPABILITY_STATUS_INACTIVE = 'inactive'; + const CAPABILITY_STATUS_PENDING = 'pending'; + + /** + * Possible string representations of an account's type. + * @link https://stripe.com/docs/api/accounts/object#account_object-type + */ + const TYPE_CUSTOM = 'custom'; + const TYPE_EXPRESS = 'express'; + const TYPE_STANDARD = 'standard'; + public static function getSavedNestedResources() { static $savedNestedResources = null; @@ -61,6 +87,7 @@ class Account extends ApiResource const PATH_EXTERNAL_ACCOUNTS = '/external_accounts'; const PATH_LOGIN_LINKS = '/login_links'; + const PATH_PERSONS = '/persons'; public function instanceUrl() { @@ -101,6 +128,21 @@ class Account extends ApiResource return $this; } + /** + * @param array|null $params + * @param array|string|null $options + * + * @return Collection The list of persons. + */ + public function persons($params = null, $options = null) + { + $url = $this->instanceUrl() . '/persons'; + list($response, $opts) = $this->_request('get', $url, $params, $options); + $obj = Util\Util::convertToStripeObject($response, $opts); + $obj->setLastResponse($response); + return $obj; + } + /** * @param array|null $clientId * @param array|string|null $opts @@ -113,11 +155,11 @@ class Account extends ApiResource 'client_id' => $clientId, 'stripe_user_id' => $this->id, ]; - OAuth::deauthorize($params, $opts); + return OAuth::deauthorize($params, $opts); } /** - * @param array|null $id The ID of the account on which to create the external account. + * @param string|null $id The ID of the account on which to create the external account. * @param array|null $params * @param array|string|null $opts * @@ -129,7 +171,7 @@ class Account extends ApiResource } /** - * @param array|null $id The ID of the account to which the external account belongs. + * @param string|null $id The ID of the account to which the external account belongs. * @param array|null $externalAccountId The ID of the external account to retrieve. * @param array|null $params * @param array|string|null $opts @@ -142,7 +184,7 @@ class Account extends ApiResource } /** - * @param array|null $id The ID of the account to which the external account belongs. + * @param string|null $id The ID of the account to which the external account belongs. * @param array|null $externalAccountId The ID of the external account to update. * @param array|null $params * @param array|string|null $opts @@ -155,7 +197,7 @@ class Account extends ApiResource } /** - * @param array|null $id The ID of the account to which the external account belongs. + * @param string|null $id The ID of the account to which the external account belongs. * @param array|null $externalAccountId The ID of the external account to delete. * @param array|null $params * @param array|string|null $opts @@ -168,11 +210,11 @@ class Account extends ApiResource } /** - * @param array|null $id The ID of the account on which to retrieve the external accounts. + * @param string|null $id The ID of the account on which to retrieve the external accounts. * @param array|null $params * @param array|string|null $opts * - * @return BankAccount|Card + * @return Collection The list of external accounts (BankAccount or Card). */ public static function allExternalAccounts($id, $params = null, $opts = null) { @@ -180,7 +222,7 @@ class Account extends ApiResource } /** - * @param array|null $id The ID of the account on which to create the login link. + * @param string|null $id The ID of the account on which to create the login link. * @param array|null $params * @param array|string|null $opts * @@ -191,6 +233,69 @@ class Account extends ApiResource return self::_createNestedResource($id, static::PATH_LOGIN_LINKS, $params, $opts); } + /** + * @param string|null $id The ID of the account on which to create the person. + * @param array|null $params + * @param array|string|null $opts + * + * @return Person + */ + public static function createPerson($id, $params = null, $opts = null) + { + return self::_createNestedResource($id, static::PATH_PERSONS, $params, $opts); + } + + /** + * @param string|null $id The ID of the account to which the person belongs. + * @param string|null $personId The ID of the person to retrieve. + * @param array|null $params + * @param array|string|null $opts + * + * @return Person + */ + public static function retrievePerson($id, $personId, $params = null, $opts = null) + { + return self::_retrieveNestedResource($id, static::PATH_PERSONS, $personId, $params, $opts); + } + + /** + * @param string|null $id The ID of the account to which the person belongs. + * @param string|null $personId The ID of the person to update. + * @param array|null $params + * @param array|string|null $opts + * + * @return Person + */ + public static function updatePerson($id, $personId, $params = null, $opts = null) + { + return self::_updateNestedResource($id, static::PATH_PERSONS, $personId, $params, $opts); + } + + /** + * @param string|null $id The ID of the account to which the person belongs. + * @param string|null $personId The ID of the person to delete. + * @param array|null $params + * @param array|string|null $opts + * + * @return Person + */ + public static function deletePerson($id, $personId, $params = null, $opts = null) + { + return self::_deleteNestedResource($id, static::PATH_PERSONS, $personId, $params, $opts); + } + + /** + * @param string|null $id The ID of the account on which to retrieve the persons. + * @param array|null $params + * @param array|string|null $opts + * + * @return Collection The list of persons. + */ + public static function allPersons($id, $params = null, $opts = null) + { + return self::_allNestedResources($id, static::PATH_PERSONS, $params, $opts); + } + public function serializeParameters($force = false) { $update = parent::serializeParameters($force); @@ -203,6 +308,12 @@ class Account extends ApiResource $update['legal_entity'] = $entityUpdate; } } + if (isset($this->_values['individual'])) { + $individual = $this['individual']; + if (($individual instanceof Person) && !isset($update['individual'])) { + $update['individual'] = $individual->serializeParameters($force); + } + } return $update; } @@ -224,7 +335,9 @@ class Account extends ApiResource $update = ($v instanceof StripeObject) ? $v->serializeParameters() : $v; if ($update !== []) { - if (!$originalValue || ($update != $legalEntity->serializeParamsValue($originalValue[$i], null, false, true))) { + if (!$originalValue || + !array_key_exists($i, $originalValue) || + ($update != $legalEntity->serializeParamsValue($originalValue[$i], null, false, true))) { $updateArr[$i] = $update; } } diff --git a/htdocs/includes/stripe/lib/AccountLink.php b/htdocs/includes/stripe/lib/AccountLink.php new file mode 100644 index 00000000000..f2975ae3834 --- /dev/null +++ b/htdocs/includes/stripe/lib/AccountLink.php @@ -0,0 +1,21 @@ +setLastResponse($response); $obj->setRequestParams($params); diff --git a/htdocs/includes/stripe/lib/ApiOperations/NestedResource.php b/htdocs/includes/stripe/lib/ApiOperations/NestedResource.php index 1c3a73f45de..2122354362f 100644 --- a/htdocs/includes/stripe/lib/ApiOperations/NestedResource.php +++ b/htdocs/includes/stripe/lib/ApiOperations/NestedResource.php @@ -60,6 +60,7 @@ trait NestedResource /** * @param string $id * @param string $nestedPath + * @param string|null $nestedId * @param array|null $params * @param array|string|null $options * @@ -74,6 +75,7 @@ trait NestedResource /** * @param string $id * @param string $nestedPath + * @param string|null $nestedId * @param array|null $params * @param array|string|null $options * @@ -88,6 +90,7 @@ trait NestedResource /** * @param string $id * @param string $nestedPath + * @param string|null $nestedId * @param array|null $params * @param array|string|null $options * diff --git a/htdocs/includes/stripe/lib/ApiOperations/Request.php b/htdocs/includes/stripe/lib/ApiOperations/Request.php index c6b06585ad2..dd048dc5f5c 100644 --- a/htdocs/includes/stripe/lib/ApiOperations/Request.php +++ b/htdocs/includes/stripe/lib/ApiOperations/Request.php @@ -52,7 +52,8 @@ trait Request protected static function _staticRequest($method, $url, $params, $options) { $opts = \Stripe\Util\RequestOptions::parse($options); - $requestor = new \Stripe\ApiRequestor($opts->apiKey, static::baseUrl()); + $baseUrl = isset($opts->apiBase) ? $opts->apiBase : static::baseUrl(); + $requestor = new \Stripe\ApiRequestor($opts->apiKey, $baseUrl); list($response, $opts->apiKey) = $requestor->request($method, $url, $params, $opts->headers); $opts->discardNonPersistentHeaders(); return [$response, $opts]; diff --git a/htdocs/includes/stripe/lib/ApiOperations/Retrieve.php b/htdocs/includes/stripe/lib/ApiOperations/Retrieve.php index a037326b3e8..ed52296b75b 100644 --- a/htdocs/includes/stripe/lib/ApiOperations/Retrieve.php +++ b/htdocs/includes/stripe/lib/ApiOperations/Retrieve.php @@ -15,7 +15,7 @@ trait Retrieve * or an options array containing an `id` key. * @param array|string|null $opts * - * @return \Stripe\StripeObject + * @return static */ public static function retrieve($id, $opts = null) { diff --git a/htdocs/includes/stripe/lib/ApiRequestor.php b/htdocs/includes/stripe/lib/ApiRequestor.php index 334d84425b3..7cf851877de 100644 --- a/htdocs/includes/stripe/lib/ApiRequestor.php +++ b/htdocs/includes/stripe/lib/ApiRequestor.php @@ -9,12 +9,32 @@ namespace Stripe; */ class ApiRequestor { + /** + * @var string|null + */ private $_apiKey; + /** + * @var string + */ private $_apiBase; + /** + * @var HttpClient\ClientInterface + */ private static $_httpClient; + /** + * @var RequestTelemetry + */ + private static $requestTelemetry; + + /** + * ApiRequestor constructor. + * + * @param string|null $apiKey + * @param string|null $apiBase + */ public function __construct($apiKey = null, $apiBase = null) { $this->_apiKey = $apiKey; @@ -24,6 +44,37 @@ class ApiRequestor $this->_apiBase = $apiBase; } + /** + * Creates a telemetry json blob for use in 'X-Stripe-Client-Telemetry' headers + * @static + * + * @param RequestTelemetry $requestTelemetry + * @return string + */ + private static function _telemetryJson($requestTelemetry) + { + $payload = array( + 'last_request_metrics' => array( + 'request_id' => $requestTelemetry->requestId, + 'request_duration_ms' => $requestTelemetry->requestDuration, + )); + + $result = json_encode($payload); + if ($result != false) { + return $result; + } else { + Stripe::getLogger()->error("Serializing telemetry payload failed!"); + return "{}"; + } + } + + /** + * @static + * + * @param ApiResource|bool|array|mixed $d + * + * @return ApiResource|array|string|mixed + */ private static function _encodeObjects($d) { if ($d instanceof ApiResource) { @@ -44,13 +95,27 @@ class ApiRequestor } /** - * @param string $method - * @param string $url + * @param string $method + * @param string $url * @param array|null $params * @param array|null $headers * * @return array An array whose first element is an API response and second * element is the API key used to make the request. + * @throws Error\Api + * @throws Error\Authentication + * @throws Error\Card + * @throws Error\InvalidRequest + * @throws Error\OAuth\InvalidClient + * @throws Error\OAuth\InvalidGrant + * @throws Error\OAuth\InvalidRequest + * @throws Error\OAuth\InvalidScope + * @throws Error\OAuth\UnsupportedGrantType + * @throws Error\OAuth\UnsupportedResponseType + * @throws Error\Permission + * @throws Error\RateLimit + * @throws Error\Idempotency + * @throws Error\ApiConnection */ public function request($method, $url, $params = null, $headers = null) { @@ -70,13 +135,22 @@ class ApiRequestor * @param array $resp * * @throws Error\InvalidRequest if the error is caused by the user. - * @throws Error\Idempotency if the error is caused by an idempotency key. * @throws Error\Authentication if the error is caused by a lack of * permissions. * @throws Error\Permission if the error is caused by insufficient * permissions. * @throws Error\Card if the error is the error code is 402 (payment * required) + * @throws Error\InvalidRequest if the error is caused by the user. + * @throws Error\Idempotency if the error is caused by an idempotency key. + * @throws Error\OAuth\InvalidClient + * @throws Error\OAuth\InvalidGrant + * @throws Error\OAuth\InvalidRequest + * @throws Error\OAuth\InvalidScope + * @throws Error\OAuth\UnsupportedGrantType + * @throws Error\OAuth\UnsupportedResponseType + * @throws Error\Permission if the error is caused by insufficient + * permissions. * @throws Error\RateLimit if the error is caused by too many requests * hitting the API. * @throws Error\Api otherwise. @@ -102,6 +176,17 @@ class ApiRequestor throw $error; } + /** + * @static + * + * @param string $rbody + * @param int $rcode + * @param array $rheaders + * @param array $resp + * @param array $errorData + * + * @return Error\RateLimit|Error\Idempotency|Error\InvalidRequest|Error\Authentication|Error\Card|Error\Permission|Error\Api + */ private static function _specificAPIError($rbody, $rcode, $rheaders, $resp, $errorData) { $msg = isset($errorData['message']) ? $errorData['message'] : null; @@ -136,6 +221,17 @@ class ApiRequestor } } + /** + * @static + * + * @param string|bool $rbody + * @param int $rcode + * @param array $rheaders + * @param array $resp + * @param string $errorCode + * + * @return null|Error\OAuth\InvalidClient|Error\OAuth\InvalidGrant|Error\OAuth\InvalidRequest|Error\OAuth\InvalidScope|Error\OAuth\UnsupportedGrantType|Error\OAuth\UnsupportedResponseType + */ private static function _specificOAuthError($rbody, $rcode, $rheaders, $resp, $errorCode) { $description = isset($resp['error_description']) ? $resp['error_description'] : $errorCode; @@ -158,6 +254,13 @@ class ApiRequestor return null; } + /** + * @static + * + * @param null|array $appInfo + * + * @return null|string + */ private static function _formatAppInfo($appInfo) { if ($appInfo !== null) { @@ -174,6 +277,14 @@ class ApiRequestor } } + /** + * @static + * + * @param string $apiKey + * @param null $clientInfo + * + * @return array + */ private static function _defaultHeaders($apiKey, $clientInfo = null) { $uaString = 'Stripe/v1 PhpBindings/' . Stripe::VERSION; @@ -205,6 +316,17 @@ class ApiRequestor return $defaultHeaders; } + /** + * @param string $method + * @param string $url + * @param array $params + * @param array $headers + * + * @return array + * @throws Error\Api + * @throws Error\ApiConnection + * @throws Error\Authentication + */ private function _requestRaw($method, $url, $params, $headers) { $myApiKey = $this->_apiKey; @@ -239,6 +361,10 @@ class ApiRequestor $defaultHeaders['Stripe-Account'] = Stripe::$accountId; } + if (Stripe::$enableTelemetry && self::$requestTelemetry != null) { + $defaultHeaders["X-Stripe-Client-Telemetry"] = self::_telemetryJson(self::$requestTelemetry); + } + $hasFile = false; $hasCurlFile = class_exists('\CURLFile', false); foreach ($params as $k => $v) { @@ -263,6 +389,8 @@ class ApiRequestor $rawHeaders[] = $header . ': ' . $value; } + $requestStartMs = Util\Util::currentTimeMillis(); + list($rbody, $rcode, $rheaders) = $this->httpClient()->request( $method, $absUrl, @@ -270,9 +398,24 @@ class ApiRequestor $params, $hasFile ); + + if (array_key_exists('request-id', $rheaders)) { + self::$requestTelemetry = new RequestTelemetry( + $rheaders['request-id'], + Util\Util::currentTimeMillis() - $requestStartMs + ); + } + return [$rbody, $rcode, $rheaders, $myApiKey]; } + /** + * @param resource $resource + * @param bool $hasCurlFile + * + * @return \CURLFile|string + * @throws Error\Api + */ private function _processResourceParam($resource, $hasCurlFile) { if (get_resource_type($resource) !== 'stream') { @@ -296,6 +439,26 @@ class ApiRequestor } } + /** + * @param string $rbody + * @param int $rcode + * @param array $rheaders + * + * @return mixed + * @throws Error\Api + * @throws Error\Authentication + * @throws Error\Card + * @throws Error\InvalidRequest + * @throws Error\OAuth\InvalidClient + * @throws Error\OAuth\InvalidGrant + * @throws Error\OAuth\InvalidRequest + * @throws Error\OAuth\InvalidScope + * @throws Error\OAuth\UnsupportedGrantType + * @throws Error\OAuth\UnsupportedResponseType + * @throws Error\Permission + * @throws Error\RateLimit + * @throws Error\Idempotency + */ private function _interpretResponse($rbody, $rcode, $rheaders) { $resp = json_decode($rbody, true); @@ -312,11 +475,29 @@ class ApiRequestor return $resp; } + /** + * @static + * + * @param HttpClient\ClientInterface $client + */ public static function setHttpClient($client) { self::$_httpClient = $client; } + /** + * @static + * + * Resets any stateful telemetry data + */ + public static function resetTelemetry() + { + self::$requestTelemetry = null; + } + + /** + * @return HttpClient\ClientInterface + */ private function httpClient() { if (!self::$_httpClient) { diff --git a/htdocs/includes/stripe/lib/ApiResource.php b/htdocs/includes/stripe/lib/ApiResource.php index f73b22c9663..fe594321687 100644 --- a/htdocs/includes/stripe/lib/ApiResource.php +++ b/htdocs/includes/stripe/lib/ApiResource.php @@ -66,30 +66,6 @@ abstract class ApiResource extends StripeObject return $this; } - /** - * @return string The name of the class, with namespacing and underscores - * stripped. - */ - public static function className() - { - $class = get_called_class(); - // Useful for namespaces: Foo\Charge - if ($postfixNamespaces = strrchr($class, '\\')) { - $class = substr($postfixNamespaces, 1); - } - // Useful for underscored 'namespaces': Foo_Charge - if ($postfixFakeNamespaces = strrchr($class, '')) { - $class = $postfixFakeNamespaces; - } - if (substr($class, 0, strlen('Stripe')) == 'Stripe') { - $class = substr($class, strlen('Stripe')); - } - $class = str_replace('_', '', $class); - $name = urlencode($class); - $name = strtolower($name); - return $name; - } - /** * @return string The base URL for the given class. */ @@ -103,7 +79,9 @@ abstract class ApiResource extends StripeObject */ public static function classUrl() { - $base = static::className(); + // Replace dots with slashes for namespaced resources, e.g. if the object's name is + // "foo.bar", then its URL will be "/v1/foo/bars". + $base = str_replace('.', '/', static::OBJECT_NAME); return "/v1/${base}s"; } diff --git a/htdocs/includes/stripe/lib/ApplePayDomain.php b/htdocs/includes/stripe/lib/ApplePayDomain.php index 124c5dc0632..ea84220a7a9 100644 --- a/htdocs/includes/stripe/lib/ApplePayDomain.php +++ b/htdocs/includes/stripe/lib/ApplePayDomain.php @@ -9,6 +9,9 @@ namespace Stripe; */ class ApplePayDomain extends ApiResource { + + const OBJECT_NAME = "apple_pay_domain"; + use ApiOperations\All; use ApiOperations\Create; use ApiOperations\Delete; diff --git a/htdocs/includes/stripe/lib/ApplicationFee.php b/htdocs/includes/stripe/lib/ApplicationFee.php index 05b94ea9235..0d9fde4c521 100644 --- a/htdocs/includes/stripe/lib/ApplicationFee.php +++ b/htdocs/includes/stripe/lib/ApplicationFee.php @@ -24,23 +24,15 @@ namespace Stripe; */ class ApplicationFee extends ApiResource { + + const OBJECT_NAME = "application_fee"; + use ApiOperations\All; use ApiOperations\NestedResource; use ApiOperations\Retrieve; const PATH_REFUNDS = '/refunds'; - /** - * This is a special case because the application fee endpoint has an - * underscore in it. The parent `className` function strips underscores. - * - * @return string The name of the class. - */ - public static function className() - { - return 'application_fee'; - } - /** * @param array|null $params * @param array|string|null $opts @@ -55,7 +47,7 @@ class ApplicationFee extends ApiResource } /** - * @param array|null $id The ID of the application fee on which to create the refund. + * @param string|null $id The ID of the application fee on which to create the refund. * @param array|null $params * @param array|string|null $opts * @@ -67,7 +59,7 @@ class ApplicationFee extends ApiResource } /** - * @param array|null $id The ID of the application fee to which the refund belongs. + * @param string|null $id The ID of the application fee to which the refund belongs. * @param array|null $refundId The ID of the refund to retrieve. * @param array|null $params * @param array|string|null $opts @@ -80,7 +72,7 @@ class ApplicationFee extends ApiResource } /** - * @param array|null $id The ID of the application fee to which the refund belongs. + * @param string|null $id The ID of the application fee to which the refund belongs. * @param array|null $refundId The ID of the refund to update. * @param array|null $params * @param array|string|null $opts @@ -93,11 +85,11 @@ class ApplicationFee extends ApiResource } /** - * @param array|null $id The ID of the application fee on which to retrieve the refunds. + * @param string|null $id The ID of the application fee on which to retrieve the refunds. * @param array|null $params * @param array|string|null $opts * - * @return ApplicationFeeRefund + * @return Collection The list of refunds. */ public static function allRefunds($id, $params = null, $opts = null) { diff --git a/htdocs/includes/stripe/lib/ApplicationFeeRefund.php b/htdocs/includes/stripe/lib/ApplicationFeeRefund.php index 4b1c425a8ee..91d7e9d2bc6 100644 --- a/htdocs/includes/stripe/lib/ApplicationFeeRefund.php +++ b/htdocs/includes/stripe/lib/ApplicationFeeRefund.php @@ -18,6 +18,9 @@ namespace Stripe; */ class ApplicationFeeRefund extends ApiResource { + + const OBJECT_NAME = "fee_refund"; + use ApiOperations\Update { save as protected _save; } diff --git a/htdocs/includes/stripe/lib/Balance.php b/htdocs/includes/stripe/lib/Balance.php index 115307f843b..25f88ae74c7 100644 --- a/htdocs/includes/stripe/lib/Balance.php +++ b/htdocs/includes/stripe/lib/Balance.php @@ -7,6 +7,7 @@ namespace Stripe; * * @property string $object * @property array $available + * @property array $connect_reserved * @property bool $livemode * @property array $pending * @@ -14,6 +15,9 @@ namespace Stripe; */ class Balance extends SingletonApiResource { + + const OBJECT_NAME = "balance"; + /** * @param array|string|null $opts * diff --git a/htdocs/includes/stripe/lib/BalanceTransaction.php b/htdocs/includes/stripe/lib/BalanceTransaction.php index f82888ab1dd..cd9b79ae675 100644 --- a/htdocs/includes/stripe/lib/BalanceTransaction.php +++ b/htdocs/includes/stripe/lib/BalanceTransaction.php @@ -24,6 +24,9 @@ namespace Stripe; */ class BalanceTransaction extends ApiResource { + + const OBJECT_NAME = "balance_transaction"; + use ApiOperations\All; use ApiOperations\Retrieve; diff --git a/htdocs/includes/stripe/lib/BankAccount.php b/htdocs/includes/stripe/lib/BankAccount.php index 2afc312d003..019a4d87cbd 100644 --- a/htdocs/includes/stripe/lib/BankAccount.php +++ b/htdocs/includes/stripe/lib/BankAccount.php @@ -25,6 +25,9 @@ namespace Stripe; */ class BankAccount extends ApiResource { + + const OBJECT_NAME = "bank_account"; + use ApiOperations\Delete; use ApiOperations\Update; diff --git a/htdocs/includes/stripe/lib/BitcoinReceiver.php b/htdocs/includes/stripe/lib/BitcoinReceiver.php index 8d04256b5db..b4cc5291b56 100644 --- a/htdocs/includes/stripe/lib/BitcoinReceiver.php +++ b/htdocs/includes/stripe/lib/BitcoinReceiver.php @@ -12,6 +12,9 @@ namespace Stripe; */ class BitcoinReceiver extends ApiResource { + + const OBJECT_NAME = "bitcoin_receiver"; + use ApiOperations\All; use ApiOperations\Retrieve; diff --git a/htdocs/includes/stripe/lib/BitcoinTransaction.php b/htdocs/includes/stripe/lib/BitcoinTransaction.php index 6b8e5421124..8269fd216eb 100644 --- a/htdocs/includes/stripe/lib/BitcoinTransaction.php +++ b/htdocs/includes/stripe/lib/BitcoinTransaction.php @@ -10,4 +10,5 @@ namespace Stripe; class BitcoinTransaction extends ApiResource { + const OBJECT_NAME = "bitcoin_transaction"; } diff --git a/htdocs/includes/stripe/lib/Card.php b/htdocs/includes/stripe/lib/Card.php index 7e57423601a..40de733e780 100644 --- a/htdocs/includes/stripe/lib/Card.php +++ b/htdocs/includes/stripe/lib/Card.php @@ -7,6 +7,7 @@ namespace Stripe; * * @property string $id * @property string $object + * @property string $account * @property string $address_city * @property string $address_country * @property string $address_line1 @@ -15,10 +16,13 @@ namespace Stripe; * @property string $address_state * @property string $address_zip * @property string $address_zip_check + * @property string[] $available_payout_methods * @property string $brand * @property string $country + * @property string $currency * @property string $customer * @property string $cvc_check + * @property bool $default_for_currency * @property string $dynamic_last4 * @property int $exp_month * @property int $exp_year @@ -27,15 +31,44 @@ namespace Stripe; * @property string $last4 * @property StripeObject $metadata * @property string $name + * @property string $recipient * @property string $tokenization_method * * @package Stripe */ class Card extends ApiResource { + + const OBJECT_NAME = "card"; + use ApiOperations\Delete; use ApiOperations\Update; + /** + * Possible string representations of the CVC check status. + * @link https://stripe.com/docs/api/cards/object#card_object-cvc_check + */ + const CVC_CHECK_FAIL = 'fail'; + const CVC_CHECK_PASS = 'pass'; + const CVC_CHECK_UNAVAILABLE = 'unavailable'; + const CVC_CHECK_UNCHECKED = 'unchecked'; + + /** + * Possible string representations of the funding of the card. + * @link https://stripe.com/docs/api/cards/object#card_object-funding + */ + const FUNDING_CREDIT = 'credit'; + const FUNDING_DEBIT = 'debit'; + const FUNDING_PREPAID = 'prepaid'; + const FUNDING_UNKNOWN = 'unknown'; + + /** + * Possible string representations of the tokenization method when using Apple Pay or Google Pay. + * @link https://stripe.com/docs/api/cards/object#card_object-tokenization_method + */ + const TOKENIZATION_METHOD_APPLE_PAY = 'apple_pay'; + const TOKENIZATION_METHOD_GOOGLE_PAY = 'google_pay'; + /** * @return string The instance URL for this resource. It needs to be special * cased because cards are nested resources that may belong to different @@ -74,7 +107,7 @@ class Card extends ApiResource { $msg = "Cards cannot be accessed without a customer, recipient or account ID. " . "Retrieve a card using \$customer->sources->retrieve('card_id'), " . - "\$recipient->cards->retrieve('card_id'), or"; + "\$recipient->cards->retrieve('card_id'), or " . "\$account->external_accounts->retrieve('card_id') instead."; throw new Error\InvalidRequest($msg, null); } @@ -90,7 +123,7 @@ class Card extends ApiResource { $msg = "Cards cannot be accessed without a customer, recipient or account ID. " . "Call save() on \$customer->sources->retrieve('card_id'), " . - "\$recipient->cards->retrieve('card_id'), or"; + "\$recipient->cards->retrieve('card_id'), or " . "\$account->external_accounts->retrieve('card_id') instead."; throw new Error\InvalidRequest($msg, null); } diff --git a/htdocs/includes/stripe/lib/Charge.php b/htdocs/includes/stripe/lib/Charge.php index 6d448022877..832a07c7c04 100644 --- a/htdocs/includes/stripe/lib/Charge.php +++ b/htdocs/includes/stripe/lib/Charge.php @@ -29,8 +29,10 @@ namespace Stripe; * @property string $order * @property mixed $outcome * @property bool $paid + * @property string $payment_intent * @property string $receipt_email * @property string $receipt_number + * @property string $receipt_url * @property bool $refunded * @property Collection $refunds * @property string $review @@ -40,17 +42,77 @@ namespace Stripe; * @property string $statement_descriptor * @property string $status * @property string $transfer + * @property mixed $transfer_data * @property string $transfer_group * * @package Stripe */ class Charge extends ApiResource { + + const OBJECT_NAME = "charge"; + use ApiOperations\All; use ApiOperations\Create; use ApiOperations\Retrieve; use ApiOperations\Update; + /** + * Possible string representations of decline codes. + * These strings are applicable to the decline_code property of the \Stripe\Error\Card exception. + * @link https://stripe.com/docs/declines/codes + */ + const DECLINED_APPROVE_WITH_ID = 'approve_with_id'; + const DECLINED_CALL_ISSUER = 'call_issuer'; + const DECLINED_CARD_NOT_SUPPORTED = 'card_not_supported'; + const DECLINED_CARD_VELOCITY_EXCEEDED = 'card_velocity_exceeded'; + const DECLINED_CURRENCY_NOT_SUPPORTED = 'currency_not_supported'; + const DECLINED_DO_NOT_HONOR = 'do_not_honor'; + const DECLINED_DO_NOT_TRY_AGAIN = 'do_not_try_again'; + const DECLINED_DUPLICATED_TRANSACTION = 'duplicate_transaction'; + const DECLINED_EXPIRED_CARD = 'expired_card'; + const DECLINED_FRAUDULENT = 'fraudulent'; + const DECLINED_GENERIC_DECLINE = 'generic_decline'; + const DECLINED_INCORRECT_NUMBER = 'incorrect_number'; + const DECLINED_INCORRECT_CVC = 'incorrect_cvc'; + const DECLINED_INCORRECT_PIN = 'incorrect_pin'; + const DECLINED_INCORRECT_ZIP = 'incorrect_zip'; + const DECLINED_INSUFFICIENT_FUNDS = 'insufficient_funds'; + const DECLINED_INVALID_ACCOUNT = 'invalid_account'; + const DECLINED_INVALID_AMOUNT = 'invalid_amount'; + const DECLINED_INVALID_CVC = 'invalid_cvc'; + const DECLINED_INVALID_EXPIRY_YEAR = 'invalid_expiry_year'; + const DECLINED_INVALID_NUMBER = 'invalid_number'; + const DECLINED_INVALID_PIN = 'invalid_pin'; + const DECLINED_ISSUER_NOT_AVAILABLE = 'issuer_not_available'; + const DECLINED_LOST_CARD = 'lost_card'; + const DECLINED_NEW_ACCOUNT_INFORMATION_AVAILABLE = 'new_account_information_available'; + const DECLINED_NO_ACTION_TAKEN = 'no_action_taken'; + const DECLINED_NOT_PERMITTED = 'not_permitted'; + const DECLINED_PICKUP_CARD = 'pickup_card'; + const DECLINED_PIN_TRY_EXCEEDED = 'pin_try_exceeded'; + const DECLINED_PROCESSING_ERROR = 'processing_error'; + const DECLINED_REENTER_TRANSACTION = 'reenter_transaction'; + const DECLINED_RESTRICTED_CARD = 'restricted_card'; + const DECLINED_REVOCATION_OF_ALL_AUTHORIZATIONS = 'revocation_of_all_authorizations'; + const DECLINED_REVOCATION_OF_AUTHORIZATION = 'revocation_of_authorization'; + const DECLINED_SECURITY_VIOLATION = 'security_violation'; + const DECLINED_SERVICE_NOT_ALLOWED = 'service_not_allowed'; + const DECLINED_STOLEN_CARD = 'stolen_card'; + const DECLINED_STOP_PAYMENT_ORDER = 'stop_payment_order'; + const DECLINED_TESTMODE_DECLINE = 'testmode_decline'; + const DECLINED_TRANSACTION_NOT_ALLOWED = 'transaction_not_allowed'; + const DECLINED_TRY_AGAIN_LATER = 'try_again_later'; + const DECLINED_WITHDRAWAL_COUNT_LIMIT_EXCEEDED = 'withdrawal_count_limit_exceeded'; + + /** + * Possible string representations of the status of the charge. + * @link https://stripe.com/docs/api/charges/object#charge_object-status + */ + const STATUS_FAILED = 'failed'; + const STATUS_PENDING = 'pending'; + const STATUS_SUCCEEDED = 'succeeded'; + /** * @param array|null $params * @param array|string|null $options diff --git a/htdocs/includes/stripe/lib/Checkout/Session.php b/htdocs/includes/stripe/lib/Checkout/Session.php new file mode 100644 index 00000000000..968d58cf632 --- /dev/null +++ b/htdocs/includes/stripe/lib/Checkout/Session.php @@ -0,0 +1,30 @@ +data); + } + /** * @return Util\AutoPagingIterator An iterator that can be used to iterate * across all objects across all pages. As page boundaries are diff --git a/htdocs/includes/stripe/lib/CountrySpec.php b/htdocs/includes/stripe/lib/CountrySpec.php index cdaa4e84d89..668bfe62ed9 100644 --- a/htdocs/includes/stripe/lib/CountrySpec.php +++ b/htdocs/includes/stripe/lib/CountrySpec.php @@ -11,23 +11,16 @@ namespace Stripe; * @property mixed $supported_bank_account_currencies * @property string[] $supported_payment_currencies * @property string[] $supported_payment_methods + * @property string[] $supported_transfer_countries * @property mixed $verification_fields * * @package Stripe */ class CountrySpec extends ApiResource { + + const OBJECT_NAME = "country_spec"; + use ApiOperations\All; use ApiOperations\Retrieve; - - /** - * This is a special case because the country specs endpoint has an - * underscore in it. The parent `className` function strips underscores. - * - * @return string The name of the class. - */ - public static function className() - { - return 'country_spec'; - } } diff --git a/htdocs/includes/stripe/lib/Coupon.php b/htdocs/includes/stripe/lib/Coupon.php index a2d44443ce5..51d4fd86593 100644 --- a/htdocs/includes/stripe/lib/Coupon.php +++ b/htdocs/includes/stripe/lib/Coupon.php @@ -15,7 +15,8 @@ namespace Stripe; * @property bool $livemode * @property int $max_redemptions * @property StripeObject $metadata - * @property int $percent_off + * @property string $name + * @property float $percent_off * @property int $redeem_by * @property int $times_redeemed * @property bool $valid @@ -24,6 +25,9 @@ namespace Stripe; */ class Coupon extends ApiResource { + + const OBJECT_NAME = "coupon"; + use ApiOperations\All; use ApiOperations\Create; use ApiOperations\Delete; diff --git a/htdocs/includes/stripe/lib/CreditNote.php b/htdocs/includes/stripe/lib/CreditNote.php new file mode 100644 index 00000000000..169ed0815c3 --- /dev/null +++ b/htdocs/includes/stripe/lib/CreditNote.php @@ -0,0 +1,73 @@ +instanceUrl() . '/void'; + list($response, $opts) = $this->_request('post', $url, $params, $opts); + $this->refreshFrom($response, $opts); + return $this; + } +} diff --git a/htdocs/includes/stripe/lib/Customer.php b/htdocs/includes/stripe/lib/Customer.php index 8d31b5ac0aa..44f5e6e2f09 100644 --- a/htdocs/includes/stripe/lib/Customer.php +++ b/htdocs/includes/stripe/lib/Customer.php @@ -8,24 +8,33 @@ namespace Stripe; * @property string $id * @property string $object * @property int $account_balance - * @property string $business_vat_id + * @property mixed $address * @property string $created * @property string $currency * @property string $default_source * @property bool $delinquent * @property string $description - * @property mixed $discount + * @property Discount $discount * @property string $email + * @property string $invoice_prefix + * @property mixed $invoice_settings * @property bool $livemode * @property StripeObject $metadata + * @property string $name + * @property string $phone + * @property string[] preferred_locales * @property mixed $shipping * @property Collection $sources * @property Collection $subscriptions + * @property Collection $tax_ids * * @package Stripe */ class Customer extends ApiResource { + + const OBJECT_NAME = "customer"; + use ApiOperations\All; use ApiOperations\Create; use ApiOperations\Delete; @@ -33,6 +42,14 @@ class Customer extends ApiResource use ApiOperations\Retrieve; use ApiOperations\Update; + /** + * Possible string representations of the customer's type of tax exemption. + * @link https://stripe.com/docs/api/customers/object#customer_object-tax_exempt + */ + const TAX_EXEMPT_NONE = 'none'; + const TAX_EXEMPT_EXEMPT = 'exempt'; + const TAX_EXEMPT_REVERSE = 'reverse'; + public static function getSavedNestedResources() { static $savedNestedResources = null; @@ -45,6 +62,7 @@ class Customer extends ApiResource } const PATH_SOURCES = '/sources'; + const PATH_TAX_IDS = '/tax_ids'; /** * @param array|null $params @@ -135,7 +153,7 @@ class Customer extends ApiResource } /** - * @param array|null $id The ID of the customer on which to create the source. + * @param string|null $id The ID of the customer on which to create the source. * @param array|null $params * @param array|string|null $opts * @@ -147,8 +165,8 @@ class Customer extends ApiResource } /** - * @param array|null $id The ID of the customer to which the source belongs. - * @param array|null $sourceId The ID of the source to retrieve. + * @param string|null $id The ID of the customer to which the source belongs. + * @param string|null $sourceId The ID of the source to retrieve. * @param array|null $params * @param array|string|null $opts * @@ -160,8 +178,8 @@ class Customer extends ApiResource } /** - * @param array|null $id The ID of the customer to which the source belongs. - * @param array|null $sourceId The ID of the source to update. + * @param string|null $id The ID of the customer to which the source belongs. + * @param string|null $sourceId The ID of the source to update. * @param array|null $params * @param array|string|null $opts * @@ -173,8 +191,8 @@ class Customer extends ApiResource } /** - * @param array|null $id The ID of the customer to which the source belongs. - * @param array|null $sourceId The ID of the source to delete. + * @param string|null $id The ID of the customer to which the source belongs. + * @param string|null $sourceId The ID of the source to delete. * @param array|null $params * @param array|string|null $opts * @@ -186,14 +204,64 @@ class Customer extends ApiResource } /** - * @param array|null $id The ID of the customer on which to retrieve the sources. + * @param string|null $id The ID of the customer on which to retrieve the sources. * @param array|null $params * @param array|string|null $opts * - * @return ApiResource + * @return Collection The list of sources. */ public static function allSources($id, $params = null, $opts = null) { return self::_allNestedResources($id, static::PATH_SOURCES, $params, $opts); } + + /** + * @param string|null $id The ID of the customer on which to create the tax id. + * @param array|null $params + * @param array|string|null $opts + * + * @return ApiResource + */ + public static function createTaxId($id, $params = null, $opts = null) + { + return self::_createNestedResource($id, static::PATH_TAX_IDS, $params, $opts); + } + + /** + * @param string|null $id The ID of the customer to which the tax id belongs. + * @param string|null $taxIdId The ID of the tax id to retrieve. + * @param array|null $params + * @param array|string|null $opts + * + * @return ApiResource + */ + public static function retrieveTaxId($id, $taxIdId, $params = null, $opts = null) + { + return self::_retrieveNestedResource($id, static::PATH_TAX_IDS, $taxIdId, $params, $opts); + } + + /** + * @param string|null $id The ID of the customer to which the tax id belongs. + * @param string|null $taxIdId The ID of the tax id to delete. + * @param array|null $params + * @param array|string|null $opts + * + * @return ApiResource + */ + public static function deleteTaxId($id, $taxIdId, $params = null, $opts = null) + { + return self::_deleteNestedResource($id, static::PATH_TAX_IDS, $taxIdId, $params, $opts); + } + + /** + * @param string|null $id The ID of the customer on which to retrieve the tax ids. + * @param array|null $params + * @param array|string|null $opts + * + * @return Collection The list of tax ids. + */ + public static function allTaxIds($id, $params = null, $opts = null) + { + return self::_allNestedResources($id, static::PATH_TAX_IDS, $params, $opts); + } } diff --git a/htdocs/includes/stripe/lib/Discount.php b/htdocs/includes/stripe/lib/Discount.php new file mode 100644 index 00000000000..a72d12bc6e3 --- /dev/null +++ b/htdocs/includes/stripe/lib/Discount.php @@ -0,0 +1,21 @@ +code = $code; + $this->errorCode = $code; } public function getErrorCode() { - return $this->code; + return $this->errorCode; } } diff --git a/htdocs/includes/stripe/lib/Event.php b/htdocs/includes/stripe/lib/Event.php index 2add5ce11be..90b55c75151 100644 --- a/htdocs/includes/stripe/lib/Event.php +++ b/htdocs/includes/stripe/lib/Event.php @@ -7,107 +7,152 @@ namespace Stripe; * * @property string $id * @property string $object + * @property string $account * @property string $api_version - * @property int $created - * @property mixed $data - * @property bool $livemode - * @property int $pending_webhooks - * @property mixed $request + * @property int $created + * @property mixed $data + * @property bool $livemode + * @property int $pending_webhooks + * @property mixed $request * @property string $type * * @package Stripe */ class Event extends ApiResource { - /** + + const OBJECT_NAME = "event"; + + /** * Possible string representations of event types. * @link https://stripe.com/docs/api#event_types */ - const ACCOUNT_UPDATED = 'account.updated'; - const ACCOUNT_APPLICATION_DEAUTHORIZED = 'account.application.deauthorized'; - const ACCOUNT_EXTERNAL_ACCOUNT_CREATED = 'account.external_account.created'; - const ACCOUNT_EXTERNAL_ACCOUNT_DELETED = 'account.external_account.deleted'; - const ACCOUNT_EXTERNAL_ACCOUNT_UPDATED = 'account.external_account.updated'; - const APPLICATION_FEE_CREATED = 'application_fee.created'; - const APPLICATION_FEE_REFUNDED = 'application_fee.refunded'; - const APPLICATION_FEE_REFUND_UPDATED = 'application_fee.refund.updated'; - const BALANCE_AVAILABLE = 'balance.available'; - const CHARGE_CAPTURED = 'charge.captured'; - const CHARGE_FAILED = 'charge.failed'; - const CHARGE_PENDING = 'charge.pending'; - const CHARGE_REFUNDED = 'charge.refunded'; - const CHARGE_SUCCEEDED = 'charge.succeeded'; - const CHARGE_UPDATED = 'charge.updated'; - const CHARGE_DISPUTE_CLOSED = 'charge.dispute.closed'; - const CHARGE_DISPUTE_CREATED = 'charge.dispute.created'; - const CHARGE_DISPUTE_FUNDS_REINSTATED = 'charge.dispute.funds_reinstated'; - const CHARGE_DISPUTE_FUNDS_WITHDRAWN = 'charge.dispute.funds_withdrawn'; - const CHARGE_DISPUTE_UPDATED = 'charge.dispute.updated'; - const CHARGE_REFUND_UPDATED = 'charge.refund.updated'; - const COUPON_CREATED = 'coupon.created'; - const COUPON_DELETED = 'coupon.deleted'; - const COUPON_UPDATED = 'coupon.updated'; - const CUSTOMER_CREATED = 'customer.created'; - const CUSTOMER_DELETED = 'customer.deleted'; - const CUSTOMER_UPDATED = 'customer.updated'; - const CUSTOMER_DISCOUNT_CREATED = 'customer.discount.created'; - const CUSTOMER_DISCOUNT_DELETED = 'customer.discount.deleted'; - const CUSTOMER_DISCOUNT_UPDATED = 'customer.discount.updated'; - const CUSTOMER_SOURCE_CREATED = 'customer.source.created'; - const CUSTOMER_SOURCE_DELETED = 'customer.source.deleted'; - const CUSTOMER_SOURCE_EXPIRING = 'customer.source.expiring'; - const CUSTOMER_SOURCE_UPDATED = 'customer.source.updated'; - const CUSTOMER_SUBSCRIPTION_CREATED = 'customer.subscription.created'; - const CUSTOMER_SUBSCRIPTION_DELETED = 'customer.subscription.deleted'; - const CUSTOMER_SUBSCRIPTION_TRIAL_WILL_END = 'customer.subscription.trial_will_end'; - const CUSTOMER_SUBSCRIPTION_UPDATED = 'customer.subscription.updated'; - const FILE_CREATED = 'file.created'; - const INVOICE_CREATED = 'invoice.created'; - const INVOICE_PAYMENT_FAILED = 'invoice.payment_failed'; - const INVOICE_PAYMENT_SUCCEEDED = 'invoice.payment_succeeded'; - const INVOICE_SENT = 'invoice.sent'; - const INVOICE_UPCOMING = 'invoice.upcoming'; - const INVOICE_UPDATED = 'invoice.updated'; - const INVOICEITEM_CREATED = 'invoiceitem.created'; - const INVOICEITEM_DELETED = 'invoiceitem.deleted'; - const INVOICEITEM_UPDATED = 'invoiceitem.updated'; - const ORDER_CREATED = 'order.created'; - const ORDER_PAYMENT_FAILED = 'order.payment_failed'; - const ORDER_PAYMENT_SUCCEEDED = 'order.payment_succeeded'; - const ORDER_UPDATED = 'order.updated'; - const ORDER_RETURN_CREATED = 'order_return.created'; - const PAYOUT_CANCELED = 'payout.canceled'; - const PAYOUT_CREATED = 'payout.created'; - const PAYOUT_FAILED = 'payout.failed'; - const PAYOUT_PAID = 'payout.paid'; - const PAYOUT_UPDATED = 'payout.updated'; - const PING = 'ping'; - const PLAN_CREATED = 'plan.created'; - const PLAN_DELETED = 'plan.deleted'; - const PLAN_UPDATED = 'plan.updated'; - const PRODUCT_CREATED = 'product.created'; - const PRODUCT_DELETED = 'product.deleted'; - const PRODUCT_UPDATED = 'product.updated'; - const RECIPIENT_CREATED = 'recipient.created'; - const RECIPIENT_DELETED = 'recipient.deleted'; - const RECIPIENT_UPDATED = 'recipient.updated'; - const REVIEW_CLOSED = 'review.closed'; - const REVIEW_OPENED = 'review.opened'; - const SIGMA_SCHEDULED_QUERY_RUN_CREATED = 'sigma.scheduled_query_run.created'; - const SKU_CREATED = 'sku.created'; - const SKU_DELETED = 'sku.deleted'; - const SKU_UPDATED = 'sku.updated'; - const SOURCE_CANCELED = 'source.canceled'; - const SOURCE_CHARGEABLE = 'source.chargeable'; - const SOURCE_FAILED = 'source.failed'; - const SOURCE_MANDATE_NOTIFICATION = 'source.mandate_notification'; - const SOURCE_TRANSACTION_CREATED = 'source.transaction.created'; - const TOPUP_CREATED = 'topup.created'; - const TOPUP_FAILED = 'topup.failed'; - const TOPUP_SUCCEEDED = 'topup.succeeded'; - const TRANSFER_CREATED = 'transfer.created'; - const TRANSFER_REVERSED = 'transfer.reversed'; - const TRANSFER_UPDATED = 'transfer.updated'; + const ACCOUNT_UPDATED = 'account.updated'; + const ACCOUNT_APPLICATION_AUTHORIZED = 'account.application.authorized'; + const ACCOUNT_APPLICATION_DEAUTHORIZED = 'account.application.deauthorized'; + const ACCOUNT_EXTERNAL_ACCOUNT_CREATED = 'account.external_account.created'; + const ACCOUNT_EXTERNAL_ACCOUNT_DELETED = 'account.external_account.deleted'; + const ACCOUNT_EXTERNAL_ACCOUNT_UPDATED = 'account.external_account.updated'; + const APPLICATION_FEE_CREATED = 'application_fee.created'; + const APPLICATION_FEE_REFUNDED = 'application_fee.refunded'; + const APPLICATION_FEE_REFUND_UPDATED = 'application_fee.refund.updated'; + const BALANCE_AVAILABLE = 'balance.available'; + const CHARGE_CAPTURED = 'charge.captured'; + const CHARGE_EXPIRED = 'charge.expired'; + const CHARGE_FAILED = 'charge.failed'; + const CHARGE_PENDING = 'charge.pending'; + const CHARGE_REFUNDED = 'charge.refunded'; + const CHARGE_SUCCEEDED = 'charge.succeeded'; + const CHARGE_UPDATED = 'charge.updated'; + const CHARGE_DISPUTE_CLOSED = 'charge.dispute.closed'; + const CHARGE_DISPUTE_CREATED = 'charge.dispute.created'; + const CHARGE_DISPUTE_FUNDS_REINSTATED = 'charge.dispute.funds_reinstated'; + const CHARGE_DISPUTE_FUNDS_WITHDRAWN = 'charge.dispute.funds_withdrawn'; + const CHARGE_DISPUTE_UPDATED = 'charge.dispute.updated'; + const CHARGE_REFUND_UPDATED = 'charge.refund.updated'; + const COUPON_CREATED = 'coupon.created'; + const COUPON_DELETED = 'coupon.deleted'; + const COUPON_UPDATED = 'coupon.updated'; + const CREDIT_NOTE_CREATED = 'credit_note.created'; + const CREDIT_NOTE_UPDATED = 'credit_note.updated'; + const CREDIT_NOTE_VOIDED = 'credit_note.voided'; + const CUSTOMER_CREATED = 'customer.created'; + const CUSTOMER_DELETED = 'customer.deleted'; + const CUSTOMER_UPDATED = 'customer.updated'; + const CUSTOMER_DISCOUNT_CREATED = 'customer.discount.created'; + const CUSTOMER_DISCOUNT_DELETED = 'customer.discount.deleted'; + const CUSTOMER_DISCOUNT_UPDATED = 'customer.discount.updated'; + const CUSTOMER_SOURCE_CREATED = 'customer.source.created'; + const CUSTOMER_SOURCE_DELETED = 'customer.source.deleted'; + const CUSTOMER_SOURCE_EXPIRING = 'customer.source.expiring'; + const CUSTOMER_SOURCE_UPDATED = 'customer.source.updated'; + const CUSTOMER_SUBSCRIPTION_CREATED = 'customer.subscription.created'; + const CUSTOMER_SUBSCRIPTION_DELETED = 'customer.subscription.deleted'; + const CUSTOMER_SUBSCRIPTION_TRIAL_WILL_END = 'customer.subscription.trial_will_end'; + const CUSTOMER_SUBSCRIPTION_UPDATED = 'customer.subscription.updated'; + const FILE_CREATED = 'file.created'; + const INVOICE_CREATED = 'invoice.created'; + const INVOICE_DELETED = 'invoice.deleted'; + const INVOICE_FINALIZED = 'invoice.finalized'; + const INVOICE_MARKED_UNCOLLECTIBLE = 'invoice.marked_uncollectible'; + const INVOICE_PAYMENT_FAILED = 'invoice.payment_failed'; + const INVOICE_PAYMENT_SUCCEEDED = 'invoice.payment_succeeded'; + const INVOICE_SENT = 'invoice.sent'; + const INVOICE_UPCOMING = 'invoice.upcoming'; + const INVOICE_UPDATED = 'invoice.updated'; + const INVOICE_VOIDED = 'invoice.voided'; + const INVOICEITEM_CREATED = 'invoiceitem.created'; + const INVOICEITEM_DELETED = 'invoiceitem.deleted'; + const INVOICEITEM_UPDATED = 'invoiceitem.updated'; + const ISSUER_FRAUD_RECORD_CREATED = 'issuer_fraud_record.created'; + const ISSUING_AUTHORIZATION_CREATED = 'issuing_authorization.created'; + const ISSUING_AUTHORIZATION_UPDATED = 'issuing_authorization.updated'; + const ISSUING_CARD_CREATED = 'issuing_card.created'; + const ISSUING_CARD_UPDATED = 'issuing_card.updated'; + const ISSUING_CARDHOLDER_CREATED = 'issuing_cardholder.created'; + const ISSUING_CARDHOLDER_UPDATED = 'issuing_cardholder.updated'; + const ISSUING_TRANSACTION_CREATED = 'issuing_transaction.created'; + const ISSUING_TRANSACTION_UPDATED = 'issuing_transaction.updated'; + const ORDER_CREATED = 'order.created'; + const ORDER_PAYMENT_FAILED = 'order.payment_failed'; + const ORDER_PAYMENT_SUCCEEDED = 'order.payment_succeeded'; + const ORDER_UPDATED = 'order.updated'; + const ORDER_RETURN_CREATED = 'order_return.created'; + const PAYMENT_INTENT_AMOUNT_CAPTURABLE_UPDATED = 'payment_intent.amount_capturable_updated'; + const PAYMENT_INTENT_CREATED = 'payment_intent.created'; + const PAYMENT_INTENT_PAYMENT_FAILED = 'payment_intent.payment_failed'; + const PAYMENT_INTENT_SUCCEEDED = 'payment_intent.succeeded'; + const PAYOUT_CANCELED = 'payout.canceled'; + const PAYOUT_CREATED = 'payout.created'; + const PAYOUT_FAILED = 'payout.failed'; + const PAYOUT_PAID = 'payout.paid'; + const PAYOUT_UPDATED = 'payout.updated'; + const PERSON_CREATED = 'person.created'; + const PERSON_DELETED = 'person.deleted'; + const PERSON_UPDATED = 'person.updated'; + const PING = 'ping'; + const PLAN_CREATED = 'plan.created'; + const PLAN_DELETED = 'plan.deleted'; + const PLAN_UPDATED = 'plan.updated'; + const PRODUCT_CREATED = 'product.created'; + const PRODUCT_DELETED = 'product.deleted'; + const PRODUCT_UPDATED = 'product.updated'; + const RECIPIENT_CREATED = 'recipient.created'; + const RECIPIENT_DELETED = 'recipient.deleted'; + const RECIPIENT_UPDATED = 'recipient.updated'; + const REPORTING_REPORT_RUN_FAILED = 'reporting.report_run.failed'; + const REPORTING_REPORT_RUN_SUCCEEDED = 'reporting.report_run.succeeded'; + const REPORTING_REPORT_TYPE_UPDATED = 'reporting.report_type.updated'; + const REVIEW_CLOSED = 'review.closed'; + const REVIEW_OPENED = 'review.opened'; + const SIGMA_SCHEDULED_QUERY_RUN_CREATED = 'sigma.scheduled_query_run.created'; + const SKU_CREATED = 'sku.created'; + const SKU_DELETED = 'sku.deleted'; + const SKU_UPDATED = 'sku.updated'; + const SOURCE_CANCELED = 'source.canceled'; + const SOURCE_CHARGEABLE = 'source.chargeable'; + const SOURCE_FAILED = 'source.failed'; + const SOURCE_MANDATE_NOTIFICATION = 'source.mandate_notification'; + const SOURCE_REFUND_ATTRIBUTES_REQUIRED = 'source.refund_attributes_required'; + const SOURCE_TRANSACTION_CREATED = 'source.transaction.created'; + const SOURCE_TRANSACTION_UPDATED = 'source.transaction.updated'; + const SUBSCRIPTION_SCHEDULE_ABORTED = 'subscription_schedule.aborted'; + const SUBSCRIPTION_SCHEDULE_CANCELED = 'subscription_schedule.canceled'; + const SUBSCRIPTION_SCHEDULE_COMPLETED = 'subscription_schedule.completed'; + const SUBSCRIPTION_SCHEDULE_CREATED = 'subscription_schedule.created'; + const SUBSCRIPTION_SCHEDULE_EXPIRING = 'subscription_schedule.expiring'; + const SUBSCRIPTION_SCHEDULE_RELEASED = 'subscription_schedule.released'; + const SUBSCRIPTION_SCHEDULE_UPDATED = 'subscription_schedule.updated'; + const TAX_RATE_CREATED = 'tax_rate.created'; + const TAX_RATE_UPDATED = 'tax_rate.updated'; + const TOPUP_CANCELED = 'topup.canceled'; + const TOPUP_CREATED = 'topup.created'; + const TOPUP_FAILED = 'topup.failed'; + const TOPUP_REVERSED = 'topup.reversed'; + const TOPUP_SUCCEEDED = 'topup.succeeded'; + const TRANSFER_CREATED = 'transfer.created'; + const TRANSFER_REVERSED = 'transfer.reversed'; + const TRANSFER_UPDATED = 'transfer.updated'; use ApiOperations\All; use ApiOperations\Retrieve; diff --git a/htdocs/includes/stripe/lib/ExchangeRate.php b/htdocs/includes/stripe/lib/ExchangeRate.php index 40763261834..803a5f87700 100644 --- a/htdocs/includes/stripe/lib/ExchangeRate.php +++ b/htdocs/includes/stripe/lib/ExchangeRate.php @@ -9,17 +9,9 @@ namespace Stripe; */ class ExchangeRate extends ApiResource { + + const OBJECT_NAME = "exchange_rate"; + use ApiOperations\All; use ApiOperations\Retrieve; - - /** - * This is a special case because the exchange rates endpoint has an - * underscore in it. The parent `className` function strips underscores. - * - * @return string The name of the class. - */ - public static function className() - { - return 'exchange_rate'; - } } diff --git a/htdocs/includes/stripe/lib/File.php b/htdocs/includes/stripe/lib/File.php new file mode 100644 index 00000000000..76109ad38cf --- /dev/null +++ b/htdocs/includes/stripe/lib/File.php @@ -0,0 +1,62 @@ +apiBase)) { + $opts->apiBase = Stripe::$apiUploadBase; + } + // Manually flatten params, otherwise curl's multipart encoder will + // choke on nested arrays. + // TODO: use array_column() once we drop support for PHP 5.4 + $flatParams = []; + foreach (\Stripe\Util\Util::flattenParams($params) as $pair) { + $flatParams[$pair[0]] = $pair[1]; + } + return static::_create($flatParams, $opts); + } +} diff --git a/htdocs/includes/stripe/lib/FileLink.php b/htdocs/includes/stripe/lib/FileLink.php new file mode 100644 index 00000000000..2a012b36105 --- /dev/null +++ b/htdocs/includes/stripe/lib/FileLink.php @@ -0,0 +1,29 @@ +defaultOptions = $defaultOptions; $this->randomGenerator = $randomGenerator ?: new Util\RandomGenerator(); $this->initUserAgentInfo(); + + // TODO: curl_reset requires PHP >= 5.5.0. Once we drop support for PHP 5.4, we can simply + // initialize this to true. + $this->enablePersistentConnections = function_exists('curl_reset'); + + $this->enableHttp2 = $this->canSafelyUseHttp2(); + } + + public function __destruct() + { + $this->closeCurlHandle(); } public function initUserAgentInfo() @@ -77,6 +98,38 @@ class CurlClient implements ClientInterface return $this->userAgentInfo; } + /** + * @return boolean + */ + public function getEnablePersistentConnections() + { + return $this->enablePersistentConnections; + } + + /** + * @param boolean $enable + */ + public function setEnablePersistentConnections($enable) + { + $this->enablePersistentConnections = $enable; + } + + /** + * @return boolean + */ + public function getEnableHttp2() + { + return $this->enableHttp2; + } + + /** + * @param boolean $enable + */ + public function setEnableHttp2($enable) + { + $this->enableHttp2 = $enable; + } + // USER DEFINED TIMEOUTS const DEFAULT_TIMEOUT = 80; @@ -123,6 +176,8 @@ class CurlClient implements ClientInterface $opts = $this->defaultOptions; } + $params = Util\Util::objectsToIds($params); + if ($method == 'get') { if ($hasFile) { throw new Error\Api( @@ -131,16 +186,16 @@ class CurlClient implements ClientInterface } $opts[CURLOPT_HTTPGET] = 1; if (count($params) > 0) { - $encoded = Util\Util::urlEncode($params); + $encoded = Util\Util::encodeParameters($params); $absUrl = "$absUrl?$encoded"; } } elseif ($method == 'post') { $opts[CURLOPT_POST] = 1; - $opts[CURLOPT_POSTFIELDS] = $hasFile ? $params : Util\Util::urlEncode($params); + $opts[CURLOPT_POSTFIELDS] = $hasFile ? $params : Util\Util::encodeParameters($params); } elseif ($method == 'delete') { $opts[CURLOPT_CUSTOMREQUEST] = 'DELETE'; if (count($params) > 0) { - $encoded = Util\Util::urlEncode($params); + $encoded = Util\Util::encodeParameters($params); $absUrl = "$absUrl?$encoded"; } } else { @@ -150,13 +205,13 @@ class CurlClient implements ClientInterface // It is only safe to retry network failures on POST requests if we // add an Idempotency-Key header if (($method == 'post') && (Stripe::$maxNetworkRetries > 0)) { - if (!isset($headers['Idempotency-Key'])) { + if (!$this->hasHeader($headers, "Idempotency-Key")) { array_push($headers, 'Idempotency-Key: ' . $this->randomGenerator->uuid()); } } // Create a callback to capture HTTP headers for the response - $rheaders = []; + $rheaders = new Util\CaseInsensitiveArray(); $headerCallback = function ($curl, $header_line) use (&$rheaders) { // Ignore the HTTP request line (HTTP/1.1 200 OK) if (strpos($header_line, ":") === false) { @@ -193,6 +248,11 @@ class CurlClient implements ClientInterface $opts[CURLOPT_SSL_VERIFYPEER] = false; } + if (!isset($opts[CURLOPT_HTTP_VERSION]) && $this->getEnableHttp2()) { + // For HTTPS requests, enable HTTP/2, if supported + $opts[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2TLS; + } + list($rbody, $rcode) = $this->executeRequestWithRetries($opts, $absUrl); return [$rbody, $rcode, $rheaders]; @@ -209,17 +269,19 @@ class CurlClient implements ClientInterface $rcode = 0; $errno = 0; - $curl = curl_init(); - curl_setopt_array($curl, $opts); - $rbody = curl_exec($curl); + $this->resetCurlHandle(); + curl_setopt_array($this->curlHandle, $opts); + $rbody = curl_exec($this->curlHandle); if ($rbody === false) { - $errno = curl_errno($curl); - $message = curl_error($curl); + $errno = curl_errno($this->curlHandle); + $message = curl_error($this->curlHandle); } else { - $rcode = curl_getinfo($curl, CURLINFO_HTTP_CODE); + $rcode = curl_getinfo($this->curlHandle, CURLINFO_HTTP_CODE); + } + if (!$this->getEnablePersistentConnections()) { + $this->closeCurlHandle(); } - curl_close($curl); if ($this->shouldRetry($errno, $rcode, $numRetries)) { $numRetries += 1; @@ -331,4 +393,68 @@ class CurlClient implements ClientInterface return $sleepSeconds; } + + /** + * Initializes the curl handle. If already initialized, the handle is closed first. + */ + private function initCurlHandle() + { + $this->closeCurlHandle(); + $this->curlHandle = curl_init(); + } + + /** + * Closes the curl handle if initialized. Do nothing if already closed. + */ + private function closeCurlHandle() + { + if (!is_null($this->curlHandle)) { + curl_close($this->curlHandle); + $this->curlHandle = null; + } + } + + /** + * Resets the curl handle. If the handle is not already initialized, or if persistent + * connections are disabled, the handle is reinitialized instead. + */ + private function resetCurlHandle() + { + if (!is_null($this->curlHandle) && $this->getEnablePersistentConnections()) { + curl_reset($this->curlHandle); + } else { + $this->initCurlHandle(); + } + } + + /** + * Indicates whether it is safe to use HTTP/2 or not. + * + * @return boolean + */ + private function canSafelyUseHttp2() + { + // Versions of curl older than 7.60.0 don't respect GOAWAY frames + // (cf. https://github.com/curl/curl/issues/2416), which Stripe use. + $curlVersion = curl_version()['version']; + return (version_compare($curlVersion, '7.60.0') >= 0); + } + + /** + * Checks if a list of headers contains a specific header name. + * + * @param string[] $headers + * @param string $name + * @return boolean + */ + private function hasHeader($headers, $name) + { + foreach ($headers as $header) { + if (strncasecmp($header, "{$name}: ", strlen($name) + 2) === 0) { + return true; + } + } + + return false; + } } diff --git a/htdocs/includes/stripe/lib/Invoice.php b/htdocs/includes/stripe/lib/Invoice.php index 07d67f74a8a..6e0ec9d6b6c 100644 --- a/htdocs/includes/stripe/lib/Invoice.php +++ b/htdocs/includes/stripe/lib/Invoice.php @@ -7,51 +7,161 @@ namespace Stripe; * * @property string $id * @property string $object + * @property string $account_country + * @property string $account_name * @property int $amount_due * @property int $amount_paid * @property int $amount_remaining - * @property int $application_fee + * @property int $application_fee_amount * @property int $attempt_count * @property bool $attempted + * @property bool $auto_advance * @property string $billing + * @property string $billing_reason * @property string $charge - * @property bool $closed + * @property int $created * @property string $currency + * @property array $custom_fields * @property string $customer - * @property int $date + * @property mixed $customer_address + * @property string $customer_email + * @property string $customer_name + * @property string $customer_phone + * @property mixed $customer_shipping + * @property array $customer_tax_ids + * @property string $default_payment_method + * @property string $default_source + * @property array $default_tax_rates * @property string $description - * @property mixed $discount + * @property Discount $discount * @property int $due_date * @property int $ending_balance - * @property bool $forgiven + * @property string $footer + * @property string $hosted_invoice_url + * @property string $invoice_pdf * @property Collection $lines * @property bool $livemode * @property StripeObject $metadata * @property int $next_payment_attempt * @property string $number * @property bool $paid + * @property string $payment_intent * @property int $period_end * @property int $period_start + * @property int $post_payment_credit_notes_amount + * @property int $pre_payment_credit_notes_amount * @property string $receipt_number * @property int $starting_balance * @property string $statement_descriptor + * @property string $status + * @property mixed $status_transitions * @property string $subscription * @property int $subscription_proration_date * @property int $subtotal * @property int $tax - * @property float $tax_percent + * @property mixed $threshold_reason * @property int $total + * @property array $total_tax_amounts * @property int $webhooks_delivered_at * * @package Stripe */ class Invoice extends ApiResource { + + const OBJECT_NAME = "invoice"; + use ApiOperations\All; use ApiOperations\Create; + use ApiOperations\Delete; use ApiOperations\Retrieve; use ApiOperations\Update; + /** + * Possible string representations of the invoice status. + * @link https://stripe.com/docs/api/invoices/object#invoice_object-status + */ + const STATUS_DRAFT = 'draft'; + const STATUS_OPEN = 'open'; + const STATUS_PAID = 'paid'; + const STATUS_UNCOLLECTIBLE = 'uncollectible'; + const STATUS_VOID = 'void'; + + /** + * Possible string representations of the billing. + * @link https://stripe.com/docs/api/invoices/object#invoice_object-billing + */ + const BILLING_SEND_INVOICE = 'send_invoice'; + const BILLING_CHARGE_AUTOMATICALLY = 'charge_automatically'; + + /** + * Possible string representations of the billing reason. + * @link https://stripe.com/docs/api/invoices/object#invoice_object-billing_reason + */ + const BILLING_REASON_SUBSCRIPTION = 'subscription'; + const BILLING_REASON_SUBSCRIPTION_CREATE = 'subscription_create'; + const BILLING_REASON_SUBSCRIPTION_CYCLE = 'subscription_cycle'; + const BILLING_REASON_SUBSCRIPTION_UPDATE = 'subscription_update'; + const BILLING_REASON_SUBSCRIPTION_THRESHOLD = 'subscription_threshold'; + const BILLING_REASON_MANUAL = 'manual'; + const BILLING_REASON_UPCOMING = 'upcoming'; + + /** + * @param array|null $params + * @param array|string|null $opts + * + * @return Invoice The finalized invoice. + */ + public function finalizeInvoice($params = null, $opts = null) + { + $url = $this->instanceUrl() . '/finalize'; + list($response, $opts) = $this->_request('post', $url, $params, $opts); + $this->refreshFrom($response, $opts); + return $this; + } + + /** + * @param array|null $params + * @param array|string|null $opts + * + * @return Invoice The uncollectible invoice. + */ + public function markUncollectible($params = null, $opts = null) + { + $url = $this->instanceUrl() . '/mark_uncollectible'; + list($response, $opts) = $this->_request('post', $url, $params, $opts); + $this->refreshFrom($response, $opts); + return $this; + } + + /** + * @param array|null $params + * @param array|string|null $opts + * + * @return Invoice The paid invoice. + */ + public function pay($params = null, $opts = null) + { + $url = $this->instanceUrl() . '/pay'; + list($response, $opts) = $this->_request('post', $url, $params, $opts); + $this->refreshFrom($response, $opts); + return $this; + } + + /** + * @param array|null $params + * @param array|string|null $opts + * + * @return Invoice The sent invoice. + */ + public function sendInvoice($params = null, $opts = null) + { + $url = $this->instanceUrl() . '/send'; + list($response, $opts) = $this->_request('post', $url, $params, $opts); + $this->refreshFrom($response, $opts); + return $this; + } + /** * @param array|null $params * @param array|string|null $opts @@ -68,11 +178,14 @@ class Invoice extends ApiResource } /** - * @return Invoice The paid invoice. + * @param array|null $params + * @param array|string|null $opts + * + * @return Invoice The voided invoice. */ - public function pay($params = null, $opts = null) + public function voidInvoice($params = null, $opts = null) { - $url = $this->instanceUrl() . '/pay'; + $url = $this->instanceUrl() . '/void'; list($response, $opts) = $this->_request('post', $url, $params, $opts); $this->refreshFrom($response, $opts); return $this; diff --git a/htdocs/includes/stripe/lib/InvoiceItem.php b/htdocs/includes/stripe/lib/InvoiceItem.php index 37e39f3e105..02ca0f2d7ee 100644 --- a/htdocs/includes/stripe/lib/InvoiceItem.php +++ b/htdocs/includes/stripe/lib/InvoiceItem.php @@ -22,11 +22,16 @@ namespace Stripe; * @property int $quantity * @property string $subscription * @property string $subscription_item + * @property array $tax_rates + * @property int $unit_amount * * @package Stripe */ class InvoiceItem extends ApiResource { + + const OBJECT_NAME = "invoiceitem"; + use ApiOperations\All; use ApiOperations\Create; use ApiOperations\Delete; diff --git a/htdocs/includes/stripe/lib/InvoiceLineItem.php b/htdocs/includes/stripe/lib/InvoiceLineItem.php new file mode 100644 index 00000000000..e8e8c881d5a --- /dev/null +++ b/htdocs/includes/stripe/lib/InvoiceLineItem.php @@ -0,0 +1,32 @@ +instanceUrl() . '/approve'; + list($response, $opts) = $this->_request('post', $url, $params, $options); + $this->refreshFrom($response, $opts); + return $this; + } + + /** + * @param array|null $params + * @param array|string|null $options + * + * @return Authorization The declined authorization. + */ + public function decline($params = null, $options = null) + { + $url = $this->instanceUrl() . '/decline'; + list($response, $opts) = $this->_request('post', $url, $params, $options); + $this->refreshFrom($response, $opts); + return $this; + } +} diff --git a/htdocs/includes/stripe/lib/Issuing/Card.php b/htdocs/includes/stripe/lib/Issuing/Card.php new file mode 100644 index 00000000000..60cc5b4e1bf --- /dev/null +++ b/htdocs/includes/stripe/lib/Issuing/Card.php @@ -0,0 +1,51 @@ +instanceUrl() . '/details'; + list($response, $opts) = $this->_request('get', $url, $params, $options); + $obj = \Stripe\Util\Util::convertToStripeObject($response, $opts); + $obj->setLastResponse($response); + return $obj; + } +} diff --git a/htdocs/includes/stripe/lib/Issuing/CardDetails.php b/htdocs/includes/stripe/lib/Issuing/CardDetails.php new file mode 100644 index 00000000000..65d3919caa4 --- /dev/null +++ b/htdocs/includes/stripe/lib/Issuing/CardDetails.php @@ -0,0 +1,21 @@ +instanceUrl() . '/cancel'; + list($response, $opts) = $this->_request('post', $url, $params, $options); + $this->refreshFrom($response, $opts); + return $this; + } + + /** + * @param array|null $params + * @param array|string|null $options + * + * @return PaymentIntent The captured payment intent. + */ + public function capture($params = null, $options = null) + { + $url = $this->instanceUrl() . '/capture'; + list($response, $opts) = $this->_request('post', $url, $params, $options); + $this->refreshFrom($response, $opts); + return $this; + } + + /** + * @param array|null $params + * @param array|string|null $options + * + * @return PaymentIntent The confirmed payment intent. + */ + public function confirm($params = null, $options = null) + { + $url = $this->instanceUrl() . '/confirm'; + list($response, $opts) = $this->_request('post', $url, $params, $options); + $this->refreshFrom($response, $opts); + return $this; + } +} diff --git a/htdocs/includes/stripe/lib/PaymentMethod.php b/htdocs/includes/stripe/lib/PaymentMethod.php new file mode 100644 index 00000000000..1a0bc371d5d --- /dev/null +++ b/htdocs/includes/stripe/lib/PaymentMethod.php @@ -0,0 +1,60 @@ +instanceUrl() . '/attach'; + list($response, $opts) = $this->_request('post', $url, $params, $opts); + $this->refreshFrom($response, $opts); + return $this; + } + + /** + * @param array|null $params + * @param array|string|null $opts + * + * @return PaymentMethod The detached payment method. + */ + public function detach($params = null, $opts = null) + { + $url = $this->instanceUrl() . '/detach'; + list($response, $opts) = $this->_request('post', $url, $params, $opts); + $this->refreshFrom($response, $opts); + return $this; + } +} diff --git a/htdocs/includes/stripe/lib/Payout.php b/htdocs/includes/stripe/lib/Payout.php index 0849cae3f61..365d7e47ee9 100644 --- a/htdocs/includes/stripe/lib/Payout.php +++ b/htdocs/includes/stripe/lib/Payout.php @@ -8,18 +8,19 @@ namespace Stripe; * @property string $id * @property string $object * @property int $amount + * @property int $arrival_date + * @property bool $automatic * @property string $balance_transaction - * @property string $cancellation_balance_transaction * @property int $created * @property string $currency - * @property int $arrival_date + * @property string $description * @property string $destination + * @property string $failure_balance_transaction * @property string $failure_code * @property string $failure_message * @property bool $livemode * @property StripeObject $metadata * @property string $method - * @property string $recipient * @property string $source_type * @property string $statement_descriptor * @property string $status @@ -29,11 +30,56 @@ namespace Stripe; */ class Payout extends ApiResource { + + const OBJECT_NAME = "payout"; + use ApiOperations\All; use ApiOperations\Create; use ApiOperations\Retrieve; use ApiOperations\Update; + /** + * Types of payout failure codes. + * @link https://stripe.com/docs/api#payout_failures + */ + const FAILURE_ACCOUNT_CLOSED = 'account_closed'; + const FAILURE_ACCOUNT_FROZEN = 'account_frozen'; + const FAILURE_BANK_ACCOUNT_RESTRICTED = 'bank_account_restricted'; + const FAILURE_BANK_OWNERSHIP_CHANGED = 'bank_ownership_changed'; + const FAILURE_COULD_NOT_PROCESS = 'could_not_process'; + const FAILURE_DEBIT_NOT_AUTHORIZED = 'debit_not_authorized'; + const FAILURE_DECLINED = 'declined'; + const FAILURE_INCORRECT_ACCOUNT_HOLDER_NAME = 'incorrect_account_holder_name'; + const FAILURE_INSUFFICIENT_FUNDS = 'insufficient_funds'; + const FAILURE_INVALID_ACCOUNT_NUMBER = 'invalid_account_number'; + const FAILURE_INVALID_CURRENCY = 'invalid_currency'; + const FAILURE_NO_ACCOUNT = 'no_account'; + const FAILURE_UNSUPPORTED_CARD = 'unsupported_card'; + + /** + * Possible string representations of the payout methods. + * @link https://stripe.com/docs/api/payouts/object#payout_object-method + */ + const METHOD_STANDARD = 'standard'; + const METHOD_INSTANT = 'instant'; + + /** + * Possible string representations of the status of the payout. + * @link https://stripe.com/docs/api/payouts/object#payout_object-status + */ + const STATUS_CANCELED = 'canceled'; + const STATUS_IN_TRANSIT = 'in_transit'; + const STATUS_FAILED = 'failed'; + const STATUS_PAID = 'paid'; + const STATUS_PENDING = 'pending'; + + /** + * Possible string representations of the type of payout. + * @link https://stripe.com/docs/api/payouts/object#payout_object-type + */ + const TYPE_BANK_ACCOUNT = 'bank_account'; + const TYPE_CARD = 'card'; + /** * @return Payout The canceled payout. */ diff --git a/htdocs/includes/stripe/lib/Person.php b/htdocs/includes/stripe/lib/Person.php new file mode 100644 index 00000000000..56241c4c426 --- /dev/null +++ b/htdocs/includes/stripe/lib/Person.php @@ -0,0 +1,108 @@ +retrievePerson('person_id') instead."; + throw new Error\InvalidRequest($msg, null); + } + + /** + * @param string $_id + * @param array|null $_params + * @param array|string|null $_options + * + * @throws \Stripe\Error\InvalidRequest + */ + public static function update($_id, $_params = null, $_options = null) + { + $msg = "Persons cannot be accessed without an account ID. " . + "Retrieve a Person using \$account->retrievePerson('person_id') instead."; + throw new Error\InvalidRequest($msg, null); + } +} diff --git a/htdocs/includes/stripe/lib/Plan.php b/htdocs/includes/stripe/lib/Plan.php index 8b0126b6f2d..54a2b58eb35 100644 --- a/htdocs/includes/stripe/lib/Plan.php +++ b/htdocs/includes/stripe/lib/Plan.php @@ -9,7 +9,10 @@ namespace Stripe; * * @property string $id * @property string $object + * @property bool $active + * @property string $aggregate_usage * @property int $amount + * @property string $billing_scheme * @property int $created * @property string $currency * @property string $interval @@ -18,10 +21,17 @@ namespace Stripe; * @property StripeObject $metadata * @property string $nickname * @property string $product + * @property mixed $tiers + * @property string $tiers_mode + * @property mixed $transform_usage * @property int $trial_period_days + * @property string $usage_type */ class Plan extends ApiResource { + + const OBJECT_NAME = "plan"; + use ApiOperations\All; use ApiOperations\Create; use ApiOperations\Delete; diff --git a/htdocs/includes/stripe/lib/Product.php b/htdocs/includes/stripe/lib/Product.php index 20bd4e1ae44..cb27ef42d8c 100644 --- a/htdocs/includes/stripe/lib/Product.php +++ b/htdocs/includes/stripe/lib/Product.php @@ -13,15 +13,15 @@ namespace Stripe; * @property int $created * @property string[] $deactivate_on * @property string $description - * @property array $images + * @property string[] $images * @property bool $livemode * @property StripeObject $metadata * @property string $name * @property mixed $package_dimensions * @property bool $shippable - * @property Collection $skus * @property string $statement_descriptor * @property string $type + * @property string $unit_label * @property int $updated * @property string $url * @@ -29,9 +29,19 @@ namespace Stripe; */ class Product extends ApiResource { + + const OBJECT_NAME = "product"; + use ApiOperations\All; use ApiOperations\Create; use ApiOperations\Delete; use ApiOperations\Retrieve; use ApiOperations\Update; + + /** + * Possible string representations of the type of product. + * @link https://stripe.com/docs/api/service_products/object#service_product_object-type + */ + const TYPE_GOOD = 'good'; + const TYPE_SERVICE = 'service'; } diff --git a/htdocs/includes/stripe/lib/Radar/ValueList.php b/htdocs/includes/stripe/lib/Radar/ValueList.php new file mode 100644 index 00000000000..d267429b272 --- /dev/null +++ b/htdocs/includes/stripe/lib/Radar/ValueList.php @@ -0,0 +1,32 @@ +requestId = $requestId; + $this->requestDuration = $requestDuration; + } +} diff --git a/htdocs/includes/stripe/lib/Review.php b/htdocs/includes/stripe/lib/Review.php new file mode 100644 index 00000000000..a2fd5d06db3 --- /dev/null +++ b/htdocs/includes/stripe/lib/Review.php @@ -0,0 +1,57 @@ +instanceUrl() . '/approve'; + list($response, $opts) = $this->_request('post', $url, $params, $options); + $this->refreshFrom($response, $opts); + return $this; + } +} diff --git a/htdocs/includes/stripe/lib/SKU.php b/htdocs/includes/stripe/lib/SKU.php index 1f35da4c759..5b50df8a847 100644 --- a/htdocs/includes/stripe/lib/SKU.php +++ b/htdocs/includes/stripe/lib/SKU.php @@ -24,6 +24,9 @@ namespace Stripe; */ class SKU extends ApiResource { + + const OBJECT_NAME = "sku"; + use ApiOperations\All; use ApiOperations\Create; use ApiOperations\Delete; diff --git a/htdocs/includes/stripe/lib/Sigma/ScheduledQueryRun.php b/htdocs/includes/stripe/lib/Sigma/ScheduledQueryRun.php new file mode 100644 index 00000000000..4d97bf7ce28 --- /dev/null +++ b/htdocs/includes/stripe/lib/Sigma/ScheduledQueryRun.php @@ -0,0 +1,33 @@ + "old_value"] + * + * If we update the object with `metadata[new]=new_value`, the server side + * object now has *both* fields: + * + * metadata = ["old" => "old_value", "new" => "new_value"] + * + * This is okay in itself because usually users will want to treat it as + * additive: + * + * $obj->metadata["new"] = "new_value"; + * $obj->save(); + * + * However, in other cases, they may want to replace the entire existing + * contents: + * + * $obj->metadata = ["new" => "new_value"]; + * $obj->save(); + * + * This is where things get a little bit tricky because in order to clear + * any old keys that may have existed, we actually have to send an explicit + * empty string to the server. So the operation above would have to send + * this form to get the intended behavior: + * + * metadata[old]=&metadata[new]=new_value + * + * This method allows us to track which parameters are considered additive, + * and lets us behave correctly where appropriate when serializing + * parameters to be sent. + * + * @return Util\Set Set of additive parameters + */ + public static function getAdditiveParams() + { + static $additiveParams = null; + if ($additiveParams === null) { + // Set `metadata` as additive so that when it's set directly we remember + // to clear keys that may have been previously set by sending empty + // values for them. + // + // It's possible that not every object has `metadata`, but having this + // option set when there is no `metadata` field is not harmful. + $additiveParams = new Util\Set([ + 'metadata', + ]); + } + return $additiveParams; + } + public function __construct($id = null, $opts = null) { list($id, $this->_retrieveOptions) = Util\Util::normalizeId($id); @@ -153,7 +220,7 @@ class StripeObject implements \ArrayAccess, \Countable, \JsonSerializable * @param array $values * @param null|string|array|Util\RequestOptions $opts * - * @return StripeObject The object constructed from the given values. + * @return static The object constructed from the given values. */ public static function constructFrom($values, $opts = null) { @@ -213,7 +280,7 @@ class StripeObject implements \ArrayAccess, \Countable, \JsonSerializable // This is necessary in case metadata is empty, as PHP arrays do // not differentiate between lists and hashes, and we consider // empty arrays to be lists. - if ($k === "metadata") { + if (($k === "metadata") && (is_array($v))) { $this->_values[$k] = StripeObject::constructFrom($v, $opts); } else { $this->_values[$k] = Util\Util::convertToStripeObject($v, $opts); @@ -323,7 +390,7 @@ class StripeObject implements \ArrayAccess, \Countable, \JsonSerializable } } elseif ($value instanceof StripeObject) { $update = $value->serializeParameters($force); - if ($original && $unsaved) { + if ($original && $unsaved && $key && static::getAdditiveParams()->includes($key)) { $update = array_merge(self::emptyValues($original), $update); } return $update; @@ -432,12 +499,25 @@ class StripeObject implements \ArrayAccess, \Countable, \JsonSerializable } /** - * @param ApiResponse + * Sets the last response from the Stripe API * - * @return void Set the last response from the Stripe API + * @param ApiResponse $resp + * @return void */ public function setLastResponse($resp) { $this->_lastResponse = $resp; } + + /** + * Indicates whether or not the resource has been deleted on the server. + * Note that some, but not all, resources can indicate whether they have + * been deleted. + * + * @return bool Whether the resource is deleted. + */ + public function isDeleted() + { + return isset($this->_values['deleted']) ? $this->_values['deleted'] : false; + } } diff --git a/htdocs/includes/stripe/lib/Subscription.php b/htdocs/includes/stripe/lib/Subscription.php index a5a8da1beb5..8b57d46b625 100644 --- a/htdocs/includes/stripe/lib/Subscription.php +++ b/htdocs/includes/stripe/lib/Subscription.php @@ -9,20 +9,27 @@ namespace Stripe; * @property string $object * @property float $application_fee_percent * @property string $billing + * @property int $billing_cycle_anchor + * @property mixed $billing_thresholds * @property bool $cancel_at_period_end * @property int $canceled_at * @property int $created - * @property int current_period_end - * @property int current_period_start + * @property int $current_period_end + * @property int $current_period_start * @property string $customer * @property int $days_until_due - * @property mixed $discount + * @property string $default_payment_method + * @property string $default_source + * @property array $default_tax_rates + * @property Discount $discount * @property int $ended_at * @property Collection $items + * @property string $latest_invoice * @property boolean $livemode * @property StripeObject $metadata * @property Plan $plan * @property int $quantity + * @property SubscriptionSchedule $schedule * @property int $start * @property string $status * @property float $tax_percent @@ -33,6 +40,9 @@ namespace Stripe; */ class Subscription extends ApiResource { + + const OBJECT_NAME = "subscription"; + use ApiOperations\All; use ApiOperations\Create; use ApiOperations\Delete { @@ -46,11 +56,13 @@ class Subscription extends ApiResource * * @link https://stripe.com/docs/api#subscription_object-status */ - const STATUS_ACTIVE = 'active'; - const STATUS_CANCELED = 'canceled'; - const STATUS_PAST_DUE = 'past_due'; - const STATUS_TRIALING = 'trialing'; - const STATUS_UNPAID = 'unpaid'; + const STATUS_ACTIVE = 'active'; + const STATUS_CANCELED = 'canceled'; + const STATUS_PAST_DUE = 'past_due'; + const STATUS_TRIALING = 'trialing'; + const STATUS_UNPAID = 'unpaid'; + const STATUS_INCOMPLETE = 'incomplete'; + const STATUS_INCOMPLETE_EXPIRED = 'incomplete_expired'; public static function getSavedNestedResources() { @@ -82,13 +94,4 @@ class Subscription extends ApiResource list($response, $opts) = $this->_request('delete', $url); $this->refreshFrom(['discount' => null], $opts, true); } - - public function serializeParameters($force = false) - { - $update = parent::serializeParameters($force); - if ($this->_unsavedValues->includes('items')) { - $update['items'] = $this->serializeParamsValue($this->items, null, true, $force, 'items'); - } - return $update; - } } diff --git a/htdocs/includes/stripe/lib/SubscriptionItem.php b/htdocs/includes/stripe/lib/SubscriptionItem.php index 9efc726aa66..5baa540fe98 100644 --- a/htdocs/includes/stripe/lib/SubscriptionItem.php +++ b/htdocs/includes/stripe/lib/SubscriptionItem.php @@ -7,16 +7,21 @@ namespace Stripe; * * @property string $id * @property string $object + * @property mixed $billing_thresholds * @property int $created * @property StripeObject $metadata * @property Plan $plan * @property int $quantity * @property string $subscription + * @property array $tax_rates * * @package Stripe */ class SubscriptionItem extends ApiResource { + + const OBJECT_NAME = "subscription_item"; + use ApiOperations\All; use ApiOperations\Create; use ApiOperations\Delete; @@ -24,13 +29,17 @@ class SubscriptionItem extends ApiResource use ApiOperations\Update; /** - * This is a special case because the subscription items endpoint has an - * underscore in it. The parent `className` function strips underscores. + * @param array|null $params + * @param array|string|null $options * - * @return string The name of the class. + * @return Collection The list of source transactions. */ - public static function className() + public function usageRecordSummaries($params = null, $options = null) { - return 'subscription_item'; + $url = $this->instanceUrl() . '/usage_record_summaries'; + list($response, $opts) = $this->_request('get', $url, $params, $options); + $obj = Util\Util::convertToStripeObject($response, $opts); + $obj->setLastResponse($response); + return $obj; } } diff --git a/htdocs/includes/stripe/lib/SubscriptionSchedule.php b/htdocs/includes/stripe/lib/SubscriptionSchedule.php new file mode 100644 index 00000000000..ac3686f1db8 --- /dev/null +++ b/htdocs/includes/stripe/lib/SubscriptionSchedule.php @@ -0,0 +1,111 @@ +instanceUrl() . '/cancel'; + list($response, $opts) = $this->_request('post', $url, $params, $opts); + $this->refreshFrom($response, $opts); + return $this; + } + + /** + * @param array|null $params + * @param array|string|null $opts + * + * @return SubscriptionSchedule The released subscription schedule. + */ + public function release($params = null, $opts = null) + { + $url = $this->instanceUrl() . '/release'; + list($response, $opts) = $this->_request('post', $url, $params, $opts); + $this->refreshFrom($response, $opts); + return $this; + } + + /** + * @param array|null $params + * @param array|string|null $options + * + * @return Collection The list of subscription schedule revisions. + */ + public function revisions($params = null, $options = null) + { + $url = $this->instanceUrl() . '/revisions'; + list($response, $opts) = $this->_request('get', $url, $params, $options); + $obj = Util\Util::convertToStripeObject($response, $opts); + $obj->setLastResponse($response); + return $obj; + } + + /** + * @param array|null $id The ID of the subscription schedule to which the person belongs. + * @param array|null $personId The ID of the person to retrieve. + * @param array|null $params + * @param array|string|null $opts + * + * @return Revision + */ + public static function retrieveRevision($id, $personId, $params = null, $opts = null) + { + return self::_retrieveNestedResource($id, static::PATH_REVISIONS, $personId, $params, $opts); + } + + /** + * @param array|null $id The ID of the subscription schedule on which to retrieve the persons. + * @param array|null $params + * @param array|string|null $opts + * + * @return Collection The list of revisions. + */ + public static function allRevisions($id, $params = null, $opts = null) + { + return self::_allNestedResources($id, static::PATH_REVISIONS, $params, $opts); + } +} diff --git a/htdocs/includes/stripe/lib/SubscriptionScheduleRevision.php b/htdocs/includes/stripe/lib/SubscriptionScheduleRevision.php new file mode 100644 index 00000000000..12177236530 --- /dev/null +++ b/htdocs/includes/stripe/lib/SubscriptionScheduleRevision.php @@ -0,0 +1,77 @@ +retrieveRevision('revision_id') instead."; + throw new Error\InvalidRequest($msg, null); + } + + /** + * @param array|string $_id + * @param array|string|null $_opts + * + * @throws \Stripe\Error\InvalidRequest + */ + public static function all($params = null, $opts = null) + { + $msg = "Subscription Schedule Revisions cannot be listed without a Subscription Schedule ID. " . + "List those using \$schedule->allRevisions('revision_id') instead."; + throw new Error\InvalidRequest($msg, null); + } +} diff --git a/htdocs/includes/stripe/lib/TaxId.php b/htdocs/includes/stripe/lib/TaxId.php new file mode 100644 index 00000000000..2993e2d1375 --- /dev/null +++ b/htdocs/includes/stripe/lib/TaxId.php @@ -0,0 +1,80 @@ +instanceUrl() . '/cancel'; + list($response, $opts) = $this->_request('post', $url, $params, $options); + $this->refreshFrom($response, $opts); + return $this; + } } diff --git a/htdocs/includes/stripe/lib/Transfer.php b/htdocs/includes/stripe/lib/Transfer.php index 87d8b79cbf3..dff2faa3329 100644 --- a/htdocs/includes/stripe/lib/Transfer.php +++ b/htdocs/includes/stripe/lib/Transfer.php @@ -12,6 +12,7 @@ namespace Stripe; * @property string $balance_transaction * @property int $created * @property string $currency + * @property string $description * @property string $destination * @property string $destination_payment * @property bool $livemode @@ -26,6 +27,9 @@ namespace Stripe; */ class Transfer extends ApiResource { + + const OBJECT_NAME = "transfer"; + use ApiOperations\All; use ApiOperations\Create; use ApiOperations\NestedResource; @@ -34,6 +38,15 @@ class Transfer extends ApiResource const PATH_REVERSALS = '/reversals'; + /** + * Possible string representations of the source type of the transfer. + * @link https://stripe.com/docs/api/transfers/object#transfer_object-source_type + */ + const SOURCE_TYPE_ALIPAY_ACCOUNT = 'alipay_account'; + const SOURCE_TYPE_BANK_ACCOUNT = 'bank_account'; + const SOURCE_TYPE_CARD = 'card'; + const SOURCE_TYPE_FINANCING = 'financing'; + /** * @return TransferReversal The created transfer reversal. */ @@ -57,7 +70,7 @@ class Transfer extends ApiResource } /** - * @param array|null $id The ID of the transfer on which to create the reversal. + * @param string|null $id The ID of the transfer on which to create the reversal. * @param array|null $params * @param array|string|null $opts * @@ -69,7 +82,7 @@ class Transfer extends ApiResource } /** - * @param array|null $id The ID of the transfer to which the reversal belongs. + * @param string|null $id The ID of the transfer to which the reversal belongs. * @param array|null $reversalId The ID of the reversal to retrieve. * @param array|null $params * @param array|string|null $opts @@ -82,7 +95,7 @@ class Transfer extends ApiResource } /** - * @param array|null $id The ID of the transfer to which the reversal belongs. + * @param string|null $id The ID of the transfer to which the reversal belongs. * @param array|null $reversalId The ID of the reversal to update. * @param array|null $params * @param array|string|null $opts @@ -95,11 +108,11 @@ class Transfer extends ApiResource } /** - * @param array|null $id The ID of the transfer on which to retrieve the reversals. + * @param string|null $id The ID of the transfer on which to retrieve the reversals. * @param array|null $params * @param array|string|null $opts * - * @return TransferReversal + * @return Collection The list of reversals. */ public static function allReversals($id, $params = null, $opts = null) { diff --git a/htdocs/includes/stripe/lib/TransferReversal.php b/htdocs/includes/stripe/lib/TransferReversal.php index cf2a3946d85..c945e5a9360 100644 --- a/htdocs/includes/stripe/lib/TransferReversal.php +++ b/htdocs/includes/stripe/lib/TransferReversal.php @@ -11,13 +11,18 @@ namespace Stripe; * @property string $balance_transaction * @property int $created * @property string $currency + * @property string $destination_payment_refund * @property StripeObject $metadata + * @property string $source_refund * @property string $transfer * * @package Stripe */ class TransferReversal extends ApiResource { + + const OBJECT_NAME = "transfer_reversal"; + use ApiOperations\Update { save as protected _save; } diff --git a/htdocs/includes/stripe/lib/UsageRecord.php b/htdocs/includes/stripe/lib/UsageRecord.php new file mode 100644 index 00000000000..a9e3a25e3e9 --- /dev/null +++ b/htdocs/includes/stripe/lib/UsageRecord.php @@ -0,0 +1,44 @@ +json, $opts); + $obj->setLastResponse($response); + return $obj; + } +} diff --git a/htdocs/includes/stripe/lib/UsageRecordSummary.php b/htdocs/includes/stripe/lib/UsageRecordSummary.php new file mode 100644 index 00000000000..b8f4aebe974 --- /dev/null +++ b/htdocs/includes/stripe/lib/UsageRecordSummary.php @@ -0,0 +1,22 @@ +container = array_map("strtolower", $initial_array); + } + + public function offsetSet($offset, $value) + { + $offset = static::maybeLowercase($offset); + if (is_null($offset)) { + $this->container[] = $value; + } else { + $this->container[$offset] = $value; + } + } + + public function offsetExists($offset) + { + $offset = static::maybeLowercase($offset); + return isset($this->container[$offset]); + } + + public function offsetUnset($offset) + { + $offset = static::maybeLowercase($offset); + unset($this->container[$offset]); + } + + public function offsetGet($offset) + { + $offset = static::maybeLowercase($offset); + return isset($this->container[$offset]) ? $this->container[$offset] : null; + } + + private static function maybeLowercase($v) + { + if (is_string($v)) { + return strtolower($v); + } else { + return $v; + } + } +} diff --git a/htdocs/includes/stripe/lib/Util/RequestOptions.php b/htdocs/includes/stripe/lib/Util/RequestOptions.php index a31f4d322d9..495236224d8 100644 --- a/htdocs/includes/stripe/lib/Util/RequestOptions.php +++ b/htdocs/includes/stripe/lib/Util/RequestOptions.php @@ -16,11 +16,13 @@ class RequestOptions public $headers; public $apiKey; + public $apiBase; - public function __construct($key = null, $headers = []) + public function __construct($key = null, $headers = [], $base = null) { $this->apiKey = $key; $this->headers = $headers; + $this->apiBase = $base; } /** @@ -36,6 +38,9 @@ class RequestOptions if ($other_options->apiKey === null) { $other_options->apiKey = $this->apiKey; } + if ($other_options->apiBase === null) { + $other_options->apiBase = $this->apiBase; + } $other_options->headers = array_merge($this->headers, $other_options->headers); return $other_options; } @@ -65,16 +70,17 @@ class RequestOptions } if (is_null($options)) { - return new RequestOptions(null, []); + return new RequestOptions(null, [], null); } if (is_string($options)) { - return new RequestOptions($options, []); + return new RequestOptions($options, [], null); } if (is_array($options)) { $headers = []; $key = null; + $base = null; if (array_key_exists('api_key', $options)) { $key = $options['api_key']; } @@ -87,7 +93,10 @@ class RequestOptions if (array_key_exists('stripe_version', $options)) { $headers['Stripe-Version'] = $options['stripe_version']; } - return new RequestOptions($key, $headers); + if (array_key_exists('api_base', $options)) { + $base = $options['api_base']; + } + return new RequestOptions($key, $headers, $base); } $message = 'The second argument to Stripe API method calls is an ' diff --git a/htdocs/includes/stripe/lib/Util/Util.php b/htdocs/includes/stripe/lib/Util/Util.php index 82fd337dd34..c9cfa9fcbd2 100644 --- a/htdocs/includes/stripe/lib/Util/Util.php +++ b/htdocs/includes/stripe/lib/Util/Util.php @@ -67,50 +67,84 @@ abstract class Util { $types = [ // data structures - 'list' => 'Stripe\\Collection', + \Stripe\Collection::OBJECT_NAME => 'Stripe\\Collection', // business objects - 'account' => 'Stripe\\Account', - 'alipay_account' => 'Stripe\\AlipayAccount', - 'apple_pay_domain' => 'Stripe\\ApplePayDomain', - 'application_fee' => 'Stripe\\ApplicationFee', - 'balance' => 'Stripe\\Balance', - 'balance_transaction' => 'Stripe\\BalanceTransaction', - 'bank_account' => 'Stripe\\BankAccount', - 'bitcoin_receiver' => 'Stripe\\BitcoinReceiver', - 'bitcoin_transaction' => 'Stripe\\BitcoinTransaction', - 'card' => 'Stripe\\Card', - 'charge' => 'Stripe\\Charge', - 'country_spec' => 'Stripe\\CountrySpec', - 'coupon' => 'Stripe\\Coupon', - 'customer' => 'Stripe\\Customer', - 'dispute' => 'Stripe\\Dispute', - 'ephemeral_key' => 'Stripe\\EphemeralKey', - 'event' => 'Stripe\\Event', - 'exchange_rate' => 'Stripe\\ExchangeRate', - 'fee_refund' => 'Stripe\\ApplicationFeeRefund', - 'file_upload' => 'Stripe\\FileUpload', - 'invoice' => 'Stripe\\Invoice', - 'invoiceitem' => 'Stripe\\InvoiceItem', - 'login_link' => 'Stripe\\LoginLink', - 'order' => 'Stripe\\Order', - 'order_return' => 'Stripe\\OrderReturn', - 'payout' => 'Stripe\\Payout', - 'plan' => 'Stripe\\Plan', - 'product' => 'Stripe\\Product', - 'recipient' => 'Stripe\\Recipient', - 'recipient_transfer' => 'Stripe\\RecipientTransfer', - 'refund' => 'Stripe\\Refund', - 'sku' => 'Stripe\\SKU', - 'source' => 'Stripe\\Source', - 'source_transaction' => 'Stripe\\SourceTransaction', - 'subscription' => 'Stripe\\Subscription', - 'subscription_item' => 'Stripe\\SubscriptionItem', - 'three_d_secure' => 'Stripe\\ThreeDSecure', - 'token' => 'Stripe\\Token', - 'topup' => 'Stripe\\Topup', - 'transfer' => 'Stripe\\Transfer', - 'transfer_reversal' => 'Stripe\\TransferReversal', + \Stripe\Account::OBJECT_NAME => 'Stripe\\Account', + \Stripe\AccountLink::OBJECT_NAME => 'Stripe\\AccountLink', + \Stripe\AlipayAccount::OBJECT_NAME => 'Stripe\\AlipayAccount', + \Stripe\ApplePayDomain::OBJECT_NAME => 'Stripe\\ApplePayDomain', + \Stripe\ApplicationFee::OBJECT_NAME => 'Stripe\\ApplicationFee', + \Stripe\Balance::OBJECT_NAME => 'Stripe\\Balance', + \Stripe\BalanceTransaction::OBJECT_NAME => 'Stripe\\BalanceTransaction', + \Stripe\BankAccount::OBJECT_NAME => 'Stripe\\BankAccount', + \Stripe\BitcoinReceiver::OBJECT_NAME => 'Stripe\\BitcoinReceiver', + \Stripe\BitcoinTransaction::OBJECT_NAME => 'Stripe\\BitcoinTransaction', + \Stripe\Card::OBJECT_NAME => 'Stripe\\Card', + \Stripe\Charge::OBJECT_NAME => 'Stripe\\Charge', + \Stripe\Checkout\Session::OBJECT_NAME => 'Stripe\\Checkout\\Session', + \Stripe\CountrySpec::OBJECT_NAME => 'Stripe\\CountrySpec', + \Stripe\Coupon::OBJECT_NAME => 'Stripe\\Coupon', + \Stripe\CreditNote::OBJECT_NAME => 'Stripe\\CreditNote', + \Stripe\Customer::OBJECT_NAME => 'Stripe\\Customer', + \Stripe\Discount::OBJECT_NAME => 'Stripe\\Discount', + \Stripe\Dispute::OBJECT_NAME => 'Stripe\\Dispute', + \Stripe\EphemeralKey::OBJECT_NAME => 'Stripe\\EphemeralKey', + \Stripe\Event::OBJECT_NAME => 'Stripe\\Event', + \Stripe\ExchangeRate::OBJECT_NAME => 'Stripe\\ExchangeRate', + \Stripe\ApplicationFeeRefund::OBJECT_NAME => 'Stripe\\ApplicationFeeRefund', + \Stripe\File::OBJECT_NAME => 'Stripe\\File', + \Stripe\File::OBJECT_NAME_ALT => 'Stripe\\File', + \Stripe\FileLink::OBJECT_NAME => 'Stripe\\FileLink', + \Stripe\Invoice::OBJECT_NAME => 'Stripe\\Invoice', + \Stripe\InvoiceItem::OBJECT_NAME => 'Stripe\\InvoiceItem', + \Stripe\InvoiceLineItem::OBJECT_NAME => 'Stripe\\InvoiceLineItem', + \Stripe\IssuerFraudRecord::OBJECT_NAME => 'Stripe\\IssuerFraudRecord', + \Stripe\Issuing\Authorization::OBJECT_NAME => 'Stripe\\Issuing\\Authorization', + \Stripe\Issuing\Card::OBJECT_NAME => 'Stripe\\Issuing\\Card', + \Stripe\Issuing\CardDetails::OBJECT_NAME => 'Stripe\\Issuing\\CardDetails', + \Stripe\Issuing\Cardholder::OBJECT_NAME => 'Stripe\\Issuing\\Cardholder', + \Stripe\Issuing\Dispute::OBJECT_NAME => 'Stripe\\Issuing\\Dispute', + \Stripe\Issuing\Transaction::OBJECT_NAME => 'Stripe\\Issuing\\Transaction', + \Stripe\LoginLink::OBJECT_NAME => 'Stripe\\LoginLink', + \Stripe\Order::OBJECT_NAME => 'Stripe\\Order', + \Stripe\OrderItem::OBJECT_NAME => 'Stripe\\OrderItem', + \Stripe\OrderReturn::OBJECT_NAME => 'Stripe\\OrderReturn', + \Stripe\PaymentIntent::OBJECT_NAME => 'Stripe\\PaymentIntent', + \Stripe\PaymentMethod::OBJECT_NAME => 'Stripe\\PaymentMethod', + \Stripe\Payout::OBJECT_NAME => 'Stripe\\Payout', + \Stripe\Person::OBJECT_NAME => 'Stripe\\Person', + \Stripe\Plan::OBJECT_NAME => 'Stripe\\Plan', + \Stripe\Product::OBJECT_NAME => 'Stripe\\Product', + \Stripe\Radar\ValueList::OBJECT_NAME => 'Stripe\\Radar\\ValueList', + \Stripe\Radar\ValueListItem::OBJECT_NAME => 'Stripe\\Radar\\ValueListItem', + \Stripe\Recipient::OBJECT_NAME => 'Stripe\\Recipient', + \Stripe\RecipientTransfer::OBJECT_NAME => 'Stripe\\RecipientTransfer', + \Stripe\Refund::OBJECT_NAME => 'Stripe\\Refund', + \Stripe\Reporting\ReportRun::OBJECT_NAME => 'Stripe\\Reporting\\ReportRun', + \Stripe\Reporting\ReportType::OBJECT_NAME => 'Stripe\\Reporting\\ReportType', + \Stripe\Review::OBJECT_NAME => 'Stripe\\Review', + \Stripe\SKU::OBJECT_NAME => 'Stripe\\SKU', + \Stripe\Sigma\ScheduledQueryRun::OBJECT_NAME => 'Stripe\\Sigma\\ScheduledQueryRun', + \Stripe\Source::OBJECT_NAME => 'Stripe\\Source', + \Stripe\SourceTransaction::OBJECT_NAME => 'Stripe\\SourceTransaction', + \Stripe\Subscription::OBJECT_NAME => 'Stripe\\Subscription', + \Stripe\SubscriptionItem::OBJECT_NAME => 'Stripe\\SubscriptionItem', + \Stripe\SubscriptionSchedule::OBJECT_NAME => 'Stripe\\SubscriptionSchedule', + \Stripe\SubscriptionScheduleRevision::OBJECT_NAME => 'Stripe\\SubscriptionScheduleRevision', + \Stripe\TaxId::OBJECT_NAME => 'Stripe\\TaxId', + \Stripe\TaxRate::OBJECT_NAME => 'Stripe\\TaxRate', + \Stripe\ThreeDSecure::OBJECT_NAME => 'Stripe\\ThreeDSecure', + \Stripe\Terminal\ConnectionToken::OBJECT_NAME => 'Stripe\\Terminal\\ConnectionToken', + \Stripe\Terminal\Location::OBJECT_NAME => 'Stripe\\Terminal\\Location', + \Stripe\Terminal\Reader::OBJECT_NAME => 'Stripe\\Terminal\\Reader', + \Stripe\Token::OBJECT_NAME => 'Stripe\\Token', + \Stripe\Topup::OBJECT_NAME => 'Stripe\\Topup', + \Stripe\Transfer::OBJECT_NAME => 'Stripe\\Transfer', + \Stripe\TransferReversal::OBJECT_NAME => 'Stripe\\TransferReversal', + \Stripe\UsageRecord::OBJECT_NAME => 'Stripe\\UsageRecord', + \Stripe\UsageRecordSummary::OBJECT_NAME => 'Stripe\\UsageRecordSummary', + \Stripe\WebhookEndpoint::OBJECT_NAME => 'Stripe\\WebhookEndpoint', ]; if (self::isList($resp)) { $mapped = []; @@ -186,42 +220,117 @@ abstract class Util } /** - * @param array $arr A map of param keys to values. - * @param string|null $prefix + * Recursively goes through an array of parameters. If a parameter is an instance of + * ApiResource, then it is replaced by the resource's ID. + * Also clears out null values. * - * @return string A querystring, essentially. + * @param mixed $h + * @return mixed */ - public static function urlEncode($arr, $prefix = null) + public static function objectsToIds($h) { - if (!is_array($arr)) { - return $arr; + if ($h instanceof \Stripe\ApiResource) { + return $h->id; + } elseif (static::isList($h)) { + $results = []; + foreach ($h as $v) { + array_push($results, static::objectsToIds($v)); + } + return $results; + } elseif (is_array($h)) { + $results = []; + foreach ($h as $k => $v) { + if (is_null($v)) { + continue; + } + $results[$k] = static::objectsToIds($v); + } + return $results; + } else { + return $h; } + } - $r = []; - foreach ($arr as $k => $v) { - if (is_null($v)) { - continue; - } + /** + * @param array $params + * + * @return string + */ + public static function encodeParameters($params) + { + $flattenedParams = self::flattenParams($params); + $pieces = []; + foreach ($flattenedParams as $param) { + list($k, $v) = $param; + array_push($pieces, self::urlEncode($k) . '=' . self::urlEncode($v)); + } + return implode('&', $pieces); + } - if ($prefix) { - if ($k !== null && (!is_int($k) || is_array($v))) { - $k = $prefix."[".$k."]"; - } else { - $k = $prefix."[]"; - } - } + /** + * @param array $params + * @param string|null $parentKey + * + * @return array + */ + public static function flattenParams($params, $parentKey = null) + { + $result = []; - if (is_array($v)) { - $enc = self::urlEncode($v, $k); - if ($enc) { - $r[] = $enc; - } + foreach ($params as $key => $value) { + $calculatedKey = $parentKey ? "{$parentKey}[{$key}]" : $key; + + if (self::isList($value)) { + $result = array_merge($result, self::flattenParamsList($value, $calculatedKey)); + } elseif (is_array($value)) { + $result = array_merge($result, self::flattenParams($value, $calculatedKey)); } else { - $r[] = urlencode($k)."=".urlencode($v); + array_push($result, [$calculatedKey, $value]); } } - return implode("&", $r); + return $result; + } + + /** + * @param array $value + * @param string $calculatedKey + * + * @return array + */ + public static function flattenParamsList($value, $calculatedKey) + { + $result = []; + + foreach ($value as $i => $elem) { + if (self::isList($elem)) { + $result = array_merge($result, self::flattenParamsList($elem, $calculatedKey)); + } elseif (is_array($elem)) { + $result = array_merge($result, self::flattenParams($elem, "{$calculatedKey}[{$i}]")); + } else { + array_push($result, ["{$calculatedKey}[{$i}]", $elem]); + } + } + + return $result; + } + + /** + * @param string $key A string to URL-encode. + * + * @return string The URL-encoded string. + */ + public static function urlEncode($key) + { + $s = urlencode($key); + + // Don't use strict form encoding by changing the square bracket control + // characters back to their literals. This is fine by the server, and + // makes these parameter strings easier to read. + $s = str_replace('%5B', '[', $s); + $s = str_replace('%5D', ']', $s); + + return $s; } public static function normalizeId($id) @@ -235,4 +344,14 @@ abstract class Util } return [$id, $params]; } + + /** + * Returns UNIX timestamp in milliseconds + * + * @return integer current time in millis + */ + public static function currentTimeMillis() + { + return (int) round(microtime(true) * 1000); + } } diff --git a/htdocs/includes/stripe/lib/WebhookEndpoint.php b/htdocs/includes/stripe/lib/WebhookEndpoint.php new file mode 100644 index 00000000000..27ecacf690c --- /dev/null +++ b/htdocs/includes/stripe/lib/WebhookEndpoint.php @@ -0,0 +1,29 @@ + - - - tests - - - - - lib - - - - - - diff --git a/htdocs/includes/stripe/phpunit.xml b/htdocs/includes/stripe/phpunit.xml deleted file mode 100644 index 7a73276d0b1..00000000000 --- a/htdocs/includes/stripe/phpunit.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - tests - - - - - lib - - - - - - diff --git a/htdocs/includes/stripe/tests/Stripe/AccountTest.php b/htdocs/includes/stripe/tests/Stripe/AccountTest.php deleted file mode 100644 index 4c621690dcf..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/AccountTest.php +++ /dev/null @@ -1,365 +0,0 @@ -expectsRequest( - 'get', - '/v1/accounts' - ); - $resources = Account::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\Account", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/accounts/' . self::TEST_RESOURCE_ID - ); - $resource = Account::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\Account", $resource); - } - - public function testIsRetrievableWithoutId() - { - $this->expectsRequest( - 'get', - '/v1/account' - ); - $resource = Account::retrieve(); - $this->assertInstanceOf("Stripe\\Account", $resource); - } - - public function testIsCreatable() - { - $this->expectsRequest( - 'post', - '/v1/accounts' - ); - $resource = Account::create(["type" => "custom"]); - $this->assertInstanceOf("Stripe\\Account", $resource); - } - - public function testIsSaveable() - { - $resource = Account::retrieve(self::TEST_RESOURCE_ID); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/accounts/' . $resource->id - ); - $resource->save(); - $this->assertInstanceOf("Stripe\\Account", $resource); - } - - public function testIsUpdatable() - { - $this->expectsRequest( - 'post', - '/v1/accounts/' . self::TEST_RESOURCE_ID - ); - $resource = Account::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - $this->assertInstanceOf("Stripe\\Account", $resource); - } - - public function testIsDeletable() - { - $resource = Account::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'delete', - '/v1/accounts/' . $resource->id - ); - $resource->delete(); - $this->assertInstanceOf("Stripe\\Account", $resource); - } - - public function testIsRejectable() - { - $account = Account::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'post', - '/v1/accounts/' . $account->id . '/reject' - ); - $resource = $account->reject(["reason" => "fraud"]); - $this->assertInstanceOf("Stripe\\Account", $resource); - $this->assertSame($resource, $account); - } - - public function testIsDeauthorizable() - { - $resource = Account::retrieve(self::TEST_RESOURCE_ID); - $this->stubRequest( - 'post', - '/oauth/deauthorize', - [ - 'client_id' => Stripe::getClientId(), - 'stripe_user_id' => $resource->id, - ], - null, - false, - [ - 'stripe_user_id' => $resource->id, - ], - 200, - Stripe::$connectBase - ); - $resource->deauthorize(); - } - - public function testCanCreateExternalAccount() - { - $this->expectsRequest( - 'post', - '/v1/accounts/' . self::TEST_RESOURCE_ID . '/external_accounts' - ); - $resource = Account::createExternalAccount(self::TEST_RESOURCE_ID, [ - "external_account" => "btok_123", - ]); - $this->assertInstanceOf("Stripe\\BankAccount", $resource); - } - - public function testCanRetrieveExternalAccount() - { - $this->expectsRequest( - 'get', - '/v1/accounts/' . self::TEST_RESOURCE_ID . '/external_accounts/' . self::TEST_EXTERNALACCOUNT_ID - ); - $resource = Account::retrieveExternalAccount(self::TEST_RESOURCE_ID, self::TEST_EXTERNALACCOUNT_ID); - $this->assertInstanceOf("Stripe\\BankAccount", $resource); - } - - public function testCanUpdateExternalAccount() - { - $this->expectsRequest( - 'post', - '/v1/accounts/' . self::TEST_RESOURCE_ID . '/external_accounts/' . self::TEST_EXTERNALACCOUNT_ID - ); - $resource = Account::updateExternalAccount(self::TEST_RESOURCE_ID, self::TEST_EXTERNALACCOUNT_ID, [ - "name" => "name", - ]); - $this->assertInstanceOf("Stripe\\BankAccount", $resource); - } - - public function testCanDeleteExternalAccount() - { - $this->expectsRequest( - 'delete', - '/v1/accounts/' . self::TEST_RESOURCE_ID . '/external_accounts/' . self::TEST_EXTERNALACCOUNT_ID - ); - $resource = Account::deleteExternalAccount(self::TEST_RESOURCE_ID, self::TEST_EXTERNALACCOUNT_ID); - $this->assertInstanceOf("Stripe\\BankAccount", $resource); - } - - public function testCanListExternalAccounts() - { - $this->expectsRequest( - 'get', - '/v1/accounts/' . self::TEST_RESOURCE_ID . '/external_accounts' - ); - $resources = Account::allExternalAccounts(self::TEST_RESOURCE_ID); - $this->assertTrue(is_array($resources->data)); - } - - public function testCanCreateLoginLink() - { - $this->expectsRequest( - 'post', - '/v1/accounts/' . self::TEST_RESOURCE_ID . '/login_links' - ); - $resource = Account::createLoginLink(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\LoginLink", $resource); - } - - public function testSerializeNewAdditionalOwners() - { - $obj = Util\Util::convertToStripeObject([ - 'object' => 'account', - 'legal_entity' => StripeObject::constructFrom([]), - ], null); - $obj->legal_entity->additional_owners = [ - ['first_name' => 'Joe'], - ['first_name' => 'Jane'], - ]; - - $expected = [ - 'legal_entity' => [ - 'additional_owners' => [ - 0 => ['first_name' => 'Joe'], - 1 => ['first_name' => 'Jane'], - ], - ], - ]; - $this->assertSame($expected, $obj->serializeParameters()); - } - - public function testSerializePartiallyChangedAdditionalOwners() - { - $obj = Util\Util::convertToStripeObject([ - 'object' => 'account', - 'legal_entity' => [ - 'additional_owners' => [ - StripeObject::constructFrom(['first_name' => 'Joe']), - StripeObject::constructFrom(['first_name' => 'Jane']), - ], - ], - ], null); - $obj->legal_entity->additional_owners[1]->first_name = 'Stripe'; - - $expected = [ - 'legal_entity' => [ - 'additional_owners' => [ - 1 => ['first_name' => 'Stripe'], - ], - ], - ]; - $this->assertSame($expected, $obj->serializeParameters()); - } - - public function testSerializeUnchangedAdditionalOwners() - { - $obj = Util\Util::convertToStripeObject([ - 'object' => 'account', - 'legal_entity' => [ - 'additional_owners' => [ - StripeObject::constructFrom(['first_name' => 'Joe']), - StripeObject::constructFrom(['first_name' => 'Jane']), - ], - ], - ], null); - - $expected = [ - 'legal_entity' => [ - 'additional_owners' => [], - ], - ]; - $this->assertSame($expected, $obj->serializeParameters()); - } - - public function testSerializeUnsetAdditionalOwners() - { - $obj = Util\Util::convertToStripeObject([ - 'object' => 'account', - 'legal_entity' => [ - 'additional_owners' => [ - StripeObject::constructFrom(['first_name' => 'Joe']), - StripeObject::constructFrom(['first_name' => 'Jane']), - ], - ], - ], null); - $obj->legal_entity->additional_owners = null; - - // Note that the empty string that we send for this one has a special - // meaning for the server, which interprets it as an array unset. - $expected = [ - 'legal_entity' => [ - 'additional_owners' => '', - ], - ]; - $this->assertSame($expected, $obj->serializeParameters()); - } - - /** - * @expectedException \InvalidArgumentException - */ - public function testSerializeAdditionalOwnersDeletedItem() - { - $obj = Util\Util::convertToStripeObject([ - 'object' => 'account', - 'legal_entity' => [ - 'additional_owners' => [ - StripeObject::constructFrom(['first_name' => 'Joe']), - StripeObject::constructFrom(['first_name' => 'Jane']), - ], - ], - ], null); - unset($obj->legal_entity->additional_owners[0]); - - $obj->serializeParameters(); - } - - public function testSerializeExternalAccountString() - { - $obj = Util\Util::convertToStripeObject([ - 'object' => 'account', - ], null); - $obj->external_account = 'btok_123'; - - $expected = [ - 'external_account' => 'btok_123', - ]; - $this->assertSame($expected, $obj->serializeParameters()); - } - - public function testSerializeExternalAccountHash() - { - $obj = Util\Util::convertToStripeObject([ - 'object' => 'account', - ], null); - $obj->external_account = [ - 'object' => 'bank_account', - 'routing_number' => '110000000', - 'account_number' => '000123456789', - 'country' => 'US', - 'currency' => 'usd', - ]; - - $expected = [ - 'external_account' => [ - 'object' => 'bank_account', - 'routing_number' => '110000000', - 'account_number' => '000123456789', - 'country' => 'US', - 'currency' => 'usd', - ], - ]; - $this->assertSame($expected, $obj->serializeParameters()); - } - - public function testSerializeBankAccountString() - { - $obj = Util\Util::convertToStripeObject([ - 'object' => 'account', - ], null); - $obj->bank_account = 'btok_123'; - - $expected = [ - 'bank_account' => 'btok_123', - ]; - $this->assertSame($expected, $obj->serializeParameters()); - } - - public function testSerializeBankAccountHash() - { - $obj = Util\Util::convertToStripeObject([ - 'object' => 'account', - ], null); - $obj->bank_account = [ - 'object' => 'bank_account', - 'routing_number' => '110000000', - 'account_number' => '000123456789', - 'country' => 'US', - 'currency' => 'usd', - ]; - - $expected = [ - 'bank_account' => [ - 'object' => 'bank_account', - 'routing_number' => '110000000', - 'account_number' => '000123456789', - 'country' => 'US', - 'currency' => 'usd', - ], - ]; - $this->assertSame($expected, $obj->serializeParameters()); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/AlipayAccountTest.php b/htdocs/includes/stripe/tests/Stripe/AlipayAccountTest.php deleted file mode 100644 index 7159f5444df..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/AlipayAccountTest.php +++ /dev/null @@ -1,76 +0,0 @@ - self::TEST_RESOURCE_ID, - 'object' => 'card', - 'metadata' => [], - ]; - return AlipayAccount::constructFrom( - array_merge($params, $base), - new Util\RequestOptions() - ); - } - - public function testHasCorrectUrlForCustomer() - { - $resource = $this->createFixture(['customer' => 'cus_123']); - $this->assertSame( - "/v1/customers/cus_123/sources/" . self::TEST_RESOURCE_ID, - $resource->instanceUrl() - ); - } - - /** - * @expectedException \Stripe\Error\InvalidRequest - */ - public function testIsNotDirectlyRetrievable() - { - AlipayAccount::retrieve(self::TEST_RESOURCE_ID); - } - - public function testIsSaveable() - { - $resource = $this->createFixture(); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/customers/cus_123/sources/' . self::TEST_RESOURCE_ID - ); - $resource->save(); - $this->assertSame("Stripe\\AlipayAccount", get_class($resource)); - } - - /** - * @expectedException \Stripe\Error\InvalidRequest - */ - public function testIsNotDirectlyUpdatable() - { - AlipayAccount::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - } - - public function testIsDeletable() - { - $resource = $this->createFixture(); - $this->expectsRequest( - 'delete', - '/v1/customers/cus_123/sources/' . self::TEST_RESOURCE_ID - ); - $resource->delete(); - $this->assertSame("Stripe\\AlipayAccount", get_class($resource)); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/ApiRequestorTest.php b/htdocs/includes/stripe/tests/Stripe/ApiRequestorTest.php deleted file mode 100644 index 6fb8229c57d..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/ApiRequestorTest.php +++ /dev/null @@ -1,572 +0,0 @@ -getMethod('_encodeObjects'); - $method->setAccessible(true); - - $a = ['customer' => new Customer('abcd')]; - $enc = $method->invoke(null, $a); - $this->assertSame($enc, ['customer' => 'abcd']); - - // Preserves UTF-8 - $v = ['customer' => "☃"]; - $enc = $method->invoke(null, $v); - $this->assertSame($enc, $v); - - // Encodes latin-1 -> UTF-8 - $v = ['customer' => "\xe9"]; - $enc = $method->invoke(null, $v); - $this->assertSame($enc, ['customer' => "\xc3\xa9"]); - - // Encodes booleans - $v = true; - $enc = $method->invoke(null, $v); - $this->assertSame('true', $enc); - - $v = false; - $enc = $method->invoke(null, $v); - $this->assertSame('false', $enc); - } - - public function testHttpClientInjection() - { - $reflector = new \ReflectionClass('Stripe\\ApiRequestor'); - $method = $reflector->getMethod('httpClient'); - $method->setAccessible(true); - - $curl = new CurlClient(); - $curl->setTimeout(10); - ApiRequestor::setHttpClient($curl); - - $injectedCurl = $method->invoke(new ApiRequestor()); - $this->assertSame($injectedCurl, $curl); - } - - public function testDefaultHeaders() - { - $reflector = new \ReflectionClass('Stripe\\ApiRequestor'); - $method = $reflector->getMethod('_defaultHeaders'); - $method->setAccessible(true); - - // no way to stub static methods with PHPUnit 4.x :( - Stripe::setAppInfo('MyTestApp', '1.2.34', 'https://mytestapp.example'); - $apiKey = 'sk_test_notarealkey'; - $clientInfo = ['httplib' => 'testlib 0.1.2']; - - $headers = $method->invoke(null, $apiKey, $clientInfo); - - $ua = json_decode($headers['X-Stripe-Client-User-Agent']); - $this->assertSame($ua->application->name, 'MyTestApp'); - $this->assertSame($ua->application->version, '1.2.34'); - $this->assertSame($ua->application->url, 'https://mytestapp.example'); - - $this->assertSame($ua->httplib, 'testlib 0.1.2'); - - $this->assertSame( - $headers['User-Agent'], - 'Stripe/v1 PhpBindings/' . Stripe::VERSION . ' MyTestApp/1.2.34 (https://mytestapp.example)' - ); - - $this->assertSame($headers['Authorization'], 'Bearer ' . $apiKey); - } - - /** - * @expectedException \Stripe\Error\Authentication - * @expectedExceptionMessageRegExp #No API key provided# - */ - public function testRaisesAuthenticationErrorWhenNoApiKey() - { - Stripe::setApiKey(null); - Charge::create(); - } - - public function testRaisesInvalidRequestErrorOn400() - { - $this->stubRequest( - 'POST', - '/v1/charges', - [], - null, - false, - [ - 'error' => [ - 'type' => 'invalid_request_error', - 'message' => 'Missing id', - 'param' => 'id', - ], - ], - 400 - ); - - try { - Charge::create(); - $this->fail("Did not raise error"); - } catch (Error\InvalidRequest $e) { - $this->assertSame(400, $e->getHttpStatus()); - $this->assertTrue(is_array($e->getJsonBody())); - $this->assertSame('Missing id', $e->getMessage()); - $this->assertSame('id', $e->getStripeParam()); - } catch (\Exception $e) { - $this->fail("Unexpected exception: " . get_class($e)); - } - } - - public function testRaisesIdempotencyErrorOn400AndTypeIdempotencyError() - { - $this->stubRequest( - 'POST', - '/v1/charges', - array(), - null, - false, - array( - 'error' => array( - 'type' => 'idempotency_error', - 'message' => "Keys for idempotent requests can only be used with the same parameters they were first used with. Try using a key other than 'abc' if you meant to execute a different request.", - ), - ), - 400 - ); - - try { - Charge::create(); - $this->fail("Did not raise error"); - } catch (Error\Idempotency $e) { - $this->assertSame(400, $e->getHttpStatus()); - $this->assertTrue(is_array($e->getJsonBody())); - $this->assertSame("Keys for idempotent requests can only be used with the same parameters they were first used with. Try using a key other than 'abc' if you meant to execute a different request.", $e->getMessage()); - } catch (\Exception $e) { - $this->fail("Unexpected exception: " . get_class($e)); - } - } - - public function testRaisesAuthenticationErrorOn401() - { - $this->stubRequest( - 'POST', - '/v1/charges', - [], - null, - false, - [ - 'error' => [ - 'type' => 'invalid_request_error', - 'message' => 'You did not provide an API key.', - ], - ], - 401 - ); - - try { - Charge::create(); - $this->fail("Did not raise error"); - } catch (Error\Authentication $e) { - $this->assertSame(401, $e->getHttpStatus()); - $this->assertTrue(is_array($e->getJsonBody())); - $this->assertSame('You did not provide an API key.', $e->getMessage()); - } catch (\Exception $e) { - $this->fail("Unexpected exception: " . get_class($e)); - } - } - - public function testRaisesCardErrorOn402() - { - $this->stubRequest( - 'POST', - '/v1/charges', - [], - null, - false, - [ - 'error' => [ - 'type' => 'card_error', - 'message' => 'Your card was declined.', - 'code' => 'card_declined', - 'decline_code' => 'generic_decline', - 'charge' => 'ch_declined_charge', - 'param' => 'exp_month', - ], - ], - 402 - ); - - try { - Charge::create(); - $this->fail("Did not raise error"); - } catch (Error\Card $e) { - $this->assertSame(402, $e->getHttpStatus()); - $this->assertTrue(is_array($e->getJsonBody())); - $this->assertSame('Your card was declined.', $e->getMessage()); - $this->assertSame('card_declined', $e->getStripeCode()); - $this->assertSame('generic_decline', $e->getDeclineCode()); - $this->assertSame('exp_month', $e->getStripeParam()); - } catch (\Exception $e) { - $this->fail("Unexpected exception: " . get_class($e)); - } - } - - public function testRaisesPermissionErrorOn403() - { - $this->stubRequest( - 'GET', - '/v1/accounts/foo', - [], - null, - false, - [ - 'error' => [ - 'type' => 'invalid_request_error', - 'message' => "The provided key 'sk_test_********************1234' does not have access to account 'foo' (or that account does not exist). Application access may have been revoked.", - ], - ], - 403 - ); - - try { - Account::retrieve('foo'); - $this->fail("Did not raise error"); - } catch (Error\Permission $e) { - $this->assertSame(403, $e->getHttpStatus()); - $this->assertTrue(is_array($e->getJsonBody())); - $this->assertSame("The provided key 'sk_test_********************1234' does not have access to account 'foo' (or that account does not exist). Application access may have been revoked.", $e->getMessage()); - } catch (\Exception $e) { - $this->fail("Unexpected exception: " . get_class($e)); - } - } - - public function testRaisesInvalidRequestErrorOn404() - { - $this->stubRequest( - 'GET', - '/v1/charges/foo', - [], - null, - false, - [ - 'error' => [ - 'type' => 'invalid_request_error', - 'message' => 'No such charge: foo', - 'param' => 'id', - ], - ], - 404 - ); - - try { - Charge::retrieve('foo'); - $this->fail("Did not raise error"); - } catch (Error\InvalidRequest $e) { - $this->assertSame(404, $e->getHttpStatus()); - $this->assertTrue(is_array($e->getJsonBody())); - $this->assertSame('No such charge: foo', $e->getMessage()); - $this->assertSame('id', $e->getStripeParam()); - } catch (\Exception $e) { - $this->fail("Unexpected exception: " . get_class($e)); - } - } - - public function testRaisesRateLimitErrorOn429() - { - $this->stubRequest( - 'POST', - '/v1/charges', - [], - null, - false, - [ - 'error' => [ - 'message' => 'Too many requests', - ], - ], - 429 - ); - - try { - Charge::create(); - $this->fail("Did not raise error"); - } catch (Error\RateLimit $e) { - $this->assertSame(429, $e->getHttpStatus()); - $this->assertTrue(is_array($e->getJsonBody())); - $this->assertSame('Too many requests', $e->getMessage()); - } catch (\Exception $e) { - $this->fail("Unexpected exception: " . get_class($e)); - } - } - - public function testRaisesRateLimitErrorOn400AndCodeRateLimit() - { - $this->stubRequest( - 'POST', - '/v1/charges', - [], - null, - false, - [ - 'error' => [ - 'code' => 'rate_limit', - 'message' => 'Too many requests', - ], - ], - 400 - ); - - try { - Charge::create(); - $this->fail("Did not raise error"); - } catch (Error\RateLimit $e) { - $this->assertSame(400, $e->getHttpStatus()); - $this->assertTrue(is_array($e->getJsonBody())); - $this->assertSame('Too many requests', $e->getMessage()); - } catch (\Exception $e) { - $this->fail("Unexpected exception: " . get_class($e)); - } - } - - public function testRaisesOAuthInvalidRequestError() - { - $this->stubRequest( - 'POST', - '/oauth/token', - [], - null, - false, - [ - 'error' => 'invalid_request', - 'error_description' => 'No grant type specified', - ], - 400, - Stripe::$connectBase - ); - - try { - OAuth::token(); - $this->fail("Did not raise error"); - } catch (Error\OAuth\InvalidRequest $e) { - $this->assertSame(400, $e->getHttpStatus()); - $this->assertSame('invalid_request', $e->getErrorCode()); - $this->assertSame('No grant type specified', $e->getMessage()); - } catch (\Exception $e) { - $this->fail("Unexpected exception: " . get_class($e)); - } - } - - public function testRaisesOAuthInvalidClientError() - { - $this->stubRequest( - 'POST', - '/oauth/token', - [], - null, - false, - [ - 'error' => 'invalid_client', - 'error_description' => 'No authentication was provided. Send your secret API key using the Authorization header, or as a client_secret POST parameter.', - ], - 401, - Stripe::$connectBase - ); - - try { - OAuth::token(); - $this->fail("Did not raise error"); - } catch (Error\OAuth\InvalidClient $e) { - $this->assertSame(401, $e->getHttpStatus()); - $this->assertSame('invalid_client', $e->getErrorCode()); - $this->assertSame('No authentication was provided. Send your secret API key using the Authorization header, or as a client_secret POST parameter.', $e->getMessage()); - } catch (\Exception $e) { - $this->fail("Unexpected exception: " . get_class($e)); - } - } - - public function testRaisesOAuthInvalidGrantError() - { - $this->stubRequest( - 'POST', - '/oauth/token', - [], - null, - false, - [ - 'error' => 'invalid_grant', - 'error_description' => 'This authorization code has already been used. All tokens issued with this code have been revoked.', - ], - 400, - Stripe::$connectBase - ); - - try { - OAuth::token(); - $this->fail("Did not raise error"); - } catch (Error\OAuth\InvalidGrant $e) { - $this->assertSame(400, $e->getHttpStatus()); - $this->assertSame('invalid_grant', $e->getErrorCode()); - $this->assertSame('This authorization code has already been used. All tokens issued with this code have been revoked.', $e->getMessage()); - } catch (\Exception $e) { - $this->fail("Unexpected exception: " . get_class($e)); - } - } - - public function testRaisesOAuthInvalidScopeError() - { - $this->stubRequest( - 'POST', - '/oauth/token', - [], - null, - false, - [ - 'error' => 'invalid_scope', - 'error_description' => 'Invalid scope provided: invalid_scope.', - ], - 400, - Stripe::$connectBase - ); - - try { - OAuth::token(); - $this->fail("Did not raise error"); - } catch (Error\OAuth\InvalidScope $e) { - $this->assertSame(400, $e->getHttpStatus()); - $this->assertSame('invalid_scope', $e->getErrorCode()); - $this->assertSame('Invalid scope provided: invalid_scope.', $e->getMessage()); - } catch (\Exception $e) { - $this->fail("Unexpected exception: " . get_class($e)); - } - } - - public function testRaisesOAuthUnsupportedGrantTypeError() - { - $this->stubRequest( - 'POST', - '/oauth/token', - [], - null, - false, - [ - 'error' => 'unsupported_grant_type', - ], - 400, - Stripe::$connectBase - ); - - try { - OAuth::token(); - $this->fail("Did not raise error"); - } catch (Error\OAuth\UnsupportedGrantType $e) { - $this->assertSame(400, $e->getHttpStatus()); - $this->assertSame('unsupported_grant_type', $e->getErrorCode()); - } catch (\Exception $e) { - $this->fail("Unexpected exception: " . get_class($e)); - } - } - - public function testRaisesOAuthUnsupportedResponseTypeError() - { - $this->stubRequest( - 'POST', - '/oauth/token', - [], - null, - false, - [ - 'error' => 'unsupported_response_type', - 'error_description' => "Only 'code' response_type is supported, but 'unsupported_response_type' was provided", - ], - 400, - Stripe::$connectBase - ); - - try { - OAuth::token(); - $this->fail("Did not raise error"); - } catch (Error\OAuth\UnsupportedResponseType $e) { - $this->assertSame(400, $e->getHttpStatus()); - $this->assertSame('unsupported_response_type', $e->getErrorCode()); - $this->assertSame("Only 'code' response_type is supported, but 'unsupported_response_type' was provided", $e->getMessage()); - } catch (\Exception $e) { - $this->fail("Unexpected exception: " . get_class($e)); - } - } - - public function testHeaderStripeVersionGlobal() - { - Stripe::setApiVersion('2222-22-22'); - $this->stubRequest( - 'POST', - '/v1/charges', - [], - [ - 'Stripe-Version: 2222-22-22', - ], - false, - [ - 'id' => 'ch_123', - 'object' => 'charge', - ] - ); - Charge::create(); - } - - public function testHeaderStripeVersionRequestOptions() - { - $this->stubRequest( - 'POST', - '/v1/charges', - [], - [ - 'Stripe-Version: 2222-22-22', - ], - false, - [ - 'id' => 'ch_123', - 'object' => 'charge', - ] - ); - Charge::create([], ['stripe_version' => '2222-22-22']); - } - - public function testHeaderStripeAccountGlobal() - { - Stripe::setAccountId('acct_123'); - $this->stubRequest( - 'POST', - '/v1/charges', - [], - [ - 'Stripe-Account: acct_123', - ], - false, - [ - 'id' => 'ch_123', - 'object' => 'charge', - ] - ); - Charge::create(); - } - - public function testHeaderStripeAccountRequestOptions() - { - $this->stubRequest( - 'POST', - '/v1/charges', - [], - [ - 'Stripe-Account: acct_123', - ], - false, - [ - 'id' => 'ch_123', - 'object' => 'charge', - ] - ); - Charge::create([], ['stripe_account' => 'acct_123']); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/ApplePayDomainTest.php b/htdocs/includes/stripe/tests/Stripe/ApplePayDomainTest.php deleted file mode 100644 index d033f55cbb0..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/ApplePayDomainTest.php +++ /dev/null @@ -1,52 +0,0 @@ -expectsRequest( - 'get', - '/v1/apple_pay/domains' - ); - $resources = ApplePayDomain::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\ApplePayDomain", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/apple_pay/domains/' . self::TEST_RESOURCE_ID - ); - $resource = ApplePayDomain::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\ApplePayDomain", $resource); - } - - public function testIsCreatable() - { - $this->expectsRequest( - 'post', - '/v1/apple_pay/domains' - ); - $resource = ApplePayDomain::create([ - "domain_name" => "domain", - ]); - $this->assertInstanceOf("Stripe\\ApplePayDomain", $resource); - } - - public function testIsDeletable() - { - $resource = ApplePayDomain::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'delete', - '/v1/apple_pay/domains/' . $resource->id - ); - $resource->delete(); - $this->assertInstanceOf("Stripe\\ApplePayDomain", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/ApplicationFeeRefundTest.php b/htdocs/includes/stripe/tests/Stripe/ApplicationFeeRefundTest.php deleted file mode 100644 index 9af059ff7f3..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/ApplicationFeeRefundTest.php +++ /dev/null @@ -1,21 +0,0 @@ -metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/application_fees/' . $resource->fee . '/refunds/' . $resource->id - ); - $resource->save(); - $this->assertInstanceOf("Stripe\\ApplicationFeeRefund", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/ApplicationFeeTest.php b/htdocs/includes/stripe/tests/Stripe/ApplicationFeeTest.php deleted file mode 100644 index 66e007ff3d2..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/ApplicationFeeTest.php +++ /dev/null @@ -1,83 +0,0 @@ -expectsRequest( - 'get', - '/v1/application_fees' - ); - $resources = ApplicationFee::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\ApplicationFee", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/application_fees/' . self::TEST_RESOURCE_ID - ); - $resource = ApplicationFee::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\ApplicationFee", $resource); - } - - public function testIsRefundable() - { - $fee = ApplicationFee::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'post', - '/v1/application_fees/' . $fee->id . '/refunds' - ); - $resource = $fee->refund(); - $this->assertInstanceOf("Stripe\\ApplicationFee", $resource); - $this->assertSame($resource, $fee); - } - - public function testCanCreateRefund() - { - $this->expectsRequest( - 'post', - '/v1/application_fees/' . self::TEST_RESOURCE_ID . '/refunds' - ); - $resource = ApplicationFee::createRefund(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\ApplicationFeeRefund", $resource); - } - - public function testCanRetrieveRefund() - { - $this->expectsRequest( - 'get', - '/v1/application_fees/' . self::TEST_RESOURCE_ID . '/refunds/' . self::TEST_FEEREFUND_ID - ); - $resource = ApplicationFee::retrieveRefund(self::TEST_RESOURCE_ID, self::TEST_FEEREFUND_ID); - $this->assertInstanceOf("Stripe\\ApplicationFeeRefund", $resource); - } - - public function testCanUpdateRefund() - { - $this->expectsRequest( - 'post', - '/v1/application_fees/' . self::TEST_RESOURCE_ID . '/refunds/' . self::TEST_FEEREFUND_ID - ); - $resource = ApplicationFee::updateRefund(self::TEST_RESOURCE_ID, self::TEST_FEEREFUND_ID); - $this->assertInstanceOf("Stripe\\ApplicationFeeRefund", $resource); - } - - public function testCanListRefunds() - { - $this->expectsRequest( - 'get', - '/v1/application_fees/' . self::TEST_RESOURCE_ID . '/refunds' - ); - $resources = ApplicationFee::allRefunds(self::TEST_RESOURCE_ID); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\ApplicationFeeRefund", $resources->data[0]); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/BalanceTest.php b/htdocs/includes/stripe/tests/Stripe/BalanceTest.php deleted file mode 100644 index ccbdbdfb747..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/BalanceTest.php +++ /dev/null @@ -1,16 +0,0 @@ -expectsRequest( - 'get', - '/v1/balance' - ); - $resource = Balance::retrieve(); - $this->assertInstanceOf("Stripe\\Balance", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/BalanceTransactionTest.php b/htdocs/includes/stripe/tests/Stripe/BalanceTransactionTest.php deleted file mode 100644 index 8785e859113..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/BalanceTransactionTest.php +++ /dev/null @@ -1,29 +0,0 @@ -expectsRequest( - 'get', - '/v1/balance/history' - ); - $resources = BalanceTransaction::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\BalanceTransaction", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/balance/history/' . self::TEST_RESOURCE_ID - ); - $resource = BalanceTransaction::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\BalanceTransaction", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/BankAccountTest.php b/htdocs/includes/stripe/tests/Stripe/BankAccountTest.php deleted file mode 100644 index ab1dff9d5a8..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/BankAccountTest.php +++ /dev/null @@ -1,99 +0,0 @@ - self::TEST_RESOURCE_ID, - 'object' => 'bank_account', - 'metadata' => [], - ]; - return BankAccount::constructFrom( - array_merge($params, $base), - new Util\RequestOptions() - ); - } - - public function testHasCorrectUrlForCustomer() - { - $resource = $this->createFixture(['customer' => 'cus_123']); - $this->assertSame( - "/v1/customers/cus_123/sources/" . self::TEST_RESOURCE_ID, - $resource->instanceUrl() - ); - } - - public function testHasCorrectUrlForAccount() - { - $resource = $this->createFixture(['account' => 'acct_123']); - $this->assertSame( - "/v1/accounts/acct_123/external_accounts/" . self::TEST_RESOURCE_ID, - $resource->instanceUrl() - ); - } - - /** - * @expectedException \Stripe\Error\InvalidRequest - */ - public function testIsNotDirectlyRetrievable() - { - BankAccount::retrieve(self::TEST_RESOURCE_ID); - } - - public function testIsSaveable() - { - $resource = $this->createFixture(); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/customers/cus_123/sources/' . self::TEST_RESOURCE_ID - ); - $resource->save(); - $this->assertSame("Stripe\\BankAccount", get_class($resource)); - } - - /** - * @expectedException \Stripe\Error\InvalidRequest - */ - public function testIsNotDirectlyUpdatable() - { - BankAccount::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - } - - public function testIsDeletable() - { - $resource = $this->createFixture(); - $this->expectsRequest( - 'delete', - '/v1/customers/cus_123/sources/' . self::TEST_RESOURCE_ID - ); - $resource->delete(); - $this->assertSame("Stripe\\BankAccount", get_class($resource)); - } - - public function testIsVerifiable() - { - $resource = $this->createFixture(); - $this->expectsRequest( - 'post', - '/v1/customers/cus_123/sources/' . self::TEST_RESOURCE_ID . "/verify", - [ - "amounts" => [1, 2] - ] - ); - $resource->verify(["amounts" => [1, 2]]); - $this->assertInstanceOf("Stripe\\BankAccount", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/BitcoinReceiverTest.php b/htdocs/includes/stripe/tests/Stripe/BitcoinReceiverTest.php deleted file mode 100644 index cea999fc4f2..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/BitcoinReceiverTest.php +++ /dev/null @@ -1,62 +0,0 @@ - self::TEST_RESOURCE_ID, - 'object' => 'bitcoin_receiver', - 'metadata' => [], - ]; - return BitcoinReceiver::constructFrom( - array_merge($params, $base), - new Util\RequestOptions() - ); - } - - public function testHasCorrectStandaloneUrl() - { - $resource = $this->createFixture(); - $this->assertSame( - "/v1/bitcoin/receivers/" . self::TEST_RESOURCE_ID, - $resource->instanceUrl() - ); - } - - public function testHasCorrectUrlForCustomer() - { - $resource = $this->createFixture(['customer' => 'cus_123']); - $this->assertSame( - "/v1/customers/cus_123/sources/" . self::TEST_RESOURCE_ID, - $resource->instanceUrl() - ); - } - - public function testIsListable() - { - $this->expectsRequest( - 'get', - '/v1/bitcoin/receivers' - ); - $resources = BitcoinReceiver::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertSame("Stripe\\BitcoinReceiver", get_class($resources->data[0])); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/bitcoin/receivers/' . self::TEST_RESOURCE_ID - ); - $resource = BitcoinReceiver::retrieve(self::TEST_RESOURCE_ID); - $this->assertSame("Stripe\\BitcoinReceiver", get_class($resource)); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/CardTest.php b/htdocs/includes/stripe/tests/Stripe/CardTest.php deleted file mode 100644 index 8976eff6679..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/CardTest.php +++ /dev/null @@ -1,94 +0,0 @@ - self::TEST_RESOURCE_ID, - 'object' => 'card', - 'metadata' => [], - ]; - return Card::constructFrom( - array_merge($params, $base), - new Util\RequestOptions() - ); - } - - public function testHasCorrectUrlForCustomer() - { - $resource = $this->createFixture(['customer' => 'cus_123']); - $this->assertSame( - "/v1/customers/cus_123/sources/" . self::TEST_RESOURCE_ID, - $resource->instanceUrl() - ); - } - - public function testHasCorrectUrlForAccount() - { - $resource = $this->createFixture(['account' => 'acct_123']); - $this->assertSame( - "/v1/accounts/acct_123/external_accounts/" . self::TEST_RESOURCE_ID, - $resource->instanceUrl() - ); - } - - public function testHasCorrectUrlForRecipient() - { - $resource = $this->createFixture(['recipient' => 'rp_123']); - $this->assertSame( - "/v1/recipients/rp_123/cards/" . self::TEST_RESOURCE_ID, - $resource->instanceUrl() - ); - } - - /** - * @expectedException \Stripe\Error\InvalidRequest - */ - public function testIsNotDirectlyRetrievable() - { - Card::retrieve(self::TEST_RESOURCE_ID); - } - - public function testIsSaveable() - { - $resource = $this->createFixture(); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/customers/cus_123/sources/' . self::TEST_RESOURCE_ID - ); - $resource->save(); - $this->assertSame("Stripe\\Card", get_class($resource)); - } - - /** - * @expectedException \Stripe\Error\InvalidRequest - */ - public function testIsNotDirectlyUpdatable() - { - Card::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - } - - public function testIsDeletable() - { - $resource = $this->createFixture(); - $this->expectsRequest( - 'delete', - '/v1/customers/cus_123/sources/' . self::TEST_RESOURCE_ID - ); - $resource->delete(); - $this->assertSame("Stripe\\Card", get_class($resource)); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/ChargeTest.php b/htdocs/includes/stripe/tests/Stripe/ChargeTest.php deleted file mode 100644 index b8c6cbabf3b..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/ChargeTest.php +++ /dev/null @@ -1,140 +0,0 @@ -expectsRequest( - 'get', - '/v1/charges' - ); - $resources = Charge::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\Charge", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/charges/' . self::TEST_RESOURCE_ID - ); - $resource = Charge::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\Charge", $resource); - } - - public function testIsCreatable() - { - $this->expectsRequest( - 'post', - '/v1/charges' - ); - $resource = Charge::create([ - "amount" => 100, - "currency" => "usd", - "source" => "tok_123" - ]); - $this->assertInstanceOf("Stripe\\Charge", $resource); - } - - public function testIsSaveable() - { - $resource = Charge::retrieve(self::TEST_RESOURCE_ID); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/charges/' . $resource->id - ); - $resource->save(); - $this->assertInstanceOf("Stripe\\Charge", $resource); - } - - public function testIsUpdatable() - { - $this->expectsRequest( - 'post', - '/v1/charges/' . self::TEST_RESOURCE_ID - ); - $resource = Charge::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - $this->assertInstanceOf("Stripe\\Charge", $resource); - } - - public function testCanRefund() - { - $charge = Charge::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'post', - '/v1/charges/' . $charge->id . '/refund' - ); - $resource = $charge->refund(); - $this->assertInstanceOf("Stripe\\Charge", $resource); - $this->assertSame($resource, $charge); - } - - public function testCanCapture() - { - $charge = Charge::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'post', - '/v1/charges/' . $charge->id . '/capture' - ); - $resource = $charge->capture(); - $this->assertInstanceOf("Stripe\\Charge", $resource); - $this->assertSame($resource, $charge); - } - - public function testCanUpdateDispute() - { - $charge = Charge::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'post', - '/v1/charges/' . $charge->id . '/dispute' - ); - $resource = $charge->updateDispute(); - $this->assertInstanceOf("Stripe\\Dispute", $resource); - } - - public function testCanCloseDispute() - { - $charge = Charge::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'post', - '/v1/charges/' . $charge->id . '/dispute/close' - ); - $resource = $charge->closeDispute(); - $this->assertInstanceOf("Stripe\\Charge", $resource); - $this->assertSame($resource, $charge); - } - - public function testCanMarkAsFraudulent() - { - $charge = Charge::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'post', - '/v1/charges/' . $charge->id, - ['fraud_details' => ['user_report' => 'fraudulent']] - ); - $resource = $charge->markAsFraudulent(); - $this->assertInstanceOf("Stripe\\Charge", $resource); - $this->assertSame($resource, $charge); - } - - public function testCanMarkAsSafe() - { - $charge = Charge::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'post', - '/v1/charges/' . $charge->id, - ['fraud_details' => ['user_report' => 'safe']] - ); - $resource = $charge->markAsSafe(); - $this->assertInstanceOf("Stripe\\Charge", $resource); - $this->assertSame($resource, $charge); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/CollectionTest.php b/htdocs/includes/stripe/tests/Stripe/CollectionTest.php deleted file mode 100644 index 560085aede2..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/CollectionTest.php +++ /dev/null @@ -1,147 +0,0 @@ -fixture = Collection::constructFrom([ - 'data' => [['id' => 1]], - 'has_more' => true, - 'url' => '/things', - ]); - } - - public function testCanList() - { - $this->stubRequest( - 'GET', - '/things', - [], - null, - false, - [ - 'data' => [['id' => 1]], - 'has_more' => true, - 'url' => '/things', - ] - ); - - $resources = $this->fixture->all(); - $this->assertTrue(is_array($resources->data)); - } - - public function testCanRetrieve() - { - $this->stubRequest( - 'GET', - '/things/1', - [], - null, - false, - [ - 'id' => 1, - ] - ); - - $this->fixture->retrieve(1); - } - - public function testCanCreate() - { - $this->stubRequest( - 'POST', - '/things', - [ - 'foo' => 'bar', - ], - null, - false, - [ - 'id' => 2, - ] - ); - - $this->fixture->create([ - 'foo' => 'bar', - ]); - } - - public function testProvidesAutoPagingIterator() - { - $this->stubRequest( - 'GET', - '/things', - [ - 'starting_after' => 1, - ], - null, - false, - [ - 'data' => [['id' => 2], ['id' => 3]], - 'has_more' => false, - ] - ); - - $seen = []; - foreach ($this->fixture->autoPagingIterator() as $item) { - array_push($seen, $item['id']); - } - - $this->assertSame([1, 2, 3], $seen); - } - - public function testSupportsIteratorToArray() - { - $this->stubRequest( - 'GET', - '/things', - [ - 'starting_after' => 1, - ], - null, - false, - [ - 'data' => [['id' => 2], ['id' => 3]], - 'has_more' => false, - ] - ); - - $seen = []; - foreach (iterator_to_array($this->fixture->autoPagingIterator()) as $item) { - array_push($seen, $item['id']); - } - - $this->assertSame([1, 2, 3], $seen); - } - - public function testHeaders() - { - $this->stubRequest( - 'POST', - '/things', - [ - 'foo' => 'bar', - ], - [ - 'Stripe-Account: acct_foo', - 'Idempotency-Key: qwertyuiop', - ], - false, - [ - 'id' => 2, - ] - ); - - $this->fixture->create([ - 'foo' => 'bar', - ], [ - 'stripe_account' => 'acct_foo', - 'idempotency_key' => 'qwertyuiop', - ]); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/CountrySpecTest.php b/htdocs/includes/stripe/tests/Stripe/CountrySpecTest.php deleted file mode 100644 index cccd4116845..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/CountrySpecTest.php +++ /dev/null @@ -1,29 +0,0 @@ -expectsRequest( - 'get', - '/v1/country_specs' - ); - $resources = CountrySpec::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\CountrySpec", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/country_specs/' . self::TEST_RESOURCE_ID - ); - $resource = CountrySpec::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\CountrySpec", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/CouponTest.php b/htdocs/includes/stripe/tests/Stripe/CouponTest.php deleted file mode 100644 index 8a6fbf630cd..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/CouponTest.php +++ /dev/null @@ -1,79 +0,0 @@ -expectsRequest( - 'get', - '/v1/coupons' - ); - $resources = Coupon::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\Coupon", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/coupons/' . self::TEST_RESOURCE_ID - ); - $resource = Coupon::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\Coupon", $resource); - } - - public function testIsCreatable() - { - $this->expectsRequest( - 'post', - '/v1/coupons' - ); - $resource = Coupon::create([ - "percent_off" => 25, - "duration" => "repeating", - "duration_in_months" => 3, - "id" => self::TEST_RESOURCE_ID, - ]); - $this->assertInstanceOf("Stripe\\Coupon", $resource); - } - - public function testIsSaveable() - { - $resource = Coupon::retrieve(self::TEST_RESOURCE_ID); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/coupons/' . self::TEST_RESOURCE_ID - ); - $resource->save(); - $this->assertInstanceOf("Stripe\\Coupon", $resource); - } - - public function testIsUpdatable() - { - $this->expectsRequest( - 'post', - '/v1/coupons/' . self::TEST_RESOURCE_ID - ); - $resource = Coupon::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - $this->assertInstanceOf("Stripe\\Coupon", $resource); - } - - public function testIsDeletable() - { - $resource = Coupon::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'delete', - '/v1/coupons/' . self::TEST_RESOURCE_ID - ); - $resource->delete(); - $this->assertInstanceOf("Stripe\\Coupon", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/CustomerTest.php b/htdocs/includes/stripe/tests/Stripe/CustomerTest.php deleted file mode 100644 index e279e5489e8..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/CustomerTest.php +++ /dev/null @@ -1,269 +0,0 @@ -expectsRequest( - 'get', - '/v1/customers' - ); - $resources = Customer::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\Customer", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/customers/' . self::TEST_RESOURCE_ID - ); - $resource = Customer::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\Customer", $resource); - } - - public function testIsCreatable() - { - $this->expectsRequest( - 'post', - '/v1/customers' - ); - $resource = Customer::create(); - $this->assertInstanceOf("Stripe\\Customer", $resource); - } - - public function testIsSaveable() - { - $resource = Customer::retrieve(self::TEST_RESOURCE_ID); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/customers/' . $resource->id - ); - $resource->save(); - $this->assertInstanceOf("Stripe\\Customer", $resource); - } - - public function testIsUpdatable() - { - $this->expectsRequest( - 'post', - '/v1/customers/' . self::TEST_RESOURCE_ID - ); - $resource = Customer::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - $this->assertInstanceOf("Stripe\\Customer", $resource); - } - - public function testIsDeletable() - { - $resource = Customer::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'delete', - '/v1/customers/' . $resource->id - ); - $resource->delete(); - $this->assertInstanceOf("Stripe\\Customer", $resource); - } - - public function testCanAddInvoiceItem() - { - $customer = Customer::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'post', - '/v1/invoiceitems', - [ - "amount" => 100, - "currency" => "usd", - "customer" => $customer->id - ] - ); - $resource = $customer->addInvoiceItem([ - "amount" => 100, - "currency" => "usd" - ]); - $this->assertInstanceOf("Stripe\\InvoiceItem", $resource); - } - - public function testCanListInvoices() - { - $customer = Customer::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'get', - '/v1/invoices', - ["customer" => $customer->id] - ); - $resources = $customer->invoices(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\Invoice", $resources->data[0]); - } - - public function testCanListInvoiceItems() - { - $customer = Customer::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'get', - '/v1/invoiceitems', - ["customer" => $customer->id] - ); - $resources = $customer->invoiceItems(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\InvoiceItem", $resources->data[0]); - } - - public function testCanListCharges() - { - $customer = Customer::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'get', - '/v1/charges', - ["customer" => $customer->id] - ); - $resources = $customer->charges(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\Charge", $resources->data[0]); - } - - public function testCanUpdateSubscription() - { - $customer = Customer::retrieve(self::TEST_RESOURCE_ID); - $this->stubRequest( - 'post', - '/v1/customers/' . $customer->id . '/subscription', - ["plan" => "plan"], - null, - false, - [ - "object" => "subscription", - "id" => "sub_foo" - ] - ); - $resource = $customer->updateSubscription(["plan" => "plan"]); - $this->assertInstanceOf("Stripe\\Subscription", $resource); - $this->assertSame("sub_foo", $customer->subscription->id); - } - - public function testCanCancelSubscription() - { - $customer = Customer::retrieve(self::TEST_RESOURCE_ID); - $this->stubRequest( - 'delete', - '/v1/customers/' . $customer->id . '/subscription', - [], - null, - false, - [ - "object" => "subscription", - "id" => "sub_foo" - ] - ); - $resource = $customer->cancelSubscription(); - $this->assertInstanceOf("Stripe\\Subscription", $resource); - $this->assertSame("sub_foo", $customer->subscription->id); - } - - public function testCanDeleteDiscount() - { - $customer = Customer::retrieve(self::TEST_RESOURCE_ID); - $this->stubRequest( - 'delete', - '/v1/customers/' . $customer->id . '/discount' - ); - $customer->deleteDiscount(); - $this->assertSame($customer->discount, null); - } - - public function testCanCreateSource() - { - $this->expectsRequest( - 'post', - '/v1/customers/' . self::TEST_RESOURCE_ID . '/sources' - ); - $resource = Customer::createSource(self::TEST_RESOURCE_ID, ["source" => "btok_123"]); - $this->assertInstanceOf("Stripe\\BankAccount", $resource); - } - - public function testCanRetrieveSource() - { - $this->expectsRequest( - 'get', - '/v1/customers/' . self::TEST_RESOURCE_ID . '/sources/' . self::TEST_SOURCE_ID - ); - $resource = Customer::retrieveSource(self::TEST_RESOURCE_ID, self::TEST_SOURCE_ID); - $this->assertInstanceOf("Stripe\\BankAccount", $resource); - } - - public function testCanUpdateSource() - { - $this->expectsRequest( - 'post', - '/v1/customers/' . self::TEST_RESOURCE_ID . '/sources/' . self::TEST_SOURCE_ID - ); - $resource = Customer::updateSource(self::TEST_RESOURCE_ID, self::TEST_SOURCE_ID, ["name" => "name"]); - // stripe-mock returns a Card on this method and not a bank account - $this->assertInstanceOf("Stripe\\Card", $resource); - } - - public function testCanDeleteSource() - { - $this->expectsRequest( - 'delete', - '/v1/customers/' . self::TEST_RESOURCE_ID . '/sources/' . self::TEST_SOURCE_ID - ); - $resource = Customer::deleteSource(self::TEST_RESOURCE_ID, self::TEST_SOURCE_ID); - $this->assertInstanceOf("Stripe\\BankAccount", $resource); - } - - public function testCanListSources() - { - $this->expectsRequest( - 'get', - '/v1/customers/' . self::TEST_RESOURCE_ID . '/sources' - ); - $resources = Customer::allSources(self::TEST_RESOURCE_ID); - $this->assertTrue(is_array($resources->data)); - } - - public function testSerializeSourceString() - { - $obj = Util\Util::convertToStripeObject([ - 'object' => 'customer', - ], null); - $obj->source = 'tok_visa'; - - $expected = [ - 'source' => 'tok_visa', - ]; - $this->assertSame($expected, $obj->serializeParameters()); - } - - public function testSerializeSourceMap() - { - $obj = Util\Util::convertToStripeObject([ - 'object' => 'customer', - ], null); - $obj->source = [ - 'object' => 'card', - 'number' => '4242424242424242', - 'exp_month' => 12, - 'exp_year' => 2032, - ]; - - $expected = [ - 'source' => [ - 'object' => 'card', - 'number' => '4242424242424242', - 'exp_month' => 12, - 'exp_year' => 2032, - ], - ]; - $this->assertSame($expected, $obj->serializeParameters()); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/DisputeTest.php b/htdocs/includes/stripe/tests/Stripe/DisputeTest.php deleted file mode 100644 index 81d93da0213..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/DisputeTest.php +++ /dev/null @@ -1,65 +0,0 @@ -expectsRequest( - 'get', - '/v1/disputes' - ); - $resources = Dispute::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\Dispute", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/disputes/' . self::TEST_RESOURCE_ID - ); - $resource = Dispute::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\Dispute", $resource); - } - - public function testIsSaveable() - { - $resource = Dispute::retrieve(self::TEST_RESOURCE_ID); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/disputes/' . $resource->id - ); - $resource->save(); - $this->assertInstanceOf("Stripe\\Dispute", $resource); - } - - public function testIsUpdatable() - { - $this->expectsRequest( - 'post', - '/v1/disputes/' . self::TEST_RESOURCE_ID - ); - $resource = Dispute::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - $this->assertInstanceOf("Stripe\\Dispute", $resource); - } - - public function testIsClosable() - { - $dispute = Dispute::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'post', - '/v1/disputes/' . $dispute->id . '/close' - ); - $resource = $dispute->close(); - $this->assertInstanceOf("Stripe\\Dispute", $resource); - $this->assertSame($resource, $dispute); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/EphemeralKeyTest.php b/htdocs/includes/stripe/tests/Stripe/EphemeralKeyTest.php deleted file mode 100644 index e8a1fc0e9ef..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/EphemeralKeyTest.php +++ /dev/null @@ -1,43 +0,0 @@ -expectsRequest( - 'post', - '/v1/ephemeral_keys', - null, - ["Stripe-Version: 2017-05-25"] - ); - $resource = EphemeralKey::create([ - "customer" => "cus_123", - ], ["stripe_version" => "2017-05-25"]); - $this->assertInstanceOf("Stripe\\EphemeralKey", $resource); - } - - /** - * @expectedException \InvalidArgumentException - */ - public function testIsNotCreatableWithoutAnExplicitApiVersion() - { - $resource = EphemeralKey::create([ - "customer" => "cus_123", - ]); - } - - public function testIsDeletable() - { - $key = EphemeralKey::create([ - "customer" => "cus_123", - ], ["stripe_version" => "2017-05-25"]); - $this->expectsRequest( - 'delete', - '/v1/ephemeral_keys/' . $key->id - ); - $resource = $key->delete(); - $this->assertInstanceOf("Stripe\\EphemeralKey", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/Error/BaseTest.php b/htdocs/includes/stripe/tests/Stripe/Error/BaseTest.php deleted file mode 100644 index 4c2732ed1d1..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/Error/BaseTest.php +++ /dev/null @@ -1,36 +0,0 @@ -getMockForAbstractClass('Stripe\\Error\\Base', [ - 'message', - 200, - '{"key": "value"}', - ['key' => 'value'], - [ - 'Some-Header' => 'Some Value', - 'Request-Id' => 'req_test', - ], - ]); - } - - public function testGetters() - { - $e = $this->createFixture(); - $this->assertSame(200, $e->getHttpStatus()); - $this->assertSame('{"key": "value"}', $e->getHttpBody()); - $this->assertSame(['key' => 'value'], $e->getJsonBody()); - $this->assertSame('Some Value', $e->getHttpHeaders()['Some-Header']); - $this->assertSame('req_test', $e->getRequestId()); - } - - public function testToString() - { - $e = $this->createFixture(); - $this->assertContains("from API request 'req_test'", (string)$e); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/Error/SignatureVerificationTest.php b/htdocs/includes/stripe/tests/Stripe/Error/SignatureVerificationTest.php deleted file mode 100644 index 020a41f8f76..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/Error/SignatureVerificationTest.php +++ /dev/null @@ -1,12 +0,0 @@ -assertSame('sig_header', $e->getSigHeader()); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/EventTest.php b/htdocs/includes/stripe/tests/Stripe/EventTest.php deleted file mode 100644 index 2e3c92f0e49..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/EventTest.php +++ /dev/null @@ -1,29 +0,0 @@ -expectsRequest( - 'get', - '/v1/events' - ); - $resources = Event::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\Event", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/events/' . self::TEST_RESOURCE_ID - ); - $resource = Event::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\Event", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/ExchangeRateTest.php b/htdocs/includes/stripe/tests/Stripe/ExchangeRateTest.php deleted file mode 100644 index 8b07b5a1358..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/ExchangeRateTest.php +++ /dev/null @@ -1,54 +0,0 @@ -stubRequest( - 'get', - '/v1/exchange_rates', - [], - null, - false, - [ - 'object' => 'list', - 'data' => [ - [ - 'id' => 'eur', - 'object' => 'exchange_rate', - 'rates' => ['usd' => 1.18221], - ], - [ - 'id' => 'usd', - 'object' => 'exchange_rate', - 'rates' => ['eur' => 0.845876], - ], - ], - ] - ); - - $listRates = ExchangeRate::all(); - $this->assertTrue(is_array($listRates->data)); - $this->assertEquals('exchange_rate', $listRates->data[0]->object); - } - - public function testIsRetrievable() - { - $this->stubRequest( - 'get', - '/v1/exchange_rates/usd', - [], - null, - false, - [ - 'id' => 'usd', - 'object' => 'exchange_rate', - 'rates' => ['eur' => 0.845876], - ] - ); - $rates = ExchangeRate::retrieve("usd"); - $this->assertEquals('exchange_rate', $rates->object); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/FileUploadTest.php b/htdocs/includes/stripe/tests/Stripe/FileUploadTest.php deleted file mode 100644 index 21bb0b568f6..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/FileUploadTest.php +++ /dev/null @@ -1,104 +0,0 @@ -fixture = [ - 'id' => self::TEST_RESOURCE_ID, - 'object' => 'file_upload', - ]; - } - - public function testIsListable() - { - $this->stubRequest( - 'get', - '/v1/files', - [], - null, - false, - [ - 'object' => 'list', - 'data' => [$this->fixture], - 'resource_url' => '/v1/files', - ], - 200, - Stripe::$apiUploadBase - ); - - $resources = FileUpload::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\FileUpload", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->stubRequest( - 'get', - '/v1/files/' . self::TEST_RESOURCE_ID, - [], - null, - false, - $this->fixture, - 200, - Stripe::$apiUploadBase - ); - $resource = FileUpload::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\FileUpload", $resource); - } - - public function testIsCreatableWithFileHandle() - { - $this->stubRequest( - 'post', - '/v1/files', - null, - ['Content-Type: multipart/form-data'], - true, - $this->fixture, - 200, - Stripe::$apiUploadBase - ); - $fp = fopen(dirname(__FILE__) . '/../data/test.png', 'r'); - $resource = FileUpload::create([ - "purpose" => "dispute_evidence", - "file" => $fp, - ]); - $this->assertInstanceOf("Stripe\\FileUpload", $resource); - } - - public function testIsCreatableWithCurlFile() - { - if (!class_exists('\CurlFile', false)) { - // Older PHP versions don't support this - return; - } - - $this->stubRequest( - 'post', - '/v1/files', - null, - ['Content-Type: multipart/form-data'], - true, - $this->fixture, - 200, - Stripe::$apiUploadBase - ); - $curlFile = new \CurlFile(dirname(__FILE__) . '/../data/test.png'); - $resource = FileUpload::create([ - "purpose" => "dispute_evidence", - "file" => $curlFile, - ]); - $this->assertInstanceOf("Stripe\\FileUpload", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/HttpClient/CurlClientTest.php b/htdocs/includes/stripe/tests/Stripe/HttpClient/CurlClientTest.php deleted file mode 100644 index 086e6d3ee8d..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/HttpClient/CurlClientTest.php +++ /dev/null @@ -1,228 +0,0 @@ -origMaxNetworkRetries = Stripe::getMaxNetworkRetries(); - $this->origMaxNetworkRetryDelay = Stripe::getMaxNetworkRetryDelay(); - $this->origInitialNetworkRetryDelay = Stripe::getInitialNetworkRetryDelay(); - } - - /** - * @before - */ - public function setUpReflectors() - { - $stripeReflector = new \ReflectionClass('\Stripe\Stripe'); - - $this->maxNetworkRetryDelayProperty = $stripeReflector->getProperty('maxNetworkRetryDelay'); - $this->maxNetworkRetryDelayProperty->setAccessible(true); - - $this->initialNetworkRetryDelayProperty = $stripeReflector->getProperty('initialNetworkRetryDelay'); - $this->initialNetworkRetryDelayProperty->setAccessible(true); - - $curlClientReflector = new \ReflectionClass('Stripe\HttpClient\CurlClient'); - - $this->shouldRetryMethod = $curlClientReflector->getMethod('shouldRetry'); - $this->shouldRetryMethod->setAccessible(true); - - $this->sleepTimeMethod = $curlClientReflector->getMethod('sleepTime'); - $this->sleepTimeMethod->setAccessible(true); - } - - /** - * @after - */ - public function restoreOriginalNetworkValues() - { - Stripe::setMaxNetworkRetries($this->origMaxNetworkRetries); - $this->setMaxNetworkRetryDelay($this->origMaxNetworkRetryDelay); - $this->setInitialNetworkRetryDelay($this->origInitialNetworkRetryDelay); - } - - private function setMaxNetworkRetryDelay($maxNetworkRetryDelay) - { - $this->maxNetworkRetryDelayProperty->setValue(null, $maxNetworkRetryDelay); - } - - private function setInitialNetworkRetryDelay($initialNetworkRetryDelay) - { - $this->initialNetworkRetryDelayProperty->setValue(null, $initialNetworkRetryDelay); - } - - private function createFakeRandomGenerator($returnValue = 1.0) - { - $fakeRandomGenerator = $this->getMock('Stripe\Util\RandomGenetator', ['randFloat']); - $fakeRandomGenerator->method('randFloat')->willReturn($returnValue); - return $fakeRandomGenerator; - } - - public function testTimeout() - { - $curl = new CurlClient(); - $this->assertSame(CurlClient::DEFAULT_TIMEOUT, $curl->getTimeout()); - $this->assertSame(CurlClient::DEFAULT_CONNECT_TIMEOUT, $curl->getConnectTimeout()); - - // implicitly tests whether we're returning the CurlClient instance - $curl = $curl->setConnectTimeout(1)->setTimeout(10); - $this->assertSame(1, $curl->getConnectTimeout()); - $this->assertSame(10, $curl->getTimeout()); - - $curl->setTimeout(-1); - $curl->setConnectTimeout(-999); - $this->assertSame(0, $curl->getTimeout()); - $this->assertSame(0, $curl->getConnectTimeout()); - } - - public function testUserAgentInfo() - { - $curl = new CurlClient(); - $uaInfo = $curl->getUserAgentInfo(); - $this->assertNotNull($uaInfo); - $this->assertNotNull($uaInfo['httplib']); - $this->assertNotNull($uaInfo['ssllib']); - } - - public function testDefaultOptions() - { - // make sure options array loads/saves properly - $optionsArray = [CURLOPT_PROXY => 'localhost:80']; - $withOptionsArray = new CurlClient($optionsArray); - $this->assertSame($withOptionsArray->getDefaultOptions(), $optionsArray); - - // make sure closure-based options work properly, including argument passing - $ref = null; - $withClosure = new CurlClient(function ($method, $absUrl, $headers, $params, $hasFile) use (&$ref) { - $ref = func_get_args(); - return []; - }); - - $withClosure->request('get', 'https://httpbin.org/status/200', [], [], false); - $this->assertSame($ref, ['get', 'https://httpbin.org/status/200', [], [], false]); - - // this is the last test case that will run, since it'll throw an exception at the end - $withBadClosure = new CurlClient(function () { - return 'thisShouldNotWork'; - }); - $this->setExpectedException('Stripe\Error\Api', "Non-array value returned by defaultOptions CurlClient callback"); - $withBadClosure->request('get', 'https://httpbin.org/status/200', [], [], false); - } - - public function testSslOption() - { - // make sure options array loads/saves properly - $optionsArray = [CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1]; - $withOptionsArray = new CurlClient($optionsArray); - $this->assertSame($withOptionsArray->getDefaultOptions(), $optionsArray); - } - - public function testShouldRetryOnTimeout() - { - Stripe::setMaxNetworkRetries(2); - - $curlClient = new CurlClient(); - - $this->assertTrue($this->shouldRetryMethod->invoke($curlClient, CURLE_OPERATION_TIMEOUTED, 0, 0)); - } - - public function testShouldRetryOnConnectionFailure() - { - Stripe::setMaxNetworkRetries(2); - - $curlClient = new CurlClient(); - - $this->assertTrue($this->shouldRetryMethod->invoke($curlClient, CURLE_COULDNT_CONNECT, 0, 0)); - } - - public function testShouldRetryOnConflict() - { - Stripe::setMaxNetworkRetries(2); - - $curlClient = new CurlClient(); - - $this->assertTrue($this->shouldRetryMethod->invoke($curlClient, 0, 409, 0)); - } - - public function testShouldNotRetryAtMaximumCount() - { - Stripe::setMaxNetworkRetries(2); - - $curlClient = new CurlClient(); - - $this->assertFalse($this->shouldRetryMethod->invoke($curlClient, 0, 0, Stripe::getMaxNetworkRetries())); - } - - public function testShouldNotRetryOnCertValidationError() - { - Stripe::setMaxNetworkRetries(2); - - $curlClient = new CurlClient(); - - $this->assertFalse($this->shouldRetryMethod->invoke($curlClient, CURLE_SSL_PEER_CERTIFICATE, -1, 0)); - } - - public function testSleepTimeShouldGrowExponentially() - { - $this->setMaxNetworkRetryDelay(999); - - $curlClient = new CurlClient(null, $this->createFakeRandomGenerator()); - - $this->assertEquals( - Stripe::getInitialNetworkRetryDelay() * 1, - $this->sleepTimeMethod->invoke($curlClient, 1) - ); - $this->assertEquals( - Stripe::getInitialNetworkRetryDelay() * 2, - $this->sleepTimeMethod->invoke($curlClient, 2) - ); - $this->assertEquals( - Stripe::getInitialNetworkRetryDelay() * 4, - $this->sleepTimeMethod->invoke($curlClient, 3) - ); - $this->assertEquals( - Stripe::getInitialNetworkRetryDelay() * 8, - $this->sleepTimeMethod->invoke($curlClient, 4) - ); - } - - public function testSleepTimeShouldEnforceMaxNetworkRetryDelay() - { - $this->setInitialNetworkRetryDelay(1); - $this->setMaxNetworkRetryDelay(2); - - $curlClient = new CurlClient(null, $this->createFakeRandomGenerator()); - - $this->assertEquals(1, $this->sleepTimeMethod->invoke($curlClient, 1)); - $this->assertEquals(2, $this->sleepTimeMethod->invoke($curlClient, 2)); - $this->assertEquals(2, $this->sleepTimeMethod->invoke($curlClient, 3)); - $this->assertEquals(2, $this->sleepTimeMethod->invoke($curlClient, 4)); - } - - public function testSleepTimeShouldAddSomeRandomness() - { - $randomValue = 0.8; - $this->setInitialNetworkRetryDelay(1); - $this->setMaxNetworkRetryDelay(8); - - $curlClient = new CurlClient(null, $this->createFakeRandomGenerator($randomValue)); - - $baseValue = Stripe::getInitialNetworkRetryDelay() * (0.5 * (1 + $randomValue)); - - // the initial value cannot be smaller than the base, - // so the randomness is ignored - $this->assertEquals(Stripe::getInitialNetworkRetryDelay(), $this->sleepTimeMethod->invoke($curlClient, 1)); - - // after the first one, the randomness is applied - $this->assertEquals($baseValue * 2, $this->sleepTimeMethod->invoke($curlClient, 2)); - $this->assertEquals($baseValue * 4, $this->sleepTimeMethod->invoke($curlClient, 3)); - $this->assertEquals($baseValue * 8, $this->sleepTimeMethod->invoke($curlClient, 4)); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/InvoiceItemTest.php b/htdocs/includes/stripe/tests/Stripe/InvoiceItemTest.php deleted file mode 100644 index ffe140aa7ca..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/InvoiceItemTest.php +++ /dev/null @@ -1,78 +0,0 @@ -expectsRequest( - 'get', - '/v1/invoiceitems' - ); - $resources = InvoiceItem::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\InvoiceItem", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/invoiceitems/' . self::TEST_RESOURCE_ID - ); - $resource = InvoiceItem::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\InvoiceItem", $resource); - } - - public function testIsCreatable() - { - $this->expectsRequest( - 'post', - '/v1/invoiceitems' - ); - $resource = InvoiceItem::create([ - "amount" => 100, - "currency" => "usd", - "customer" => "cus_123" - ]); - $this->assertInstanceOf("Stripe\\InvoiceItem", $resource); - } - - public function testIsSaveable() - { - $resource = InvoiceItem::retrieve(self::TEST_RESOURCE_ID); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/invoiceitems/' . $resource->id - ); - $resource->save(); - $this->assertInstanceOf("Stripe\\InvoiceItem", $resource); - } - - public function testIsUpdatable() - { - $this->expectsRequest( - 'post', - '/v1/invoiceitems/' . self::TEST_RESOURCE_ID - ); - $resource = InvoiceItem::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - $this->assertInstanceOf("Stripe\\InvoiceItem", $resource); - } - - public function testIsDeletable() - { - $invoiceItem = InvoiceItem::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'delete', - '/v1/invoiceitems/' . $invoiceItem->id - ); - $resource = $invoiceItem->delete(); - $this->assertInstanceOf("Stripe\\InvoiceItem", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/InvoiceTest.php b/htdocs/includes/stripe/tests/Stripe/InvoiceTest.php deleted file mode 100644 index f1ae9378628..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/InvoiceTest.php +++ /dev/null @@ -1,87 +0,0 @@ -expectsRequest( - 'get', - '/v1/invoices' - ); - $resources = Invoice::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\Invoice", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/invoices/' . self::TEST_RESOURCE_ID - ); - $resource = Invoice::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\Invoice", $resource); - } - - public function testIsCreatable() - { - $this->expectsRequest( - 'post', - '/v1/invoices' - ); - $resource = Invoice::create([ - "customer" => "cus_123" - ]); - $this->assertInstanceOf("Stripe\\Invoice", $resource); - } - - public function testIsSaveable() - { - $resource = Invoice::retrieve(self::TEST_RESOURCE_ID); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/invoices/' . $resource->id - ); - $resource->save(); - $this->assertInstanceOf("Stripe\\Invoice", $resource); - } - - public function testIsUpdatable() - { - $this->expectsRequest( - 'post', - '/v1/invoices/' . self::TEST_RESOURCE_ID - ); - $resource = Invoice::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - $this->assertInstanceOf("Stripe\\Invoice", $resource); - } - - public function testCanRetrieveUpcoming() - { - $this->expectsRequest( - 'get', - '/v1/invoices/upcoming' - ); - $resource = Invoice::upcoming(["customer" => "cus_123"]); - $this->assertInstanceOf("Stripe\\Invoice", $resource); - } - - public function testIsPayable() - { - $invoice = Invoice::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'post', - '/v1/invoices/' . $invoice->id . '/pay' - ); - $resource = $invoice->pay(); - $this->assertInstanceOf("Stripe\\Invoice", $resource); - $this->assertSame($resource, $invoice); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/OAuthTest.php b/htdocs/includes/stripe/tests/Stripe/OAuthTest.php deleted file mode 100644 index b4e43a88103..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/OAuthTest.php +++ /dev/null @@ -1,97 +0,0 @@ - 'read_write', - 'state' => 'csrf_token', - 'stripe_user' => [ - 'email' => 'test@example.com', - 'url' => 'https://example.com/profile/test', - 'country' => 'US', - ], - ]); - - $uri = parse_url($uriStr); - parse_str($uri['query'], $params); - - $this->assertSame('https', $uri['scheme']); - $this->assertSame('connect.stripe.com', $uri['host']); - $this->assertSame('/oauth/authorize', $uri['path']); - - $this->assertSame('ca_123', $params['client_id']); - $this->assertSame('read_write', $params['scope']); - $this->assertSame('test@example.com', $params['stripe_user']['email']); - $this->assertSame('https://example.com/profile/test', $params['stripe_user']['url']); - $this->assertSame('US', $params['stripe_user']['country']); - } - - /** - * @expectedException \Stripe\Error\Authentication - * @expectedExceptionMessageRegExp #No client_id provided# - */ - public function testRaisesAuthenticationErrorWhenNoClientId() - { - Stripe::setClientId(null); - OAuth::authorizeUrl(); - } - - public function testToken() - { - $this->stubRequest( - 'POST', - '/oauth/token', - [ - 'grant_type' => 'authorization_code', - 'code' => 'this_is_an_authorization_code', - ], - null, - false, - [ - 'access_token' => 'sk_access_token', - 'scope' => 'read_only', - 'livemode' => false, - 'token_type' => 'bearer', - 'refresh_token' => 'sk_refresh_token', - 'stripe_user_id' => 'acct_test', - 'stripe_publishable_key' => 'pk_test', - ], - 200, - Stripe::$connectBase - ); - - $resp = OAuth::token([ - 'grant_type' => 'authorization_code', - 'code' => 'this_is_an_authorization_code', - ]); - $this->assertSame('sk_access_token', $resp->access_token); - } - - public function testDeauthorize() - { - $this->stubRequest( - 'POST', - '/oauth/deauthorize', - [ - 'stripe_user_id' => 'acct_test_deauth', - 'client_id' => 'ca_123', - ], - null, - false, - [ - 'stripe_user_id' => 'acct_test_deauth', - ], - 200, - Stripe::$connectBase - ); - - $resp = OAuth::deauthorize([ - 'stripe_user_id' => 'acct_test_deauth', - ]); - $this->assertSame('acct_test_deauth', $resp->stripe_user_id); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/OrderReturnTest.php b/htdocs/includes/stripe/tests/Stripe/OrderReturnTest.php deleted file mode 100644 index bb2d65c437a..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/OrderReturnTest.php +++ /dev/null @@ -1,29 +0,0 @@ -expectsRequest( - 'get', - '/v1/order_returns' - ); - $resources = OrderReturn::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\OrderReturn", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/order_returns/' . self::TEST_RESOURCE_ID - ); - $resource = OrderReturn::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\OrderReturn", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/OrderTest.php b/htdocs/includes/stripe/tests/Stripe/OrderTest.php deleted file mode 100644 index 51d17e94fc7..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/OrderTest.php +++ /dev/null @@ -1,87 +0,0 @@ -expectsRequest( - 'get', - '/v1/orders' - ); - $resources = Order::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\Order", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/orders/' . self::TEST_RESOURCE_ID - ); - $resource = Order::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\Order", $resource); - } - - public function testIsCreatable() - { - $this->expectsRequest( - 'post', - '/v1/orders' - ); - $resource = Order::create([ - 'currency' => 'usd' - ]); - $this->assertInstanceOf("Stripe\\Order", $resource); - } - - public function testIsSaveable() - { - $resource = Order::retrieve(self::TEST_RESOURCE_ID); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/orders/' . $resource->id - ); - $resource->save(); - $this->assertInstanceOf("Stripe\\Order", $resource); - } - - public function testIsUpdatable() - { - $this->expectsRequest( - 'post', - '/v1/orders/' . self::TEST_RESOURCE_ID - ); - $resource = Order::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - $this->assertInstanceOf("Stripe\\Order", $resource); - } - - public function testIsPayable() - { - $resource = Order::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'post', - '/v1/orders/' . $resource->id . '/pay' - ); - $resource->pay(); - $this->assertInstanceOf("Stripe\\Order", $resource); - } - - public function testIsReturnable() - { - $order = Order::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'post', - '/v1/orders/' . $order->id . '/returns' - ); - $resource = $order->returnOrder(); - $this->assertInstanceOf("Stripe\\OrderReturn", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/PayoutTest.php b/htdocs/includes/stripe/tests/Stripe/PayoutTest.php deleted file mode 100644 index 79c7b5fd015..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/PayoutTest.php +++ /dev/null @@ -1,77 +0,0 @@ -expectsRequest( - 'get', - '/v1/payouts' - ); - $resources = Payout::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\Payout", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/payouts/' . self::TEST_RESOURCE_ID - ); - $resource = Payout::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\Payout", $resource); - } - - public function testIsCreatable() - { - $this->expectsRequest( - 'post', - '/v1/payouts' - ); - $resource = Payout::create([ - "amount" => 100, - "currency" => "usd" - ]); - $this->assertInstanceOf("Stripe\\Payout", $resource); - } - - public function testIsSaveable() - { - $resource = Payout::retrieve(self::TEST_RESOURCE_ID); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/payouts/' . $resource->id - ); - $resource->save(); - $this->assertInstanceOf("Stripe\\Payout", $resource); - } - - public function testIsUpdatable() - { - $this->expectsRequest( - 'post', - '/v1/payouts/' . self::TEST_RESOURCE_ID - ); - $resource = Payout::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - $this->assertInstanceOf("Stripe\\Payout", $resource); - } - - public function testIsCancelable() - { - $resource = Payout::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'post', - '/v1/payouts/' . $resource->id . '/cancel' - ); - $resource->cancel(); - $this->assertInstanceOf("Stripe\\Payout", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/PlanTest.php b/htdocs/includes/stripe/tests/Stripe/PlanTest.php deleted file mode 100644 index 8d71745ed56..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/PlanTest.php +++ /dev/null @@ -1,80 +0,0 @@ -expectsRequest( - 'get', - '/v1/plans' - ); - $resources = Plan::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\Plan", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/plans/' . self::TEST_RESOURCE_ID - ); - $resource = Plan::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\Plan", $resource); - } - - public function testIsCreatable() - { - $this->expectsRequest( - 'post', - '/v1/plans' - ); - $resource = Plan::create([ - 'amount' => 100, - 'interval' => 'month', - 'currency' => 'usd', - 'name' => self::TEST_RESOURCE_ID, - 'id' => self::TEST_RESOURCE_ID - ]); - $this->assertInstanceOf("Stripe\\Plan", $resource); - } - - public function testIsSaveable() - { - $resource = Plan::retrieve(self::TEST_RESOURCE_ID); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/plans/' . $resource->id - ); - $resource->save(); - $this->assertInstanceOf("Stripe\\Plan", $resource); - } - - public function testIsUpdatable() - { - $this->expectsRequest( - 'post', - '/v1/plans/' . self::TEST_RESOURCE_ID - ); - $resource = Plan::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - $this->assertInstanceOf("Stripe\\Plan", $resource); - } - - public function testIsDeletable() - { - $resource = Plan::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'delete', - '/v1/plans/' . $resource->id - ); - $resource->delete(); - $this->assertInstanceOf("Stripe\\Plan", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/ProductTest.php b/htdocs/includes/stripe/tests/Stripe/ProductTest.php deleted file mode 100644 index c2a3813c870..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/ProductTest.php +++ /dev/null @@ -1,77 +0,0 @@ -expectsRequest( - 'get', - '/v1/products' - ); - $resources = Product::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\Product", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/products/' . self::TEST_RESOURCE_ID - ); - $resource = Product::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\Product", $resource); - } - - public function testIsCreatable() - { - $this->expectsRequest( - 'post', - '/v1/products' - ); - $resource = Product::create([ - 'name' => 'name', - 'type' => 'good' - ]); - $this->assertInstanceOf("Stripe\\Product", $resource); - } - - public function testIsSaveable() - { - $resource = Product::retrieve(self::TEST_RESOURCE_ID); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/products/' . $resource->id - ); - $resource->save(); - $this->assertInstanceOf("Stripe\\Product", $resource); - } - - public function testIsUpdatable() - { - $this->expectsRequest( - 'post', - '/v1/products/' . self::TEST_RESOURCE_ID - ); - $resource = Product::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - $this->assertInstanceOf("Stripe\\Product", $resource); - } - - public function testIsDeletable() - { - $resource = Product::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'delete', - '/v1/products/' . $resource->id - ); - $resource->delete(); - $this->assertInstanceOf("Stripe\\Product", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/RecipientTest.php b/htdocs/includes/stripe/tests/Stripe/RecipientTest.php deleted file mode 100644 index 43dd6e82a79..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/RecipientTest.php +++ /dev/null @@ -1,90 +0,0 @@ -expectsRequest( - 'get', - '/v1/recipients' - ); - $resources = Recipient::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\Recipient", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/recipients/' . self::TEST_RESOURCE_ID - ); - $resource = Recipient::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\Recipient", $resource); - } - - public function testIsCreatable() - { - $this->expectsRequest( - 'post', - '/v1/recipients' - ); - $resource = Recipient::create([ - "name" => "name", - "type" => "individual" - ]); - $this->assertInstanceOf("Stripe\\Recipient", $resource); - } - - public function testIsSaveable() - { - $resource = Recipient::retrieve(self::TEST_RESOURCE_ID); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/recipients/' . $resource->id - ); - $resource->save(); - $this->assertInstanceOf("Stripe\\Recipient", $resource); - } - - public function testIsUpdatable() - { - $this->expectsRequest( - 'post', - '/v1/recipients/' . self::TEST_RESOURCE_ID - ); - $resource = Recipient::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - $this->assertInstanceOf("Stripe\\Recipient", $resource); - } - - public function testIsDeletable() - { - $resource = Recipient::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'delete', - '/v1/recipients/' . $resource->id - ); - $resource->delete(); - $this->assertInstanceOf("Stripe\\Recipient", $resource); - } - - public function testCanListTransfers() - { - $recipient = Recipient::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'get', - '/v1/transfers', - ["recipient" => $recipient->id] - ); - $resources = $recipient->transfers(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\Transfer", $resources->data[0]); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/RefundTest.php b/htdocs/includes/stripe/tests/Stripe/RefundTest.php deleted file mode 100644 index 788361d4d9d..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/RefundTest.php +++ /dev/null @@ -1,65 +0,0 @@ -expectsRequest( - 'get', - '/v1/refunds' - ); - $resources = Refund::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\Refund", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/refunds/' . self::TEST_RESOURCE_ID - ); - $resource = Refund::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\Refund", $resource); - } - - public function testIsCreatable() - { - $this->expectsRequest( - 'post', - '/v1/refunds' - ); - $resource = Refund::create([ - "charge" => "ch_123" - ]); - $this->assertInstanceOf("Stripe\\Refund", $resource); - } - - public function testIsSaveable() - { - $resource = Refund::retrieve(self::TEST_RESOURCE_ID); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/refunds/' . $resource->id - ); - $resource->save(); - $this->assertInstanceOf("Stripe\\Refund", $resource); - } - - public function testIsUpdatable() - { - $this->expectsRequest( - 'post', - '/v1/refunds/' . self::TEST_RESOURCE_ID - ); - $resource = Refund::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - $this->assertInstanceOf("Stripe\\Refund", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/SKUTest.php b/htdocs/includes/stripe/tests/Stripe/SKUTest.php deleted file mode 100644 index d4fc2ad408b..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/SKUTest.php +++ /dev/null @@ -1,82 +0,0 @@ -expectsRequest( - 'get', - '/v1/skus' - ); - $resources = SKU::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\SKU", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/skus/' . self::TEST_RESOURCE_ID - ); - $resource = SKU::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\SKU", $resource); - } - - public function testIsCreatable() - { - $this->expectsRequest( - 'post', - '/v1/skus' - ); - $resource = SKU::create([ - 'currency' => 'usd', - 'inventory' => [ - 'type' => 'finite', - 'quantity' => 1 - ], - 'price' => 100, - 'product' => "prod_123" - ]); - $this->assertInstanceOf("Stripe\\SKU", $resource); - } - - public function testIsSaveable() - { - $resource = SKU::retrieve(self::TEST_RESOURCE_ID); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/skus/' . $resource->id - ); - $resource->save(); - $this->assertInstanceOf("Stripe\\SKU", $resource); - } - - public function testIsUpdatable() - { - $this->expectsRequest( - 'post', - '/v1/skus/' . self::TEST_RESOURCE_ID - ); - $resource = SKU::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - $this->assertInstanceOf("Stripe\\SKU", $resource); - } - - public function testIsDeletable() - { - $resource = SKU::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'delete', - '/v1/skus/' . $resource->id - ); - $resource->delete(); - $this->assertInstanceOf("Stripe\\SKU", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/SourceTest.php b/htdocs/includes/stripe/tests/Stripe/SourceTest.php deleted file mode 100644 index ad11b0d3455..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/SourceTest.php +++ /dev/null @@ -1,134 +0,0 @@ -expectsRequest( - 'get', - '/v1/sources/' . self::TEST_RESOURCE_ID - ); - $resource = Source::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\Source", $resource); - } - - public function testIsCreatable() - { - $this->expectsRequest( - 'post', - '/v1/sources' - ); - $resource = Source::create([ - "type" => "card" - ]); - $this->assertInstanceOf("Stripe\\Source", $resource); - } - - public function testIsSaveable() - { - $resource = Source::retrieve(self::TEST_RESOURCE_ID); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/sources/' . $resource->id - ); - $resource->save(); - $this->assertInstanceOf("Stripe\\Source", $resource); - } - - public function testIsUpdatable() - { - $this->expectsRequest( - 'post', - '/v1/sources/' . self::TEST_RESOURCE_ID - ); - $resource = Source::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - $this->assertInstanceOf("Stripe\\Source", $resource); - } - - public function testCanSaveCardExpiryDate() - { - $response = [ - 'id' => 'src_foo', - 'object' => 'source', - 'card' => [ - 'exp_month' => 8, - 'exp_year' => 2019, - ], - ]; - $source = Source::constructFrom($response); - - $response['card']['exp_month'] = 12; - $response['card']['exp_year'] = 2022; - $this->stubRequest( - 'POST', - '/v1/sources/src_foo', - [ - 'card' => [ - 'exp_month' => 12, - 'exp_year' => 2022, - ] - ], - null, - false, - $response - ); - - $source->card->exp_month = 12; - $source->card->exp_year = 2022; - $source->save(); - - $this->assertSame(12, $source->card->exp_month); - $this->assertSame(2022, $source->card->exp_year); - } - - public function testIsDetachableWhenAttached() - { - $resource = Source::retrieve(self::TEST_RESOURCE_ID); - $resource->customer = "cus_123"; - $this->expectsRequest( - 'delete', - '/v1/customers/cus_123/sources/' . $resource->id - ); - $resource->delete(); - $this->assertInstanceOf("Stripe\\Source", $resource); - } - - /** - * @expectedException \Stripe\Error\Api - */ - public function testIsNotDetachableWhenUnattached() - { - $resource = Source::retrieve(self::TEST_RESOURCE_ID); - $resource->detach(); - } - - public function testCanListSourceTransactions() - { - $source = Source::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'get', - '/v1/sources/' . $source->id . "/source_transactions" - ); - $resources = $source->sourceTransactions(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\SourceTransaction", $resources->data[0]); - } - - public function testCanVerify() - { - $resource = Source::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'post', - '/v1/sources/' . $resource->id . "/verify" - ); - $resource->verify(["values" => [32, 45]]); - $this->assertInstanceOf("Stripe\\Source", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/StripeObjectTest.php b/htdocs/includes/stripe/tests/Stripe/StripeObjectTest.php deleted file mode 100644 index af1cd936e1c..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/StripeObjectTest.php +++ /dev/null @@ -1,453 +0,0 @@ -deepCopyReflector = new \ReflectionMethod('Stripe\\StripeObject', 'deepCopy'); - $this->deepCopyReflector->setAccessible(true); - - // This is used to access the `_opts` protected variable - $this->optsReflector = new \ReflectionProperty('Stripe\\StripeObject', '_opts'); - $this->optsReflector->setAccessible(true); - } - - public function testArrayAccessorsSemantics() - { - $s = new StripeObject(); - $s['foo'] = 'a'; - $this->assertSame($s['foo'], 'a'); - $this->assertTrue(isset($s['foo'])); - unset($s['foo']); - $this->assertFalse(isset($s['foo'])); - } - - public function testNormalAccessorsSemantics() - { - $s = new StripeObject(); - $s->foo = 'a'; - $this->assertSame($s->foo, 'a'); - $this->assertTrue(isset($s->foo)); - unset($s->foo); - $this->assertFalse(isset($s->foo)); - } - - public function testArrayAccessorsMatchNormalAccessors() - { - $s = new StripeObject(); - $s->foo = 'a'; - $this->assertSame($s['foo'], 'a'); - - $s['bar'] = 'b'; - $this->assertSame($s->bar, 'b'); - } - - public function testCount() - { - $s = new StripeObject(); - $this->assertSame(0, count($s)); - - $s['key1'] = 'value1'; - $this->assertSame(1, count($s)); - - $s['key2'] = 'value2'; - $this->assertSame(2, count($s)); - - unset($s['key1']); - $this->assertSame(1, count($s)); - } - - public function testKeys() - { - $s = new StripeObject(); - $s->foo = 'bar'; - $this->assertSame($s->keys(), ['foo']); - } - - public function testValues() - { - $s = new StripeObject(); - $s->foo = 'bar'; - $this->assertSame($s->values(), ['bar']); - } - - public function testToArray() - { - $s = new StripeObject(); - $s->foo = 'a'; - - $converted = $s->__toArray(); - - $this->assertInternalType('array', $converted); - $this->assertArrayHasKey('foo', $converted); - $this->assertEquals('a', $converted['foo']); - } - - public function testRecursiveToArray() - { - $s = new StripeObject(); - $z = new StripeObject(); - - $s->child = $z; - $z->foo = 'a'; - - $converted = $s->__toArray(true); - - $this->assertInternalType('array', $converted); - $this->assertArrayHasKey('child', $converted); - $this->assertInternalType('array', $converted['child']); - $this->assertArrayHasKey('foo', $converted['child']); - $this->assertEquals('a', $converted['child']['foo']); - } - - public function testNonexistentProperty() - { - $s = new StripeObject(); - $this->assertNull($s->nonexistent); - } - - public function testPropertyDoesNotExists() - { - $s = new StripeObject(); - $this->assertNull($s['nonexistent']); - } - - public function testJsonEncode() - { - $s = new StripeObject(); - $s->foo = 'a'; - - $this->assertEquals('{"foo":"a"}', json_encode($s)); - } - - public function testToString() - { - $s = new StripeObject(); - $s->foo = 'a'; - - $string = $s->__toString(); - $expected = <<assertEquals($expected, $string); - } - - public function testReplaceNewNestedUpdatable() - { - $s = new StripeObject(); - - $s->metadata = ['bar']; - $this->assertSame($s->metadata, ['bar']); - $s->metadata = ['baz', 'qux']; - $this->assertSame($s->metadata, ['baz', 'qux']); - } - - /** - * @expectedException \InvalidArgumentException - */ - public function testSetPermanentAttribute() - { - $s = new StripeObject(); - $s->id = 'abc_123'; - } - - /** - * @expectedException \InvalidArgumentException - */ - public function testSetEmptyStringValue() - { - $s = new StripeObject(); - $s->foo = ''; - } - - public function testSerializeParametersOnEmptyObject() - { - $obj = StripeObject::constructFrom([]); - $this->assertSame([], $obj->serializeParameters()); - } - - public function testSerializeParametersOnNewObjectWithSubObject() - { - $obj = new StripeObject(); - $obj->metadata = ['foo' => 'bar']; - $this->assertSame(['metadata' => ['foo' => 'bar']], $obj->serializeParameters()); - } - - public function testSerializeParametersOnBasicObject() - { - $obj = StripeObject::constructFrom(['foo' => null]); - $obj->updateAttributes(['foo' => 'bar']); - $this->assertSame(['foo' => 'bar'], $obj->serializeParameters()); - } - - public function testSerializeParametersOnMoreComplexObject() - { - $obj = StripeObject::constructFrom([ - 'foo' => StripeObject::constructFrom([ - 'bar' => null, - 'baz' => null, - ]), - ]); - $obj->foo->bar = 'newbar'; - $this->assertSame(['foo' => ['bar' => 'newbar']], $obj->serializeParameters()); - } - - public function testSerializeParametersOnArray() - { - $obj = StripeObject::constructFrom([ - 'foo' => null, - ]); - $obj->foo = ['new-value']; - $this->assertSame(['foo' => ['new-value']], $obj->serializeParameters()); - } - - public function testSerializeParametersOnArrayThatShortens() - { - $obj = StripeObject::constructFrom([ - 'foo' => ['0-index', '1-index', '2-index'], - ]); - $obj->foo = ['new-value']; - $this->assertSame(['foo' => ['new-value']], $obj->serializeParameters()); - } - - public function testSerializeParametersOnArrayThatLengthens() - { - $obj = StripeObject::constructFrom([ - 'foo' => ['0-index', '1-index', '2-index'], - ]); - $obj->foo = array_fill(0, 4, 'new-value'); - $this->assertSame(['foo' => array_fill(0, 4, 'new-value')], $obj->serializeParameters()); - } - - public function testSerializeParametersOnArrayOfHashes() - { - $obj = StripeObject::constructFrom(['foo' => null]); - $obj->foo = [ - StripeObject::constructFrom(['bar' => null]), - ]; - - $obj->foo[0]->bar = 'baz'; - $this->assertSame(['foo' => [['bar' => 'baz']]], $obj->serializeParameters()); - } - - public function testSerializeParametersDoesNotIncludeUnchangedValues() - { - $obj = StripeObject::constructFrom([ - 'foo' => null, - ]); - $this->assertSame([], $obj->serializeParameters()); - } - - public function testSerializeParametersOnUnchangedArray() - { - $obj = StripeObject::constructFrom([ - 'foo' => ['0-index', '1-index', '2-index'], - ]); - $obj->foo = ['0-index', '1-index', '2-index']; - $this->assertSame([], $obj->serializeParameters()); - } - - public function testSerializeParametersWithStripeObject() - { - $obj = StripeObject::constructFrom([]); - $obj->metadata = StripeObject::constructFrom(['foo' => 'bar']); - - $serialized = $obj->serializeParameters(); - $this->assertSame(['foo' => 'bar'], $serialized['metadata']); - } - - public function testSerializeParametersOnReplacedStripeObject() - { - $obj = StripeObject::constructFrom([ - 'metadata' => StripeObject::constructFrom(['bar' => 'foo']), - ]); - $obj->metadata = StripeObject::constructFrom(['baz' => 'foo']); - - $serialized = $obj->serializeParameters(); - $this->assertSame(['bar' => '', 'baz' => 'foo'], $serialized['metadata']); - } - - public function testSerializeParametersOnArrayOfStripeObjects() - { - $obj = StripeObject::constructFrom([]); - $obj->metadata = [ - StripeObject::constructFrom(['foo' => 'bar']), - ]; - - $serialized = $obj->serializeParameters(); - $this->assertSame([['foo' => 'bar']], $serialized['metadata']); - } - - public function testSerializeParametersOnSetApiResource() - { - $customer = Customer::constructFrom(['id' => 'cus_123']); - $obj = StripeObject::constructFrom([]); - - // the key here is that the property is set explicitly (and therefore - // marked as unsaved), which is why it gets included below - $obj->customer = $customer; - - $serialized = $obj->serializeParameters(); - $this->assertSame(['customer' => $customer], $serialized); - } - - public function testSerializeParametersOnNotSetApiResource() - { - $customer = Customer::constructFrom(['id' => 'cus_123']); - $obj = StripeObject::constructFrom(['customer' => $customer]); - - $serialized = $obj->serializeParameters(); - $this->assertSame([], $serialized); - } - - public function testSerializeParametersOnApiResourceFlaggedWithSaveWithParent() - { - $customer = Customer::constructFrom(['id' => 'cus_123']); - $customer->saveWithParent = true; - - $obj = StripeObject::constructFrom(['customer' => $customer]); - - $serialized = $obj->serializeParameters(); - $this->assertSame(['customer' => []], $serialized); - } - - public function testSerializeParametersRaisesExceotionOnOtherEmbeddedApiResources() - { - // This customer doesn't have an ID and therefore the library doesn't know - // what to do with it and throws an InvalidArgumentException because it's - // probably not what the user expected to happen. - $customer = Customer::constructFrom([]); - - $obj = StripeObject::constructFrom([]); - $obj->customer = $customer; - - try { - $serialized = $obj->serializeParameters(); - $this->fail("Did not raise error"); - } catch (\InvalidArgumentException $e) { - $this->assertSame( - "Cannot save property `customer` containing an API resource of type Stripe\Customer. " . - "It doesn't appear to be persisted and is not marked as `saveWithParent`.", - $e->getMessage() - ); - } catch (\Exception $e) { - $this->fail("Unexpected exception: " . get_class($e)); - } - } - - public function testSerializeParametersForce() - { - $obj = StripeObject::constructFrom([ - 'id' => 'id', - 'metadata' => StripeObject::constructFrom([ - 'bar' => 'foo', - ]), - ]); - - $serialized = $obj->serializeParameters(true); - $this->assertSame(['id' => 'id', 'metadata' => ['bar' => 'foo']], $serialized); - } - - public function testDirty() - { - $obj = StripeObject::constructFrom([ - 'id' => 'id', - 'metadata' => StripeObject::constructFrom([ - 'bar' => 'foo', - ]), - ]); - - // note that `$force` and `dirty()` are for different things, but are - // functionally equivalent - $obj->dirty(); - - $serialized = $obj->serializeParameters(); - $this->assertSame(['id' => 'id', 'metadata' => ['bar' => 'foo']], $serialized); - } - - public function testDeepCopy() - { - $opts = [ - "api_base" => Stripe::$apiBase, - "api_key" => "apikey", - ]; - $values = [ - "id" => 1, - "name" => "Stripe", - "arr" => [ - StripeObject::constructFrom(["id" => "index0"], $opts), - "index1", - 2, - ], - "map" => [ - "0" => StripeObject::constructFrom(["id" => "index0"], $opts), - "1" => "index1", - "2" => 2 - ], - ]; - - $copyValues = $this->deepCopyReflector->invoke(null, $values); - - // we can't compare the hashes directly because they have embedded - // objects which are different from each other - $this->assertEquals($values["id"], $copyValues["id"]); - $this->assertEquals($values["name"], $copyValues["name"]); - $this->assertEquals(count($values["arr"]), count($copyValues["arr"])); - - // internal values of the copied StripeObject should be the same, - // but the object itself should be new (hence the assertNotSame) - $this->assertEquals($values["arr"][0]["id"], $copyValues["arr"][0]["id"]); - $this->assertNotSame($values["arr"][0], $copyValues["arr"][0]); - - // likewise, the Util\RequestOptions instance in _opts should have - // copied values but be a new instance - $this->assertEquals( - $this->optsReflector->getValue($values["arr"][0]), - $this->optsReflector->getValue($copyValues["arr"][0]) - ); - $this->assertNotSame( - $this->optsReflector->getValue($values["arr"][0]), - $this->optsReflector->getValue($copyValues["arr"][0]) - ); - - // scalars however, can be compared - $this->assertEquals($values["arr"][1], $copyValues["arr"][1]); - $this->assertEquals($values["arr"][2], $copyValues["arr"][2]); - - // and a similar story with the hash - $this->assertEquals($values["map"]["0"]["id"], $copyValues["map"]["0"]["id"]); - $this->assertNotSame($values["map"]["0"], $copyValues["map"]["0"]); - $this->assertNotSame( - $this->optsReflector->getValue($values["arr"][0]), - $this->optsReflector->getValue($copyValues["arr"][0]) - ); - $this->assertEquals( - $this->optsReflector->getValue($values["map"]["0"]), - $this->optsReflector->getValue($copyValues["map"]["0"]) - ); - $this->assertNotSame( - $this->optsReflector->getValue($values["map"]["0"]), - $this->optsReflector->getValue($copyValues["map"]["0"]) - ); - $this->assertEquals($values["map"]["1"], $copyValues["map"]["1"]); - $this->assertEquals($values["map"]["2"], $copyValues["map"]["2"]); - } - - public function testDeepCopyMaintainClass() - { - $charge = Charge::constructFrom(["id" => 1], null); - $copyCharge = $this->deepCopyReflector->invoke(null, $charge); - $this->assertEquals(get_class($charge), get_class($copyCharge)); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/StripeTest.php b/htdocs/includes/stripe/tests/Stripe/StripeTest.php deleted file mode 100644 index f594518d13d..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/StripeTest.php +++ /dev/null @@ -1,30 +0,0 @@ -orig = [ - 'caBundlePath' => Stripe::$caBundlePath, - ]; - } - - /** - * @after - */ - public function restoreOriginalValues() - { - Stripe::$caBundlePath = $this->orig['caBundlePath']; - } - - public function testCABundlePathAccessors() - { - Stripe::setCABundlePath('path/to/ca/bundle'); - $this->assertEquals('path/to/ca/bundle', Stripe::getCABundlePath()); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/SubscriptionItemTest.php b/htdocs/includes/stripe/tests/Stripe/SubscriptionItemTest.php deleted file mode 100644 index 09e766c1bec..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/SubscriptionItemTest.php +++ /dev/null @@ -1,77 +0,0 @@ -expectsRequest( - 'get', - '/v1/subscription_items' - ); - $resources = SubscriptionItem::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\SubscriptionItem", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/subscription_items/' . self::TEST_RESOURCE_ID - ); - $resource = SubscriptionItem::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\SubscriptionItem", $resource); - } - - public function testIsCreatable() - { - $this->expectsRequest( - 'post', - '/v1/subscription_items' - ); - $resource = SubscriptionItem::create([ - "plan" => "plan", - "subscription" => "sub_123" - ]); - $this->assertInstanceOf("Stripe\\SubscriptionItem", $resource); - } - - public function testIsSaveable() - { - $resource = SubscriptionItem::retrieve(self::TEST_RESOURCE_ID); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/subscription_items/' . $resource->id - ); - $resource->save(); - $this->assertInstanceOf("Stripe\\SubscriptionItem", $resource); - } - - public function testIsUpdatable() - { - $this->expectsRequest( - 'post', - '/v1/subscription_items/' . self::TEST_RESOURCE_ID - ); - $resource = SubscriptionItem::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - $this->assertInstanceOf("Stripe\\SubscriptionItem", $resource); - } - - public function testIsDeletable() - { - $resource = SubscriptionItem::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'delete', - '/v1/subscription_items/' . $resource->id - ); - $resource->delete(); - $this->assertInstanceOf("Stripe\\SubscriptionItem", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/SubscriptionTest.php b/htdocs/includes/stripe/tests/Stripe/SubscriptionTest.php deleted file mode 100644 index 4a42e218224..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/SubscriptionTest.php +++ /dev/null @@ -1,115 +0,0 @@ -expectsRequest( - 'get', - '/v1/subscriptions' - ); - $resources = Subscription::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\Subscription", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/subscriptions/' . self::TEST_RESOURCE_ID - ); - $resource = Subscription::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\Subscription", $resource); - } - - public function testIsCreatable() - { - $this->expectsRequest( - 'post', - '/v1/subscriptions' - ); - $resource = Subscription::create([ - "customer" => "cus_123", - "plan" => "plan" - ]); - $this->assertInstanceOf("Stripe\\Subscription", $resource); - } - - public function testIsSaveable() - { - $resource = Subscription::retrieve(self::TEST_RESOURCE_ID); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/subscriptions/' . $resource->id - ); - $resource->save(); - $this->assertInstanceOf("Stripe\\Subscription", $resource); - } - - public function testIsUpdatable() - { - $this->expectsRequest( - 'post', - '/v1/subscriptions/' . self::TEST_RESOURCE_ID - ); - $resource = Subscription::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - $this->assertInstanceOf("Stripe\\Subscription", $resource); - } - - public function testIsCancelable() - { - $resource = Subscription::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'delete', - '/v1/subscriptions/' . $resource->id, - [ - 'at_period_end' => 'true', - ] - ); - $resource->cancel([ - 'at_period_end' => true, - ]); - $this->assertInstanceOf("Stripe\\Subscription", $resource); - } - - public function testCanDeleteDiscount() - { - $resource = Subscription::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'delete', - '/v1/subscriptions/' . $resource->id . '/discount' - ); - $resource->deleteDiscount(); - $this->assertInstanceOf("Stripe\\Subscription", $resource); - } - - public function testSerializeParametersItems() - { - $obj = Util\Util::convertToStripeObject([ - 'object' => 'subscription', - 'items' => Util\Util::convertToStripeObject([ - 'object' => 'list', - 'data' => [], - ], null), - ], null); - $obj->items = [ - ['id' => 'si_foo', 'deleted' => true], - ['plan' => 'plan_bar'], - ]; - $expected = [ - 'items' => [ - 0 => ['id' => 'si_foo', 'deleted' => true], - 1 => ['plan' => 'plan_bar'], - ], - ]; - $this->assertSame($expected, $obj->serializeParameters()); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/ThreeDSecureTest.php b/htdocs/includes/stripe/tests/Stripe/ThreeDSecureTest.php deleted file mode 100644 index f56e649cbc1..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/ThreeDSecureTest.php +++ /dev/null @@ -1,32 +0,0 @@ -expectsRequest( - 'get', - '/v1/3d_secure/' . self::TEST_RESOURCE_ID - ); - $resource = ThreeDSecure::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\ThreeDSecure", $resource); - } - - public function testIsCreatable() - { - $this->expectsRequest( - 'post', - '/v1/3d_secure' - ); - $resource = ThreeDSecure::create([ - "amount" => 100, - "currency" => "usd", - "return_url" => "url" - ]); - $this->assertInstanceOf("Stripe\\ThreeDSecure", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/TokenTest.php b/htdocs/includes/stripe/tests/Stripe/TokenTest.php deleted file mode 100644 index 36bb4bc8283..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/TokenTest.php +++ /dev/null @@ -1,28 +0,0 @@ -expectsRequest( - 'get', - '/v1/tokens/' . self::TEST_RESOURCE_ID - ); - $resource = Token::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\Token", $resource); - } - - public function testIsCreatable() - { - $this->expectsRequest( - 'post', - '/v1/tokens' - ); - $resource = Token::create(["card" => "tok_visa"]); - $this->assertInstanceOf("Stripe\\Token", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/TopupTest.php b/htdocs/includes/stripe/tests/Stripe/TopupTest.php deleted file mode 100644 index 994447636c6..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/TopupTest.php +++ /dev/null @@ -1,69 +0,0 @@ -expectsRequest( - 'get', - '/v1/topups' - ); - $resources = Topup::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\Topup", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/topups/' . self::TEST_RESOURCE_ID - ); - $resource = Topup::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\Topup", $resource); - } - - public function testIsCreatable() - { - $this->expectsRequest( - 'post', - '/v1/topups' - ); - $resource = Topup::create([ - "amount" => 100, - "currency" => "usd", - "source" => "tok_123", - "description" => "description", - "statement_descriptor" => "statement descriptor" - ]); - $this->assertInstanceOf("Stripe\\Topup", $resource); - } - - public function testIsSaveable() - { - $resource = Topup::retrieve(self::TEST_RESOURCE_ID); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/topups/' . $resource->id - ); - $resource->save(); - $this->assertInstanceOf("Stripe\\Topup", $resource); - } - - public function testIsUpdatable() - { - $this->expectsRequest( - 'post', - '/v1/topups/' . self::TEST_RESOURCE_ID - ); - $resource = Topup::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - $this->assertInstanceOf("Stripe\\Topup", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/TransferReversalTest.php b/htdocs/includes/stripe/tests/Stripe/TransferReversalTest.php deleted file mode 100644 index 37101c73208..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/TransferReversalTest.php +++ /dev/null @@ -1,21 +0,0 @@ -metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/transfers/' . $resource->transfer . '/reversals/' . $resource->id - ); - $resource->save(); - $this->assertInstanceOf("Stripe\\TransferReversal", $resource); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/TransferTest.php b/htdocs/includes/stripe/tests/Stripe/TransferTest.php deleted file mode 100644 index d60d560e7c5..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/TransferTest.php +++ /dev/null @@ -1,140 +0,0 @@ -expectsRequest( - 'get', - '/v1/transfers' - ); - $resources = Transfer::all(); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\Transfer", $resources->data[0]); - } - - public function testIsRetrievable() - { - $this->expectsRequest( - 'get', - '/v1/transfers/' . self::TEST_RESOURCE_ID - ); - $resource = Transfer::retrieve(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\Transfer", $resource); - } - - public function testIsCreatable() - { - $this->expectsRequest( - 'post', - '/v1/transfers' - ); - $resource = Transfer::create([ - "amount" => 100, - "currency" => "usd", - "destination" => "acct_123" - ]); - $this->assertInstanceOf("Stripe\\Transfer", $resource); - } - - public function testIsSaveable() - { - $resource = Transfer::retrieve(self::TEST_RESOURCE_ID); - $resource->metadata["key"] = "value"; - $this->expectsRequest( - 'post', - '/v1/transfers/' . $resource->id - ); - $resource->save(); - $this->assertInstanceOf("Stripe\\Transfer", $resource); - } - - public function testIsUpdatable() - { - $this->expectsRequest( - 'post', - '/v1/transfers/' . self::TEST_RESOURCE_ID - ); - $resource = Transfer::update(self::TEST_RESOURCE_ID, [ - "metadata" => ["key" => "value"], - ]); - $this->assertInstanceOf("Stripe\\Transfer", $resource); - } - - public function testIsReversable() - { - $resource = Transfer::retrieve(self::TEST_RESOURCE_ID); - $this->expectsRequest( - 'post', - '/v1/transfers/' . $resource->id . '/reversals' - ); - $resource->reverse(); - $this->assertInstanceOf("Stripe\\Transfer", $resource); - } - - public function testIsCancelable() - { - $transfer = Transfer::retrieve(self::TEST_RESOURCE_ID); - - // stripe-mock does not support this anymore so we stub it - $this->stubRequest( - 'post', - '/v1/transfers/' . $transfer->id . '/cancel' - ); - $resource = $transfer->cancel(); - $this->assertInstanceOf("Stripe\\Transfer", $resource); - $this->assertSame($resource, $transfer); - } - - public function testCanCreateReversal() - { - $this->expectsRequest( - 'post', - '/v1/transfers/' . self::TEST_RESOURCE_ID . '/reversals' - ); - $resource = Transfer::createReversal(self::TEST_RESOURCE_ID); - $this->assertInstanceOf("Stripe\\TransferReversal", $resource); - } - - public function testCanRetrieveReversal() - { - $this->expectsRequest( - 'get', - '/v1/transfers/' . self::TEST_RESOURCE_ID . '/reversals/' . self::TEST_REVERSAL_ID - ); - $resource = Transfer::retrieveReversal(self::TEST_RESOURCE_ID, self::TEST_REVERSAL_ID); - $this->assertInstanceOf("Stripe\\TransferReversal", $resource); - } - - public function testCanUpdateReversal() - { - $this->expectsRequest( - 'post', - '/v1/transfers/' . self::TEST_RESOURCE_ID . '/reversals/' . self::TEST_REVERSAL_ID - ); - $resource = Transfer::updateReversal( - self::TEST_RESOURCE_ID, - self::TEST_REVERSAL_ID, - [ - "metadata" => ["key" => "value"], - ] - ); - $this->assertInstanceOf("Stripe\\TransferReversal", $resource); - } - - public function testCanListReversal() - { - $this->expectsRequest( - 'get', - '/v1/transfers/' . self::TEST_RESOURCE_ID . '/reversals' - ); - $resources = Transfer::allReversals(self::TEST_RESOURCE_ID); - $this->assertTrue(is_array($resources->data)); - $this->assertInstanceOf("Stripe\\TransferReversal", $resources->data[0]); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/Util/DefaultLoggerTest.php b/htdocs/includes/stripe/tests/Stripe/Util/DefaultLoggerTest.php deleted file mode 100644 index 711af03c4a0..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/Util/DefaultLoggerTest.php +++ /dev/null @@ -1,28 +0,0 @@ -error("message"); - - global $lastMessage; - $this->assertSame($lastMessage, "message"); - } -} - -// This is a little terrible, but unfortunately there's no clean way to stub a -// call to `error_log`. Here we overwrite it so that we can get the last arguments -// that went to it. This is obviously bad, but luckily it's constrained to -// being just in \Stripe\Util (i.e. won't interfere with PHPUnit for example) -// and _just_ present when tests are running. -function error_log($message) -{ - global $lastMessage; - $lastMessage = $message; -} diff --git a/htdocs/includes/stripe/tests/Stripe/Util/RequestOptionsTest.php b/htdocs/includes/stripe/tests/Stripe/Util/RequestOptionsTest.php deleted file mode 100644 index 558f73982ea..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/Util/RequestOptionsTest.php +++ /dev/null @@ -1,81 +0,0 @@ -assertSame("foo", $opts->apiKey); - $this->assertSame([], $opts->headers); - } - - public function testNull() - { - $opts = Util\RequestOptions::parse(null); - $this->assertSame(null, $opts->apiKey); - $this->assertSame([], $opts->headers); - } - - public function testEmptyArray() - { - $opts = Util\RequestOptions::parse([]); - $this->assertSame(null, $opts->apiKey); - $this->assertSame([], $opts->headers); - } - - public function testAPIKeyArray() - { - $opts = Util\RequestOptions::parse( - [ - 'api_key' => 'foo', - ] - ); - $this->assertSame('foo', $opts->apiKey); - $this->assertSame([], $opts->headers); - } - - public function testIdempotentKeyArray() - { - $opts = Util\RequestOptions::parse( - [ - 'idempotency_key' => 'foo', - ] - ); - $this->assertSame(null, $opts->apiKey); - $this->assertSame(['Idempotency-Key' => 'foo'], $opts->headers); - } - - public function testKeyArray() - { - $opts = Util\RequestOptions::parse( - [ - 'idempotency_key' => 'foo', - 'api_key' => 'foo' - ] - ); - $this->assertSame('foo', $opts->apiKey); - $this->assertSame(['Idempotency-Key' => 'foo'], $opts->headers); - } - - /** - * @expectedException Stripe\Error\Api - */ - public function testWrongType() - { - $opts = Util\RequestOptions::parse(5); - } - - public function testDiscardNonPersistentHeaders() - { - $opts = Util\RequestOptions::parse( - [ - 'stripe_account' => 'foo', - 'idempotency_key' => 'foo', - ] - ); - $opts->discardNonPersistentHeaders(); - $this->assertSame(['Stripe-Account' => 'foo'], $opts->headers); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/Util/UtilTest.php b/htdocs/includes/stripe/tests/Stripe/Util/UtilTest.php deleted file mode 100644 index cf5130208db..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/Util/UtilTest.php +++ /dev/null @@ -1,90 +0,0 @@ -assertTrue(Util\Util::isList($list)); - - $notlist = [5, 'nstaoush', [], 'bar' => 'baz']; - $this->assertFalse(Util\Util::isList($notlist)); - } - - public function testThatPHPHasValueSemanticsForArrays() - { - $original = ['php-arrays' => 'value-semantics']; - $derived = $original; - $derived['php-arrays'] = 'reference-semantics'; - - $this->assertSame('value-semantics', $original['php-arrays']); - } - - public function testConvertStripeObjectToArrayIncludesId() - { - $customer = Util\Util::convertToStripeObject([ - 'id' => 'cus_123', - 'object' => 'customer', - ], null); - $this->assertTrue(array_key_exists("id", $customer->__toArray(true))); - } - - public function testUtf8() - { - // UTF-8 string - $x = "\xc3\xa9"; - $this->assertSame(Util\Util::utf8($x), $x); - - // Latin-1 string - $x = "\xe9"; - $this->assertSame(Util\Util::utf8($x), "\xc3\xa9"); - - // Not a string - $x = true; - $this->assertSame(Util\Util::utf8($x), $x); - } - - public function testUrlEncode() - { - $a = [ - 'my' => 'value', - 'that' => ['your' => 'example'], - 'bar' => 1, - 'baz' => null - ]; - - $enc = Util\Util::urlEncode($a); - $this->assertSame('my=value&that%5Byour%5D=example&bar=1', $enc); - - $a = ['that' => ['your' => 'example', 'foo' => null]]; - $enc = Util\Util::urlEncode($a); - $this->assertSame('that%5Byour%5D=example', $enc); - - $a = ['that' => 'example', 'foo' => ['bar', 'baz']]; - $enc = Util\Util::urlEncode($a); - $this->assertSame('that=example&foo%5B%5D=bar&foo%5B%5D=baz', $enc); - - $a = [ - 'my' => 'value', - 'that' => ['your' => ['cheese', 'whiz', null]], - 'bar' => 1, - 'baz' => null - ]; - - $enc = Util\Util::urlEncode($a); - $expected = 'my=value&that%5Byour%5D%5B%5D=cheese' - . '&that%5Byour%5D%5B%5D=whiz&bar=1'; - $this->assertSame($expected, $enc); - - // Ignores an empty array - $enc = Util\Util::urlEncode(['foo' => [], 'bar' => 'baz']); - $expected = 'bar=baz'; - $this->assertSame($expected, $enc); - - $a = ['foo' => [['bar' => 'baz'], ['bar' => 'bin']]]; - $enc = Util\Util::urlEncode($a); - $this->assertSame('foo%5B0%5D%5Bbar%5D=baz&foo%5B1%5D%5Bbar%5D=bin', $enc); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/WebhookTest.php b/htdocs/includes/stripe/tests/Stripe/WebhookTest.php deleted file mode 100644 index dcd82671afc..00000000000 --- a/htdocs/includes/stripe/tests/Stripe/WebhookTest.php +++ /dev/null @@ -1,110 +0,0 @@ -generateHeader(); - $event = Webhook::constructEvent(self::EVENT_PAYLOAD, $sigHeader, self::SECRET); - $this->assertEquals("evt_test_webhook", $event->id); - } - - /** - * @expectedException \UnexpectedValueException - */ - public function testInvalidJson() - { - $payload = "this is not valid JSON"; - $sigHeader = $this->generateHeader(["payload" => $payload]); - Webhook::constructEvent($payload, $sigHeader, self::SECRET); - } - - /** - * @expectedException \Stripe\Error\SignatureVerification - */ - public function testValidJsonAndInvalidHeader() - { - $sigHeader = "bad_header"; - Webhook::constructEvent(self::EVENT_PAYLOAD, $sigHeader, self::SECRET); - } - - /** - * @expectedException \Stripe\Error\SignatureVerification - * @expectedExceptionMessage Unable to extract timestamp and signatures from header - */ - public function testMalformedHeader() - { - $sigHeader = "i'm not even a real signature header"; - WebhookSignature::verifyHeader(self::EVENT_PAYLOAD, $sigHeader, self::SECRET); - } - - /** - * @expectedException \Stripe\Error\SignatureVerification - * @expectedExceptionMessage No signatures found with expected scheme - */ - public function testNoSignaturesWithExpectedScheme() - { - $sigHeader = $this->generateHeader(["scheme" => "v0"]); - WebhookSignature::verifyHeader(self::EVENT_PAYLOAD, $sigHeader, self::SECRET); - } - - /** - * @expectedException \Stripe\Error\SignatureVerification - * @expectedExceptionMessage No signatures found matching the expected signature for payload - */ - public function testNoValidSignatureForPayload() - { - $sigHeader = $this->generateHeader(["signature" => "bad_signature"]); - WebhookSignature::verifyHeader(self::EVENT_PAYLOAD, $sigHeader, self::SECRET); - } - - /** - * @expectedException \Stripe\Error\SignatureVerification - * @expectedExceptionMessage Timestamp outside the tolerance zone - */ - public function testTimestampOutsideTolerance() - { - $sigHeader = $this->generateHeader(["timestamp" => time() - 15]); - WebhookSignature::verifyHeader(self::EVENT_PAYLOAD, $sigHeader, self::SECRET, 10); - } - - public function testValidHeaderAndSignature() - { - $sigHeader = $this->generateHeader(); - $this->assertTrue(WebhookSignature::verifyHeader(self::EVENT_PAYLOAD, $sigHeader, self::SECRET, 10)); - } - - public function testHeaderContainsValidSignature() - { - $sigHeader = $this->generateHeader() . ",v1=bad_signature"; - $this->assertTrue(WebhookSignature::verifyHeader(self::EVENT_PAYLOAD, $sigHeader, self::SECRET, 10)); - } - - public function testTimestampOffButNoTolerance() - { - $sigHeader = $this->generateHeader(["timestamp" => 12345]); - $this->assertTrue(WebhookSignature::verifyHeader(self::EVENT_PAYLOAD, $sigHeader, self::SECRET)); - } -} diff --git a/htdocs/includes/stripe/tests/TestCase.php b/htdocs/includes/stripe/tests/TestCase.php deleted file mode 100644 index 840c0ec58c1..00000000000 --- a/htdocs/includes/stripe/tests/TestCase.php +++ /dev/null @@ -1,177 +0,0 @@ -origApiBase = Stripe::$apiBase; - $this->origApiKey = Stripe::getApiKey(); - $this->origClientId = Stripe::getClientId(); - $this->origApiVersion = Stripe::getApiVersion(); - $this->origAccountId = Stripe::getAccountId(); - - // Set up host and credentials for stripe-mock - Stripe::$apiBase = "http://localhost:" . MOCK_PORT; - Stripe::setApiKey("sk_test_123"); - Stripe::setClientId("ca_123"); - Stripe::setApiVersion(null); - Stripe::setAccountId(null); - - // Set up the HTTP client mocker - $this->clientMock = $this->getMock('\Stripe\HttpClient\ClientInterface'); - - // By default, use the real HTTP client - ApiRequestor::setHttpClient(HttpClient\CurlClient::instance()); - } - - protected function tearDown() - { - // Restore original values - Stripe::$apiBase = $this->origApiBase; - Stripe::setApiKey($this->origApiKey); - Stripe::setClientId($this->origClientId); - Stripe::setApiVersion($this->origApiVersion); - Stripe::setAccountId($this->origAccountId); - } - - /** - * Sets up a request expectation with the provided parameters. The request - * will actually go through and be emitted. - * - * @param string $method HTTP method (e.g. 'post', 'get', etc.) - * @param string $path relative path (e.g. '/v1/charges') - * @param array|null $params array of parameters. If null, parameters will - * not be checked. - * @param string[]|null $headers array of headers. Does not need to be - * exhaustive. If null, headers are not checked. - * @param bool $hasFile Whether the request parameters contains a file. - * Defaults to false. - */ - protected function expectsRequest( - $method, - $path, - $params = null, - $headers = null, - $hasFile = false - ) { - $this->prepareRequestMock($method, $path, $params, $headers, $hasFile) - ->will($this->returnCallback( - function ($method, $absUrl, $headers, $params, $hasFile) { - $curlClient = HttpClient\CurlClient::instance(); - ApiRequestor::setHttpClient($curlClient); - return $curlClient->request($method, $absUrl, $headers, $params, $hasFile); - } - )); - } - - /** - * Sets up a request expectation with the provided parameters. The request - * will not actually be emitted, instead the provided response parameters - * will be returned. - * - * @param string $method HTTP method (e.g. 'post', 'get', etc.) - * @param string $path relative path (e.g. '/v1/charges') - * @param array|null $params array of parameters. If null, parameters will - * not be checked. - * @param string[]|null $headers array of headers. Does not need to be - * exhaustive. If null, headers are not checked. - * @param bool $hasFile Whether the request parameters contains a file. - * Defaults to false. - * @param array $response - * @param integer $rcode - * @param string|null $base - * - * @return array - */ - protected function stubRequest( - $method, - $path, - $params = null, - $headers = null, - $hasFile = false, - $response = [], - $rcode = 200, - $base = null - ) { - $this->prepareRequestMock($method, $path, $params, $headers, $hasFile, $base) - ->willReturn([json_encode($response), $rcode, []]); - } - - /** - * Prepares the client mocker for an invocation of the `request` method. - * This helper method is used by both `expectsRequest` and `stubRequest` to - * prepare the client mocker to expect an invocation of the `request` method - * with the provided arguments. - * - * @param string $method HTTP method (e.g. 'post', 'get', etc.) - * @param string $path relative path (e.g. '/v1/charges') - * @param array|null $params array of parameters. If null, parameters will - * not be checked. - * @param string[]|null $headers array of headers. Does not need to be - * exhaustive. If null, headers are not checked. - * @param bool $hasFile Whether the request parameters contains a file. - * Defaults to false. - * @param string|null $base base URL (e.g. 'https://api.stripe.com') - * - * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker - */ - private function prepareRequestMock( - $method, - $path, - $params = null, - $headers = null, - $hasFile = false, - $base = null - ) { - ApiRequestor::setHttpClient($this->clientMock); - - if ($base === null) { - $base = Stripe::$apiBase; - } - $absUrl = $base . $path; - - return $this->clientMock - ->expects($this->once()) - ->method('request') - ->with( - $this->identicalTo(strtolower($method)), - $this->identicalTo($absUrl), - // for headers, we only check that all of the headers provided in $headers are - // present in the list of headers of the actual request - $headers === null ? $this->anything() : $this->callback(function ($array) use ($headers) { - foreach ($headers as $header) { - if (!in_array($header, $array)) { - return false; - } - } - return true; - }), - $params === null ? $this->anything() : $this->identicalTo($params), - $this->identicalTo($hasFile) - ); - } -} diff --git a/htdocs/includes/stripe/tests/bootstrap.no_autoload.php b/htdocs/includes/stripe/tests/bootstrap.no_autoload.php deleted file mode 100644 index 7011a3f4782..00000000000 --- a/htdocs/includes/stripe/tests/bootstrap.no_autoload.php +++ /dev/null @@ -1,5 +0,0 @@ -s01R$Gz9%CSj!PC{xWt~$(697H@6ZHT9 diff --git a/htdocs/langs/en_US/paypal.lang b/htdocs/langs/en_US/paypal.lang index 1f8a9c2bd35..de2f0b19958 100644 --- a/htdocs/langs/en_US/paypal.lang +++ b/htdocs/langs/en_US/paypal.lang @@ -33,4 +33,4 @@ PaypalImportPayment=Import PayPal payments PostActionAfterPayment=Post actions after payments ARollbackWasPerformedOnPostActions=A rollback was performed on all Post actions. You must complete post actions manually if they are necessary. ValidationOfPaymentFailed=Validation of payment has failed -CardOwner=Card owner +CardOwner=Card holder diff --git a/htdocs/paypal/lib/paypal.lib.php b/htdocs/paypal/lib/paypal.lib.php index d3942e560ed..7d5a81dab25 100644 --- a/htdocs/paypal/lib/paypal.lib.php +++ b/htdocs/paypal/lib/paypal.lib.php @@ -88,7 +88,7 @@ function showPaypalPaymentUrl($type, $ref) * @param string $freetag Free tag * @return string Url string */ -function getPaypalPaymentUrl($mode, $type, $ref = '', $amount = '9.99', $freetag = 'your_free_tag') +function getPaypalPaymentUrl($mode, $type, $ref = '', $amount = '9.99', $freetag = 'your_tag') { global $conf; diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index 8489f0ef071..374556c3342 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -188,7 +188,7 @@ if ((empty($paymentmethod) || $paymentmethod == 'paybox') && ! empty($conf->payb { $langs->load("paybox"); - // TODO + // TODO Chek setup is complete $validpaymentmethod['paybox']='valid'; } @@ -425,187 +425,238 @@ if ($action == 'charge' && ! empty($conf->stripe->enabled)) $error = 0; $errormessage = ''; - try { - $metadata = array( - 'dol_version' => DOL_VERSION, - 'dol_entity' => $conf->entity, - 'dol_company' => $mysoc->name, // Usefull when using multicompany - 'ipaddress'=> getUserRemoteIP() - ); + if (empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) + { + try { + $metadata = array( + 'dol_version' => DOL_VERSION, + 'dol_entity' => $conf->entity, + 'dol_company' => $mysoc->name, // Usefull when using multicompany + 'ipaddress'=> getUserRemoteIP() + ); - if (! empty($thirdparty_id)) $metadata["dol_thirdparty_id"] = $thirdparty_id; + if (! empty($thirdparty_id)) $metadata["dol_thirdparty_id"] = $thirdparty_id; - if ($thirdparty_id > 0) - { - dol_syslog("Search existing Stripe customer profile for thirdparty_id=".$thirdparty_id, LOG_DEBUG, 0, '_stripe'); + if ($thirdparty_id > 0) + { + dol_syslog("Search existing Stripe customer profile for thirdparty_id=".$thirdparty_id, LOG_DEBUG, 0, '_stripe'); - $service = 'StripeTest'; - $servicestatus = 0; - if (! empty($conf->global->STRIPE_LIVE) && ! GETPOST('forcesandbox', 'int')) - { - $service = 'StripeLive'; - $servicestatus = 1; - } + $service = 'StripeTest'; + $servicestatus = 0; + if (! empty($conf->global->STRIPE_LIVE) && ! GETPOST('forcesandbox', 'int')) + { + $service = 'StripeLive'; + $servicestatus = 1; + } - $thirdparty = new Societe($db); - $thirdparty->fetch($thirdparty_id); + $thirdparty = new Societe($db); + $thirdparty->fetch($thirdparty_id); - // Create Stripe customer - include_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; - $stripe = new Stripe($db); - $stripeacc = $stripe->getStripeAccount($service); - $customer = $stripe->customerStripe($thirdparty, $stripeacc, $servicestatus, 1); + // Create Stripe customer + include_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; + $stripe = new Stripe($db); + $stripeacc = $stripe->getStripeAccount($service); + $customer = $stripe->customerStripe($thirdparty, $stripeacc, $servicestatus, 1); - // Create Stripe card from Token - if ($savesource) { - $card = $customer->sources->create(array("source" => $stripeToken, "metadata" => $metadata)); - } else { - $card = $stripeToken; - } + // Create Stripe card from Token + if ($savesource) { + $card = $customer->sources->create(array("source" => $stripeToken, "metadata" => $metadata)); + } else { + $card = $stripeToken; + } - if (empty($card)) - { - $error++; - dol_syslog('Failed to create card record', LOG_WARNING, 0, '_stripe'); - setEventMessages('Failed to create card record', null, 'errors'); - $action=''; - } - else - { - if (! empty($FULLTAG)) $metadata["FULLTAG"] = $FULLTAG; - if (! empty($dol_id)) $metadata["dol_id"] = $dol_id; - if (! empty($dol_type)) $metadata["dol_type"] = $dol_type; + if (empty($card)) + { + $error++; + dol_syslog('Failed to create card record', LOG_WARNING, 0, '_stripe'); + setEventMessages('Failed to create card record', null, 'errors'); + $action=''; + } + else + { + if (! empty($FULLTAG)) $metadata["FULLTAG"] = $FULLTAG; + if (! empty($dol_id)) $metadata["dol_id"] = $dol_id; + if (! empty($dol_type)) $metadata["dol_type"] = $dol_type; - dol_syslog("Create charge on card ".$card->id, LOG_DEBUG, 0, '_stripe'); - $charge = \Stripe\Charge::create(array( - 'amount' => price2num($amountstripe, 'MU'), - 'currency' => $currency, - 'capture' => true, // Charge immediatly - 'description' => 'Stripe payment: '.$FULLTAG.' ref='.$ref, - 'metadata' => $metadata, - 'customer' => $customer->id, - 'source' => $card, - 'statement_descriptor' => dol_trunc($FULLTAG, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description) - ), array("idempotency_key" => "$FULLTAG", "stripe_account" => "$stripeacc")); - // Return $charge = array('id'=>'ch_XXXX', 'status'=>'succeeded|pending|failed', 'failure_code'=>, 'failure_message'=>...) - if (empty($charge)) - { - $error++; - dol_syslog('Failed to charge card', LOG_WARNING, 0, '_stripe'); - setEventMessages('Failed to charge card', null, 'errors'); - $action=''; - } - } - } - else - { - $vatcleaned = $vatnumber ? $vatnumber : null; + dol_syslog("Create charge on card ".$card->id, LOG_DEBUG, 0, '_stripe'); + $charge = \Stripe\Charge::create(array( + 'amount' => price2num($amountstripe, 'MU'), + 'currency' => $currency, + 'capture' => true, // Charge immediatly + 'description' => 'Stripe payment: '.$FULLTAG.' ref='.$ref, + 'metadata' => $metadata, + 'customer' => $customer->id, + 'source' => $card, + 'statement_descriptor' => dol_trunc($FULLTAG, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description) + ), array("idempotency_key" => "$FULLTAG", "stripe_account" => "$stripeacc")); + // Return $charge = array('id'=>'ch_XXXX', 'status'=>'succeeded|pending|failed', 'failure_code'=>, 'failure_message'=>...) + if (empty($charge)) + { + $error++; + dol_syslog('Failed to charge card', LOG_WARNING, 0, '_stripe'); + setEventMessages('Failed to charge card', null, 'errors'); + $action=''; + } + } + } + else + { + $vatcleaned = $vatnumber ? $vatnumber : null; - $taxinfo = array('type'=>'vat'); - if ($vatcleaned) - { - $taxinfo["tax_id"] = $vatcleaned; - } - // We force data to "null" if not defined as expected by Stripe - if (empty($vatcleaned)) $taxinfo=null; + $taxinfo = array('type'=>'vat'); + if ($vatcleaned) + { + $taxinfo["tax_id"] = $vatcleaned; + } + // We force data to "null" if not defined as expected by Stripe + if (empty($vatcleaned)) $taxinfo=null; - dol_syslog("Create anonymous customer card profile", LOG_DEBUG, 0, '_stripe'); - $customer = \Stripe\Customer::create(array( - 'email' => $email, - 'description' => ($email?'Anonymous customer for '.$email:'Anonymous customer'), - 'metadata' => $metadata, - 'tax_info' => $taxinfo, - 'source' => $stripeToken // source can be a token OR array('object'=>'card', 'exp_month'=>xx, 'exp_year'=>xxxx, 'number'=>xxxxxxx, 'cvc'=>xxx, 'name'=>'Cardholder's full name', zip ?) - )); - // Return $customer = array('id'=>'cus_XXXX', ...) + dol_syslog("Create anonymous customer card profile", LOG_DEBUG, 0, '_stripe'); + $customer = \Stripe\Customer::create(array( + 'email' => $email, + 'description' => ($email?'Anonymous customer for '.$email:'Anonymous customer'), + 'metadata' => $metadata, + 'tax_info' => $taxinfo, + 'source' => $stripeToken // source can be a token OR array('object'=>'card', 'exp_month'=>xx, 'exp_year'=>xxxx, 'number'=>xxxxxxx, 'cvc'=>xxx, 'name'=>'Cardholder's full name', zip ?) + )); + // Return $customer = array('id'=>'cus_XXXX', ...) - if (! empty($FULLTAG)) $metadata["FULLTAG"] = $FULLTAG; - if (! empty($dol_id)) $metadata["dol_id"] = $dol_id; - if (! empty($dol_type)) $metadata["dol_type"] = $dol_type; + if (! empty($FULLTAG)) $metadata["FULLTAG"] = $FULLTAG; + if (! empty($dol_id)) $metadata["dol_id"] = $dol_id; + if (! empty($dol_type)) $metadata["dol_type"] = $dol_type; - // The customer was just created with a source, so we can make a charge - // with no card defined, the source just used for customer creation will be used. - dol_syslog("Create charge", LOG_DEBUG, 0, '_stripe'); - $charge = \Stripe\Charge::create(array( - 'customer' => $customer->id, - 'amount' => price2num($amountstripe, 'MU'), - 'currency' => $currency, - 'capture' => true, // Charge immediatly - 'description' => 'Stripe payment: '.$FULLTAG.' ref='.$ref, - 'metadata' => $metadata, - 'statement_descriptor' => dol_trunc($FULLTAG, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description) - ), array("idempotency_key" => "$FULLTAG", "stripe_account" => "$stripeacc")); - // Return $charge = array('id'=>'ch_XXXX', 'status'=>'succeeded|pending|failed', 'failure_code'=>, 'failure_message'=>...) - if (empty($charge)) - { - $error++; - dol_syslog('Failed to charge card', LOG_WARNING, 0, '_stripe'); - setEventMessages('Failed to charge card', null, 'errors'); - $action=''; - } - } - } catch(\Stripe\Error\Card $e) { - // Since it's a decline, \Stripe\Error\Card will be caught - $body = $e->getJsonBody(); - $err = $body['error']; + // The customer was just created with a source, so we can make a charge + // with no card defined, the source just used for customer creation will be used. + dol_syslog("Create charge", LOG_DEBUG, 0, '_stripe'); + $charge = \Stripe\Charge::create(array( + 'customer' => $customer->id, + 'amount' => price2num($amountstripe, 'MU'), + 'currency' => $currency, + 'capture' => true, // Charge immediatly + 'description' => 'Stripe payment: '.$FULLTAG.' ref='.$ref, + 'metadata' => $metadata, + 'statement_descriptor' => dol_trunc($FULLTAG, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description) + ), array("idempotency_key" => "$FULLTAG", "stripe_account" => "$stripeacc")); + // Return $charge = array('id'=>'ch_XXXX', 'status'=>'succeeded|pending|failed', 'failure_code'=>, 'failure_message'=>...) + if (empty($charge)) + { + $error++; + dol_syslog('Failed to charge card', LOG_WARNING, 0, '_stripe'); + setEventMessages('Failed to charge card', null, 'errors'); + $action=''; + } + } + } catch(\Stripe\Error\Card $e) { + // Since it's a decline, \Stripe\Error\Card will be caught + $body = $e->getJsonBody(); + $err = $body['error']; - print('Status is:' . $e->getHttpStatus() . "\n"); - print('Type is:' . $err['type'] . "\n"); - print('Code is:' . $err['code'] . "\n"); - // param is '' in this case - print('Param is:' . $err['param'] . "\n"); - print('Message is:' . $err['message'] . "\n"); + print('Status is:' . $e->getHttpStatus() . "\n"); + print('Type is:' . $err['type'] . "\n"); + print('Code is:' . $err['code'] . "\n"); + // param is '' in this case + print('Param is:' . $err['param'] . "\n"); + print('Message is:' . $err['message'] . "\n"); + + $error++; + $errormessage="ErrorCard ".$e->getMessage()." err=".var_export($err, true); + dol_syslog($errormessage, LOG_WARNING, 0, '_stripe'); + setEventMessages($e->getMessage(), null, 'errors'); + $action=''; + } catch (\Stripe\Error\RateLimit $e) { + // Too many requests made to the API too quickly + $error++; + $errormessage="ErrorRateLimit ".$e->getMessage(); + dol_syslog($errormessage, LOG_WARNING, 0, '_stripe'); + setEventMessages($e->getMessage(), null, 'errors'); + $action=''; + } catch (\Stripe\Error\InvalidRequest $e) { + // Invalid parameters were supplied to Stripe's API + $error++; + $errormessage="ErrorInvalidRequest ".$e->getMessage(); + dol_syslog($errormessage, LOG_WARNING, 0, '_stripe'); + setEventMessages($e->getMessage(), null, 'errors'); + $action=''; + } catch (\Stripe\Error\Authentication $e) { + // Authentication with Stripe's API failed + // (maybe you changed API keys recently) + $error++; + $errormessage="ErrorAuthentication ".$e->getMessage(); + dol_syslog($errormessage, LOG_WARNING, 0, '_stripe'); + setEventMessages($e->getMessage(), null, 'errors'); + $action=''; + } catch (\Stripe\Error\ApiConnection $e) { + // Network communication with Stripe failed + $error++; + $errormessage="ErrorApiConnection ".$e->getMessage(); + dol_syslog($errormessage, LOG_WARNING, 0, '_stripe'); + setEventMessages($e->getMessage(), null, 'errors'); + $action=''; + } catch (\Stripe\Error\Base $e) { + // Display a very generic error to the user, and maybe send + // yourself an email + $error++; + $errormessage="ErrorBase ".$e->getMessage(); + dol_syslog($errormessage, LOG_WARNING, 0, '_stripe'); + setEventMessages($e->getMessage(), null, 'errors'); + $action=''; + } catch (Exception $e) { + // Something else happened, completely unrelated to Stripe + $error++; + $errormessage="ErrorException ".$e->getMessage(); + dol_syslog($errormessage, LOG_WARNING, 0, '_stripe'); + setEventMessages($e->getMessage(), null, 'errors'); + $action=''; + } + } + + if (! empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) + { + $service = 'StripeTest'; + $servicestatus = 0; + if (! empty($conf->global->STRIPE_LIVE) && ! GETPOST('forcesandbox', 'int')) + { + $service = 'StripeLive'; + $servicestatus = 1; + } + include_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; + $stripe = new Stripe($db); + $stripeacc = $stripe->getStripeAccount($service); + + // We go here if $conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION is set. + // In such a case, payment is always ok when we call the "charge" action. + $paymentintent_id = GETPOST("paymentintent_id", "alpha"); + + // Force to use the correct API key + global $stripearrayofkeysbyenv; + \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$servicestatus]['secret_key']); + + try { + if (empty($key)) { // If the Stripe connect account not set, we use common API usage + $paymentintent = \Stripe\PaymentIntent::retrieve($paymentintent_id); + } else { + $paymentintent = \Stripe\PaymentIntent::retrieve($paymentintent_id, array("stripe_account" => $stripeacc)); + } + } + catch(Exception $e) + { + $error++; + $errormessage="CantRetreivePaymentIntent ".$e->getMessage(); + dol_syslog($errormessage, LOG_WARNING, 0, '_stripe'); + setEventMessages($e->getMessage(), null, 'errors'); + $action=''; + } + + if ($paymentintent->status != 'succeeded') + { + $error++; + $errormessage="StatusOfRetreivedIntent is not succeeded: ".$e->getMessage(); + dol_syslog($errormessage, LOG_WARNING, 0, '_stripe'); + setEventMessages($e->getMessage(), null, 'errors'); + $action=''; + } + } - $error++; - $errormessage="ErrorCard ".$e->getMessage()." err=".var_export($err, true); - dol_syslog($errormessage, LOG_WARNING, 0, '_stripe'); - setEventMessages($e->getMessage(), null, 'errors'); - $action=''; - } catch (\Stripe\Error\RateLimit $e) { - // Too many requests made to the API too quickly - $error++; - $errormessage="ErrorRateLimit ".$e->getMessage(); - dol_syslog($errormessage, LOG_WARNING, 0, '_stripe'); - setEventMessages($e->getMessage(), null, 'errors'); - $action=''; - } catch (\Stripe\Error\InvalidRequest $e) { - // Invalid parameters were supplied to Stripe's API - $error++; - $errormessage="ErrorInvalidRequest ".$e->getMessage(); - dol_syslog($errormessage, LOG_WARNING, 0, '_stripe'); - setEventMessages($e->getMessage(), null, 'errors'); - $action=''; - } catch (\Stripe\Error\Authentication $e) { - // Authentication with Stripe's API failed - // (maybe you changed API keys recently) - $error++; - $errormessage="ErrorAuthentication ".$e->getMessage(); - dol_syslog($errormessage, LOG_WARNING, 0, '_stripe'); - setEventMessages($e->getMessage(), null, 'errors'); - $action=''; - } catch (\Stripe\Error\ApiConnection $e) { - // Network communication with Stripe failed - $error++; - $errormessage="ErrorApiConnection ".$e->getMessage(); - dol_syslog($errormessage, LOG_WARNING, 0, '_stripe'); - setEventMessages($e->getMessage(), null, 'errors'); - $action=''; - } catch (\Stripe\Error\Base $e) { - // Display a very generic error to the user, and maybe send - // yourself an email - $error++; - $errormessage="ErrorBase ".$e->getMessage(); - dol_syslog($errormessage, LOG_WARNING, 0, '_stripe'); - setEventMessages($e->getMessage(), null, 'errors'); - $action=''; - } catch (Exception $e) { - // Something else happened, completely unrelated to Stripe - $error++; - $errormessage="ErrorException ".$e->getMessage(); - dol_syslog($errormessage, LOG_WARNING, 0, '_stripe'); - setEventMessages($e->getMessage(), null, 'errors'); - $action=''; - } $remoteip = getUserRemoteIP(); @@ -615,7 +666,7 @@ if ($action == 'charge' && ! empty($conf->stripe->enabled)) $_SESSION["paymentType"] = ''; $_SESSION['ipaddress'] = ($remoteip?$remoteip:'unknown'); // Payer ip $_SESSION['payerID'] = is_object($customer)?$customer->id:''; - $_SESSION['TRANSACTIONID'] = is_object($charge)?$charge->id:''; + $_SESSION['TRANSACTIONID'] = (is_object($charge) ? $charge->id : (is_object($paymentintent) ? $paymentintent->id : '')); $_SESSION['errormessage'] = $errormessage; dol_syslog("Action charge stripe ip=".$remoteip, LOG_DEBUG, 0, '_stripe'); @@ -768,8 +819,8 @@ $object = null; if (! $source) { $found=true; - $tag=GETPOST("tag"); - $fulltag=$tag; + $tag=GETPOST("tag", 'alpha'); + $fulltag="TAG=".$tag; // Creditor print ''.$langs->trans("Creditor"); @@ -818,12 +869,9 @@ if (! $source) $stripe = new Stripe($db); $stripeacc = $stripe->getStripeAccount($service); $stripecu = null; - // for dev only - print ''.$langs->trans("PaymentIntent"); - print ''; - $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, $object, $stripecu, $stripeacc, $servicestatus); - print ''.$paymentintent->id.''; - print ''."\n"; + + $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, 'Stripe payment: '.$fulltag, $object, $stripecu, $stripeacc, $servicestatus); + if ($stripe->error) setEventMessages($stripe->error, null, 'errors'); } // We do not add fields shipToName, shipToStreet, shipToCity, shipToState, shipToCountryCode, shipToZip, shipToStreet2, phoneNum // as they don't exists (buyer is unknown, tag is free). @@ -848,9 +896,8 @@ if ($source == 'order') else { $result=$order->fetch_thirdparty($order->socid); - - $object = $order; } + $object = $order; if ($action != 'dopayment') // Do not change amount if we just click on first dopayment { @@ -860,7 +907,6 @@ if ($source == 'order') } $fulltag='ORD='.$order->id.'.CUS='.$order->thirdparty->id; - //$fulltag.='.NAM='.strtr($order->thirdparty->name,"-"," "); if (! empty($TAG)) { $tag=$TAG; $fulltag.='.TAG='.$TAG; } $fulltag=dol_string_unaccent($fulltag); @@ -933,12 +979,9 @@ if ($source == 'order') $stripe = new Stripe($db); $stripeacc = $stripe->getStripeAccount($service); $stripecu = $stripe->customerStripe($order->thirdparty, $stripeacc, $servicestatus, 1); - // for dev only - print ''.$langs->trans("PaymentIntent"); - print ''; - $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, $object, $stripecu, $stripeacc, $servicestatus); - print ''.$paymentintent->id.''; - print ''."\n"; + + $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, 'Stripe payment: '.$fulltag.' ref='.$object->ref, $object, $stripecu, $stripeacc, $servicestatus); + if ($stripe->error) setEventMessages($stripe->error, null, 'errors'); } // Shipping address @@ -992,9 +1035,8 @@ if ($source == 'invoice') else { $result=$invoice->fetch_thirdparty($invoice->socid); - - $object = $invoice; } + $object = $invoice; if ($action != 'dopayment') // Do not change amount if we just click on first dopayment { @@ -1083,12 +1125,9 @@ if ($source == 'invoice') $stripe = new Stripe($db); $stripeacc = $stripe->getStripeAccount($service); $stripecu = $stripe->customerStripe($invoice->thirdparty, $stripeacc, $servicestatus, 1); - // for dev only - print ''.$langs->trans("PaymentIntent"); - print ''; - $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, $object, $stripecu, $stripeacc, $servicestatus); - print ''.$paymentintent->id.''; - print ''."\n"; + + $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, 'Stripe payment: '.$fulltag.' ref='.$object->ref, $object, $stripecu, $stripeacc, $servicestatus); + if ($stripe->error) setEventMessages($stripe->error, null, 'errors'); } // Shipping address @@ -1144,8 +1183,6 @@ if ($source == 'contractline') { if ($contractline->fk_contrat > 0) { - $object = $contractline; - $result=$contract->fetch($contractline->fk_contrat); if ($result > 0) { @@ -1163,6 +1200,7 @@ if ($source == 'contractline') $error++; } } + $object = $contractline; if ($action != 'dopayment') // Do not change amount if we just click on first dopayment { @@ -1317,12 +1355,9 @@ if ($source == 'contractline') $stripe = new Stripe($db); $stripeacc = $stripe->getStripeAccount($service); $stripecu = null; - // for dev only - print ''.$langs->trans("PaymentIntent"); - print ''; - $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, $object, $stripecu, $stripeacc, $servicestatus); - print ''.$paymentintent->id.''; - print ''."\n"; + + $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, 'Stripe payment: '.$fulltag." ref=".$object->ref, $object, $stripecu, $stripeacc, $servicestatus); + if ($stripe->error) setEventMessages($stripe->error, null, 'errors'); } // Shipping address @@ -1376,9 +1411,9 @@ if ($source == 'membersubscription') else { $member->fetch_thirdparty(); - $object = $member; $subscription=new Subscription($db); } + $object = $member; if ($action != 'dopayment') // Do not change amount if we just click on first dopayment { @@ -1506,12 +1541,9 @@ if ($source == 'membersubscription') $stripe = new Stripe($db); $stripeacc = $stripe->getStripeAccount($service); $stripecu = null; - // for dev only - print ''.$langs->trans("PaymentIntent"); - print ''; - $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, $object, $stripecu, $stripeacc, $servicestatus); - print ''.$paymentintent->id.''; - print ''."\n"; + + $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, 'Stripe payment: '.$fulltag." ref=".$object->ref, $object, $stripecu, $stripeacc, $servicestatus); + if ($stripe->error) setEventMessages($stripe->error, null, 'errors'); } // Shipping address @@ -1564,8 +1596,8 @@ if ($source == 'donation') else { $don->fetch_thirdparty(); - $object = $don; } + $object = $don; if ($action != 'dopayment') // Do not change amount if we just click on first dopayment { @@ -1670,12 +1702,9 @@ if ($source == 'donation') $stripe = new Stripe($db); $stripeacc = $stripe->getStripeAccount($service); $stripecu = $stripe->customerStripe($don->thirdparty, $stripeacc, $servicestatus, 1); - // for dev only - print ''.$langs->trans("PaymentIntent"); - print ''; - $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, $object, $stripecu, $stripeacc, $servicestatus); - print ''.$paymentintent->id.''; - print ''."\n"; + + $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, 'Stripe payment: '.$fulltag." ref=".$object->ref, $object, $stripecu, $stripeacc, $servicestatus); + if ($stripe->error) setEventMessages($stripe->error, null, 'errors'); } // Shipping address @@ -1718,6 +1747,7 @@ if ($mesg) print '
'. print ''."\n"; print "\n"; + if ($action != 'dopayment') { if ($found && ! $error) // We are in a management option and no error @@ -1748,13 +1778,13 @@ if ($action != 'dopayment') if ((empty($paymentmethod) || $paymentmethod == 'paybox') && ! empty($conf->paybox->enabled)) { // If STRIPE_PICTO_FOR_PAYMENT is 'cb' we show a picto of a crdit card instead of paybox - print '
'; + print '
'; } if ((empty($paymentmethod) || $paymentmethod == 'stripe') && ! empty($conf->stripe->enabled)) { // If STRIPE_PICTO_FOR_PAYMENT is 'cb' we show a picto of a crdit card instead of stripe - print '
'; + print '
'; } if ((empty($paymentmethod) || $paymentmethod == 'paypal') && ! empty($conf->paypal->enabled)) @@ -1763,11 +1793,11 @@ if ($action != 'dopayment') if ($conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY == 'integral') { - print '
'; + print '
'; } if ($conf->global->PAYPAL_API_INTEGRAL_OR_PAYPALONLY == 'paypalonly') { - print '
'; + print '
'; } } } @@ -1799,17 +1829,6 @@ if (preg_match('/^dopayment/', $action)) // Stripe if (GETPOST('dopayment_stripe', 'alpha')) { - // Simple checkout - /* - print ''; - */ - // Personalized checkout print ''; - print ' + print '
'; -
-
'; + print ''; print ''."\n"; print ''."\n"; @@ -1860,41 +1878,60 @@ if (preg_match('/^dopayment/', $action)) print ''; print ''; - print ' - - -
'; + if (empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION) || ! empty($paymentintent)) + { + print ' + + +
'; + + if (! empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) + { + print '
'; + } + + print ' +
+ + '; + + if (! empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) + { + print '
'; + } + + print '
+ +
+ + + + +
+ +
'; + + print ''; + print ''; + + print ' +
'; + } if (! empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) { - print '
'; + if (empty($paymentintent)) + { + print '
'.$langs->trans("Error").'
'; + } + else + { + print ''; + //$_SESSION["paymentintent_id"] = $paymentintent->id; + } } - print ' -
- - '; - - if (! empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) - { - print '
'; - } - - print '
- -
- - - - -
'; - - print '
- - -
- -
'."\n"; + print ''."\n"; print ''."\n"; @@ -1931,7 +1968,6 @@ if (preg_match('/^dopayment/', $action)) }; var cardElement = elements.create('card', {style: style}); - var cardholderName = document.getElementById('cardholder-name'); // Add an instance of the card Element into the `card-element`
cardElement.mount('#card-element'); @@ -1940,44 +1976,70 @@ if (preg_match('/^dopayment/', $action)) cardElement.addEventListener('change', function(event) { var displayError = document.getElementById('card-errors'); if (event.error) { - console.log("Show event error"); + console.log("Show event error (like 'Incorrect card number', ...)"); displayError.textContent = event.error.message; } else { - console.log("No error"); + console.log("Reset error message"); displayError.textContent = ''; } }); // Handle form submission + var cardholderName = document.getElementById('cardholder-name'); var cardButton = document.getElementById('buttontopay'); var clientSecret = cardButton.dataset.secret; cardButton.addEventListener('click', function(event) { - stripe.handleCardPayment( - clientSecret, cardElement, { - source_data: { - owner: { - name: cardholderName.value, + console.log("We click on buttontopay"); + event.preventDefault(); + + if (cardholderName.value == '') + { + console.log("Field Card holder is empty"); + var displayError = document.getElementById('card-errors'); + displayError.textContent = 'trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("CardOwner"))); ?>'; + } + else + { + stripe.handleCardPayment( + clientSecret, cardElement, { + payment_method_data: { + billing_details: { + name: cardholderName.value + , email: '', + thirdparty)) { ?>, phone: thirdparty->phone; ?>', + thirdparty)) { + print ', address: {'."\n"; + print ' city: '.$object->thirdparty->town.','; + print ' country: '.$object->thirdparty->country_code.','; + print ' line1: '.$object->thirdparty->address.','; + print ' postal_code: '.$object->thirdparty->zip; + print '}'."\n"; + } ?> + } /* TODO Add all other known data like emails, ... to be SCA compliant */ + }, + save_payment_method: false } - } + ).then(function(result) { + console.log(result); + if (result.error) { + console.log("Error on result of handleCardPayment"); + jQuery('#buttontopay').show(); + jQuery('#hourglasstopay').hide(); + // Inform the user if there was an error + var errorElement = document.getElementById('card-errors'); + errorElement.textContent = result.error.message; + } else { + // The payment has succeeded. Display a success message. + console.log("No error on result of handleCardPayment, so we submit the form"); + // Submit the form + jQuery('#buttontopay').hide(); + jQuery('#hourglasstopay').show(); + // Send form (action=charge that will do nothing) + jQuery('#payment-form').submit(); + } + }); } - ).then(function(result) { - jQuery('#buttontopay').hide(); - jQuery('#hourglasstopay').show(); - if (result.error) { - console.log("Error on result of handleCardPayment"); - jQuery('#buttontopay').show(); - jQuery('#hourglasstopay').hide(); - // Inform the user if there was an error - var errorElement = document.getElementById('card-errors'); - errorElement.textContent = result.error.message; - } else { - console.log("No error on result of handleCardPayment, so we submit the form"); - // Submit the form - jQuery('#buttontopay').hide(); - jQuery('#hourglasstopay').show(); - } - }); }); diff --git a/htdocs/public/payment/paymentok.php b/htdocs/public/payment/paymentok.php index 62d709fc674..52413921f90 100644 --- a/htdocs/public/payment/paymentok.php +++ b/htdocs/public/payment/paymentok.php @@ -280,7 +280,7 @@ $fulltag = $FULLTAG; $tmptag=dolExplodeIntoArray($fulltag, '.', '='); -dol_syslog("ispaymentok=".$ispaymentok, LOG_DEBUG, 0, '_payment'); +dol_syslog("ispaymentok=".$ispaymentok." tmptag=".var_export($tmptag, true), LOG_DEBUG, 0, '_payment'); // Make complementary actions @@ -296,7 +296,7 @@ if ($ispaymentok) $user->rights->facture->creer = 1; $user->rights->adherent->cotisation->creer = 1; - if (in_array('MEM', array_keys($tmptag))) + if (array_key_exists('MEM', $tmptag) && $tmptag['MEM'] > 0) { // Validate member // Create subscription @@ -583,7 +583,7 @@ if ($ispaymentok) $ispostactionok = -1; } } - elseif (in_array('INV', array_keys($tmptag))) + elseif (array_key_exists('INV', $tmptag) && $tmptag['INV'] > 0) { // Record payment include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; @@ -769,14 +769,14 @@ if ($ispaymentok) $urlback=$_SERVER["REQUEST_URI"]; $topic='['.$appli.'] '.$companylangs->transnoentitiesnoconv("NewOnlinePaymentReceived"); $content=""; - if (in_array('MEM', array_keys($tmptag))) + if (array_key_exists('MEM', $tmptag)) { $url=$urlwithroot."/adherents/subscription.php?rowid=".$tmptag['MEM']; $content.=''.$companylangs->trans("PaymentSubscription")."

\n"; $content.=$companylangs->trans("MemberId").': '.$tmptag['MEM']."
\n"; $content.=$companylangs->trans("Link").': '.$url.''."
\n"; } - elseif (in_array('INV', array_keys($tmptag))) + elseif (array_key_exists('INV', $tmptag)) { $url=$urlwithroot."/compta/facture/card.php?id=".$tmptag['INV']; $content.=''.$companylangs->trans("Payment")."

\n"; diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index 1f2f39719a8..ee1c1a67f0a 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -243,6 +243,7 @@ class Stripe extends CommonObject * @param double $amount Amount * @param string $currency_code Currency code * @param string $tag Tag + * @param string $description Description * @param Societe $object Object to pay with Stripe * @param string $customer Stripe customer ref 'cus_xxxxxxxxxxxxx' via customerStripe() * @param string $key ''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect @@ -252,10 +253,14 @@ class Stripe extends CommonObject * @param boolean $confirmnow false=default, true=try to confirm immediatly after create (if conditions are ok) * @return \Stripe\PaymentIntent|null Stripe PaymentIntent or null if not found */ - public function getPaymentIntent($amount, $currency_code, $tag, $object = null, $customer = null, $key = null, $status = 0, $usethirdpartyemailforreceiptemail = 0, $mode = 'automatic', $confirmnow = false) + public function getPaymentIntent($amount, $currency_code, $tag, $description = '', $object = null, $customer = null, $key = null, $status = 0, $usethirdpartyemailforreceiptemail = 0, $mode = 'automatic', $confirmnow = false) { global $conf, $user, $mysoc; + dol_syslog("getPaymentIntent"); + + $error = 0; + if (empty($status)) $service = 'StripeTest'; else $service = 'StripeLive'; @@ -305,6 +310,7 @@ class Stripe extends CommonObject } catch(Exception $e) { + $error++; $this->error = $e->getMessage(); } } @@ -314,9 +320,6 @@ class Stripe extends CommonObject if (empty($paymentintent)) { $ipaddress=getUserRemoteIP(); - // Not enough space for a ref so we store id. Also with multicompany we can have same ref for 2 different - // object and we need a unique (this is used later as idempotency_key) - $description=$tag; $metadata = array('dol_version'=>DOL_VERSION, 'dol_entity'=>$conf->entity, 'ipaddress'=>$ipaddress); if (is_object($object)) { @@ -330,12 +333,14 @@ class Stripe extends CommonObject "amount" => $stripeamount, "currency" => $currency_code, "payment_method_types" => ["card"], - "statement_descriptor" => dol_trunc($description, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description) + "description" => $description, + "statement_descriptor" => dol_trunc($tag, 10, 'right', 'UTF-8', 1), // 22 chars that appears on bank receipt (company + description) "metadata" => $metadata ); if (! is_null($customer)) $dataforintent["customer"]=$customer; // save_payment_method = true, // payment_method = + //var_dump($dataforintent); if ($conf->entity!=$conf->global->STRIPECONNECT_PRINCIPAL && $fee>0) { @@ -353,9 +358,12 @@ class Stripe extends CommonObject if (empty($key)) { // If the Stripe connect account not set, we use common API usage $paymentintent = \Stripe\PaymentIntent::create($dataforintent, array("idempotency_key" => "$description")); + //$paymentintent = \Stripe\PaymentIntent::create($dataforintent, array()); } else { $paymentintent = \Stripe\PaymentIntent::create($dataforintent, array("idempotency_key" => "$description", "stripe_account" => $key)); + //$paymentintent = \Stripe\PaymentIntent::create($dataforintent, array("stripe_account" => $key)); } + //var_dump($paymentintent); // Store the payment intent if (is_object($object)) @@ -366,6 +374,7 @@ class Stripe extends CommonObject $resql = $this->db->query($sql); if (! $resql) { + $error++; $this->error = $this->db->lasterror(); dol_syslog(get_class($this) . "::PaymentIntent failed to insert paymentintent with id=".$paymentintent->id." into database."); } @@ -377,10 +386,18 @@ class Stripe extends CommonObject } catch(Exception $e) { + /*var_dump($dataforintent); + var_dump($description); + var_dump($key); + var_dump($paymentintent); + var_dump($e->getMessage());*/ + $error++; $this->error = $e->getMessage(); } } + dol_syslog("getPaymentIntent return error=".$error); + return $paymentintent; } diff --git a/htdocs/stripe/lib/stripe.lib.php b/htdocs/stripe/lib/stripe.lib.php index d806d6a39b3..100ce840e24 100644 --- a/htdocs/stripe/lib/stripe.lib.php +++ b/htdocs/stripe/lib/stripe.lib.php @@ -87,12 +87,12 @@ function showStripePaymentUrl($type, $ref) * @param string $freetag Free tag * @return string Url string */ -function getStripePaymentUrl($mode, $type, $ref = '', $amount = '9.99', $freetag = 'your_free_tag') +function getStripePaymentUrl($mode, $type, $ref = '', $amount = '9.99', $freetag = 'your_tag') { global $conf; $ref=str_replace(' ', '', $ref); - + if ($type == 'free') { $out=DOL_MAIN_URL_ROOT.'/public/stripe/newpayment.php?amount='.($mode?'':'').$amount.($mode?'':'').'&tag='.($mode?'':'').$freetag.($mode?'':''); diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index b8ffa08fbaf..7302191fc84 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -132,19 +132,27 @@ input.smallpadd { /* Used for timesheet input */ input.buttongen { vertical-align: middle; } -input.buttonpayment { +input.buttonpayment, button.buttonpayment, div.buttonpayment { min-width: 320px; margin-bottom: 15px; background-image: none; line-height: 24px; padding: 8px; background: none; - padding-left: 38px; - text-align: ; - border: 1px solid #ddd; - background-color: #eee; + text-align: center; + border: 0; + background-color: #9999bb; white-space: normal; - box-shadow: 1px 1px 8px #bbb; + box-shadow: 1px 1px 4px #bbb; + color: #fff; + border-radius: 4px; +} +div.buttonpayment input { + background-color: unset; + color: #fff; + border-bottom: unset; + font-weight: bold; + text-transform: uppercase; } input.buttonpaymentcb { background-image: url(); @@ -3569,6 +3577,7 @@ div#card-errors { color: #fa755a; text-align: center; padding-top: 3px; + max-width: 320px; } diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 755736eb79f..2906da3729c 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -352,18 +352,25 @@ input.smallpadd { /* Used for timesheet input */ input.buttongen { vertical-align: middle; } -input.buttonpayment { +input.buttonpayment, button.buttonpayment, div.buttonpayment { min-width: 320px; margin-bottom: 15px; background-image: none; line-height: 24px; padding: 8px; background: none; - padding-left: 30px; - text-align: ; + text-align: center; border: 2px solid #ccc; background-color: #eee; white-space: normal; + color: #888 !important; +} +div.buttonpayment input { + background-color: unset; + border-bottom: unset; + font-weight: bold; + text-transform: uppercase; + color: #333; } input.buttonpaymentcb { background-image: url(); @@ -3660,6 +3667,7 @@ div#card-errors { color: #fa755a; text-align: center; padding-top: 3px; + max-width: 320px; } From ab3ad77704aaea548c00bab00f24c85b87fe8262 Mon Sep 17 00:00:00 2001 From: ATM-Nicolas Date: Fri, 3 May 2019 10:55:51 +0200 Subject: [PATCH 130/132] FIX : Sale representative column didn't increase nbfield variable on proposal list --- htdocs/comm/propal/list.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php index a253b1e2eb1..24c53d26526 100644 --- a/htdocs/comm/propal/list.php +++ b/htdocs/comm/propal/list.php @@ -968,6 +968,7 @@ if ($resql) print ' '; } print ''; + if (! $i) $totalarray['nbfield']++; } // Extra fields From 9115df743944e10464ae61cbdd1b5193c78f7477 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 3 May 2019 11:25:53 +0200 Subject: [PATCH 131/132] Debug v10 --- htdocs/admin/dict.php | 46 +++++++++++-------------- htdocs/core/modules/modTicket.class.php | 7 ++-- htdocs/fourn/facture/card.php | 2 +- 3 files changed, 25 insertions(+), 30 deletions(-) diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index ae4fde1876b..ab5803a086a 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -652,6 +652,7 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) if ($fieldnamekey == 'sortorder') $fieldnamekey = 'SortOrder'; if ($fieldnamekey == 'category_type') $fieldnamekey = 'Calculated'; if ($fieldnamekey == 'revenuestamp_type') $fieldnamekey = 'TypeOfRevenueStamp'; + if ($fieldnamekey == 'use_default') $fieldnamekey = 'UseByDefault'; setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->transnoentities($fieldnamekey)), null, 'errors'); } @@ -1053,11 +1054,12 @@ if ($id) continue; } - // Determine le nom du champ par rapport aux noms possibles - // dans les dictionnaires de donnees + // Define field friedly name from its technical name $valuetoshow=ucfirst($fieldlist[$field]); // Par defaut $valuetoshow=$langs->trans($valuetoshow); // try to translate $class=''; + + if ($fieldlist[$field]=='pos') { $valuetoshow=$langs->trans("Position"); $class='width100'; } if ($fieldlist[$field]=='source') { $valuetoshow=$langs->trans("Contact"); } if ($fieldlist[$field]=='price') { $valuetoshow=$langs->trans("PriceUHT"); } if ($fieldlist[$field]=='taux') { @@ -1125,6 +1127,7 @@ if ($id) if ($fieldlist[$field]=='range_ik') { $valuetoshow=$langs->trans("RangeIk"); } if ($fieldlist[$field]=='fk_c_exp_tax_cat') { $valuetoshow=$langs->trans("CarCategory"); } if ($fieldlist[$field]=='revenuestamp_type') { $valuetoshow=$langs->trans('TypeOfRevenueStamp'); } + if ($fieldlist[$field]=='use_default') { $valuetoshow=$langs->trans('Default'); } if ($id == 2) // Special cas for state page { @@ -1197,8 +1200,10 @@ if ($id) print ''; + print '
'; + print '
'; print ''; print ''; @@ -1221,7 +1226,7 @@ if ($id) print '
'; print ''; - // Title line with search boxes + // Title line with search input fields print ''; $filterfound=0; foreach ($fieldlist as $field => $value) @@ -1276,17 +1281,12 @@ if ($id) // dans les dictionnaires de donnees $showfield=1; // By defaut $align="left"; + $cssprefix=''; $sortable=1; - $valuetoshow=''; - /* - $tmparray=getLabelOfField($fieldlist[$field]); - $showfield=$tmp['showfield']; - $valuetoshow=$tmp['valuetoshow']; - $align=$tmp['align']; - $sortable=$tmp['sortable']; - */ $valuetoshow=ucfirst($fieldlist[$field]); // By defaut $valuetoshow=$langs->trans($valuetoshow); // try to translate + + // Special cases if ($fieldlist[$field]=='source') { $valuetoshow=$langs->trans("Contact"); } if ($fieldlist[$field]=='price') { $valuetoshow=$langs->trans("PriceUHT"); } if ($fieldlist[$field]=='taux') { @@ -1304,10 +1304,7 @@ if ($id) if ($fieldlist[$field]=='code') { $valuetoshow=$langs->trans("Code"); } if ($fieldlist[$field]=='position') { $align='right'; } if ($fieldlist[$field]=='libelle' || $fieldlist[$field]=='label') { $valuetoshow=$langs->trans("Label"); } - if ($fieldlist[$field]=='libelle_facture') { - //$valuetoshow=$form->textwithtooltip($langs->trans("LabelOnDocuments"), $langs->trans("LabelUsedByDefault"),2,1,img_help(1,'')); - $valuetoshow=$langs->trans("LabelOnDocuments"); - } + if ($fieldlist[$field]=='libelle_facture') { $valuetoshow=$langs->trans("LabelOnDocuments"); } if ($fieldlist[$field]=='country') { $valuetoshow=$langs->trans("Country"); } if ($fieldlist[$field]=='recuperableonly') { $valuetoshow=$langs->trans("NPR"); $align="center"; } if ($fieldlist[$field]=='nbjour') { $valuetoshow=$langs->trans("NbOfDays"); } @@ -1316,7 +1313,6 @@ if ($id) if ($fieldlist[$field]=='width' || $fieldlist[$field]=='nx') { $valuetoshow=$langs->trans("Width"); } if ($fieldlist[$field]=='height' || $fieldlist[$field]=='ny') { $valuetoshow=$langs->trans("Height"); } if ($fieldlist[$field]=='unit' || $fieldlist[$field]=='metric') { $valuetoshow=$langs->trans("MeasuringUnit"); } - if ($fieldlist[$field]=='region_id' || $fieldlist[$field]=='country_id') { $showfield=0; } if ($fieldlist[$field]=='accountancy_code'){ $valuetoshow=$langs->trans("AccountancyCode"); } if ($fieldlist[$field]=='accountancy_code_sell'){ $valuetoshow=$langs->trans("AccountancyCodeSell"); $sortable=0; } if ($fieldlist[$field]=='accountancy_code_buy'){ $valuetoshow=$langs->trans("AccountancyCodeBuy"); $sortable=0; } @@ -1347,11 +1343,14 @@ if ($id) if ($fieldlist[$field]=='range_ik') { $valuetoshow=$langs->trans("RangeIk"); } if ($fieldlist[$field]=='fk_c_exp_tax_cat') { $valuetoshow=$langs->trans("CarCategory"); } if ($fieldlist[$field]=='revenuestamp_type') { $valuetoshow=$langs->trans('TypeOfRevenueStamp'); } + if ($fieldlist[$field]=='use_default') { $valuetoshow=$langs->trans('Default'); } - // Affiche nom du champ + if ($fieldlist[$field]=='region_id' || $fieldlist[$field]=='country_id') { $showfield=0; } + + // Show field title if ($showfield) { - print getTitleFieldOfList($valuetoshow, 0, $_SERVER["PHP_SELF"], ($sortable?$fieldlist[$field]:''), ($page?'page='.$page.'&':''), $param, "align=".$align, $sortfield, $sortorder); + print getTitleFieldOfList($valuetoshow, 0, $_SERVER["PHP_SELF"], ($sortable?$fieldlist[$field]:''), ($page?'page='.$page.'&':''), $param, "align=".$align, $sortfield, $sortorder, $cssprefix); } } // Favorite - Only activated on country dictionary @@ -1806,7 +1805,6 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '') if (in_array('region_id', $fieldlist)) { print ''; continue; } // For state page, we do not show the country input (we link to region, not country) @@ -1912,7 +1910,7 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '') print ''; } elseif ($fieldlist[$field] == 'code' && isset($obj->{$fieldlist[$field]})) { - print ''; + print ''; } elseif ($fieldlist[$field]=='unit') { print ''; + print ''; } /* From 6797c951644e2cea922d42c2495d5a9295e175de Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 3 May 2019 12:10:29 +0200 Subject: [PATCH 132/132] Fix syntax error --- .../accountancy/bookkeeping/thirdparty_lettering_supplier.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/bookkeeping/thirdparty_lettering_supplier.php b/htdocs/accountancy/bookkeeping/thirdparty_lettering_supplier.php index 3795099c78d..fab30066982 100644 --- a/htdocs/accountancy/bookkeeping/thirdparty_lettering_supplier.php +++ b/htdocs/accountancy/bookkeeping/thirdparty_lettering_supplier.php @@ -197,7 +197,7 @@ if ($resql) { print ''; print ''; - $letteringbutton = '\'; + $letteringbutton = ''; print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_companies', 0, $letteringbutton, '', $limit);
'; - //print join(',',$fieldlist); print ''; @@ -1972,12 +1970,8 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '') $classtd=''; $class=''; if ($fieldlist[$field]=='code') $classtd='width100'; - if ($fieldlist[$field]=='affect') $class='maxwidth50'; - if ($fieldlist[$field]=='delay') $class='maxwidth50'; - if ($fieldlist[$field]=='position') $class='maxwidth50'; - if ($fieldlist[$field]=='libelle' || $fieldlist[$field]=='label') $class='quatrevingtpercent'; - if ($fieldlist[$field]=='tracking') $class='quatrevingtpercent'; - if ($fieldlist[$field]=='sortorder' || $fieldlist[$field]=='sens' || $fieldlist[$field]=='category_type') $class='maxwidth50'; + if (in_array($fieldlist[$field], array('pos', 'use_default', 'affect', 'delay', 'position', 'sortorder', 'sens', 'category_type'))) $class='maxwidth50'; + if (in_array($fieldlist[$field], array('libelle', 'label', 'tracking'))) $class='quatrevingtpercent'; print ''; $transfound=0; if (in_array($fieldlist[$field], array('label','libelle'))) diff --git a/htdocs/core/modules/modTicket.class.php b/htdocs/core/modules/modTicket.class.php index 5aef264a11e..871bc94670d 100644 --- a/htdocs/core/modules/modTicket.class.php +++ b/htdocs/core/modules/modTicket.class.php @@ -120,15 +120,16 @@ class modTicket extends DolibarrModules } $this->dictionaries = array( 'langs' => 'ticket', - 'tabname' => array(MAIN_DB_PREFIX . "c_ticket_type", MAIN_DB_PREFIX . "c_ticket_category", MAIN_DB_PREFIX . "c_ticket_severity"), - 'tablib' => array("TicketDictType", "TicketDictCategory", "TicketDictSeverity"), - 'tabsql' => array('SELECT f.rowid as rowid, f.code, f.pos, f.label, f.active, f.use_default FROM ' . MAIN_DB_PREFIX . 'c_ticket_type as f', 'SELECT f.rowid as rowid, f.code, f.pos, f.label, f.active, f.use_default FROM ' . MAIN_DB_PREFIX . 'c_ticket_category as f', 'SELECT f.rowid as rowid, f.code, f.pos, f.label, f.active, f.use_default FROM ' . MAIN_DB_PREFIX . 'c_ticket_severity as f'), + 'tabname' => array(MAIN_DB_PREFIX . "c_ticket_type", MAIN_DB_PREFIX . "c_ticket_severity", MAIN_DB_PREFIX . "c_ticket_category"), + 'tablib' => array("TicketDictType", "TicketDictSeverity", "TicketDictCategory"), + 'tabsql' => array('SELECT f.rowid as rowid, f.code, f.pos, f.label, f.active, f.use_default FROM ' . MAIN_DB_PREFIX . 'c_ticket_type as f', 'SELECT f.rowid as rowid, f.code, f.pos, f.label, f.active, f.use_default FROM ' . MAIN_DB_PREFIX . 'c_ticket_severity as f', 'SELECT f.rowid as rowid, f.code, f.pos, f.label, f.active, f.use_default FROM ' . MAIN_DB_PREFIX . 'c_ticket_category as f'), 'tabsqlsort' => array("pos ASC", "pos ASC", "pos ASC"), 'tabfield' => array("pos,code,label,use_default", "pos,code,label,use_default", "pos,code,label,use_default"), 'tabfieldvalue' => array("pos,code,label,use_default", "pos,code,label,use_default", "pos,code,label,use_default"), 'tabfieldinsert' => array("pos,code,label,use_default", "pos,code,label,use_default", "pos,code,label,use_default"), 'tabrowid' => array("rowid", "rowid", "rowid"), 'tabcond' => array($conf->ticket->enabled, $conf->ticket->enabled, $conf->ticket->enabled), + 'tabhelp' => array(array('code'=>$langs->trans("EnterAnyCode"), 'use_default'=>$langs->trans("Enter0or1")), array('code'=>$langs->trans("EnterAnyCode"), 'use_default'=>$langs->trans("Enter0or1")), array('code'=>$langs->trans("EnterAnyCode"), 'use_default'=>$langs->trans("Enter0or1"))), ); // Boxes diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index 5c47aa41f40..f7a1c800443 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -2789,7 +2789,7 @@ else } else { - print '
'.$langs->trans("None").'
'.$langs->trans("None").'