diff --git a/htdocs/core/modules/modPartnership.class.php b/htdocs/core/modules/modPartnership.class.php
index ae5886e589c..0d5d6dce7ca 100644
--- a/htdocs/core/modules/modPartnership.class.php
+++ b/htdocs/core/modules/modPartnership.class.php
@@ -177,7 +177,7 @@ class modPartnership extends DolibarrModules
// Array to add new pages in new tabs
$this->tabs = array();
- $tabtoadd = (!empty(getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR')) && getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR') == 'member') ? 'member' : 'thirdparty';
+ $tabtoadd = ($conf->global->PARTNERSHIP_IS_MANAGED_FOR == 'member') ? 'member' : 'thirdparty';
if ($tabtoadd == 'member') {
$this->tabs[] = array('data'=>'member:+partnership:Partnership:partnership@partnership:$user->rights->partnership->read:/adherents/partnership.php?socid=__ID__');
@@ -253,12 +253,12 @@ class modPartnership extends DolibarrModules
// 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
- $statusatinstall=0;
$arraydate=dol_getdate(dol_now());
$datestart=dol_mktime(21, 15, 0, $arraydate['mon'], $arraydate['mday'], $arraydate['year']);
$this->cronjobs = array(
- 0 => array('priority'=>60, 'label'=>'CancelPartnershipForExpiredMembers', 'jobtype'=>'method', 'class'=>'/partnership/class/partnershiputils.class.php', 'objectname'=>'PartnershipUtils', 'method'=>'doCancelStatusOfPartnership', 'parameters'=>'', 'comment'=>'Cancel status of partnership when subscription is expired + x days.', 'frequency'=>1, 'unitfrequency'=>86400, 'status'=>$statusatinstall, 'test'=>'$conf->partnership->enabled', 'datestart'=>$datestart),
+ 0 => array('priority'=>60, 'label'=>'CancelPartnershipForExpiredMembers', 'jobtype'=>'method', 'class'=>'/partnership/class/partnershiputils.class.php', 'objectname'=>'PartnershipUtils', 'method'=>'doCancelStatusOfMemberPartnership', 'parameters'=>'', 'comment'=>'Cancel status of partnership when subscription is expired + x days.', 'frequency'=>1, 'unitfrequency'=>86400, 'status'=>1, 'test'=>'$conf->partnership->enabled', 'datestart'=>$datestart),
+ 1 => array('priority'=>61, 'label'=>'WarningOfPartnershipIfDolibarrBacklinkNotfound', 'jobtype'=>'method', 'class'=>'/partnership/class/partnershiputils.class.php', 'objectname'=>'PartnershipUtils', 'method'=>'doWarningOfPartnershipIfDolibarrBacklinkNotfound', 'parameters'=>'', 'comment'=>'Warning of partnership if Dolibarr backlink not found on partner website.', 'frequency'=>1, 'unitfrequency'=>86400, 'status'=>0, 'test'=>'$conf->partnership->enabled', 'datestart'=>$datestart),
);
// Permissions provided by this module
diff --git a/htdocs/install/mysql/migration/13.0.0-14.0.0.sql b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql
index c1e75bbe353..d0375349880 100644
--- a/htdocs/install/mysql/migration/13.0.0-14.0.0.sql
+++ b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql
@@ -398,8 +398,9 @@ CREATE TABLE llx_partnership(
note_private text,
note_public text,
last_main_doc varchar(255),
- count_last_url_check_error integer DEFAULT '0',
- import_key varchar(14),
+ count_last_url_check_error integer DEFAULT '0',
+ last_check_backlink datetime NULL,
+ import_key varchar(14),
model_pdf varchar(255)
) ENGINE=innodb;
@@ -420,10 +421,10 @@ create table llx_partnership_extrafields
ALTER TABLE llx_partnership_extrafields ADD INDEX idx_partnership_fk_object(fk_object);
-INSERT INTO llx_c_email_templates (entity,module,type_template,label,lang,position,topic,joinfiles,content) VALUES (0, 'partnership', 'partnership_send', '(SendingEmailOnPartnershipWillExpire)', NULL, 100, '[__[MAIN_INFO_SOCIETE_NOM]__] - __(YourPartnershipWillSoonExpireTopic)__', 0, '
\n Hello,
\n__(YourPartnershipWillSoonExpireContent)__
\n
\n\n
\n\n __(Sincerely)__
\n __[MAIN_INFO_SOCIETE_NOM]__
\n \n');
-INSERT INTO llx_c_email_templates (entity,module,type_template,label,lang,position,topic,joinfiles,content) VALUES (0, 'partnership', 'partnership_send', '(SendingEmailOnPartnershipCanceled)', NULL, 100, '[__[MAIN_INFO_SOCIETE_NOM]__] - __(YourPartnershipCanceledTopic)__', 0, '\n Hello,
\n__(YourPartnershipCanceledContent)__
\n
\n\n
\n\n __(Sincerely)__
\n __[MAIN_INFO_SOCIETE_NOM]__
\n \n');
-INSERT INTO llx_c_email_templates (entity,module,type_template,label,lang,position,topic,joinfiles,content) VALUES (0, 'partnership', 'partnership_send', '(SendingEmailOnPartnershipRefused)', NULL, 100, '[__[MAIN_INFO_SOCIETE_NOM]__] - __(YourPartnershipRefusedTopic)__', 0, '\n Hello,
\n__(YourPartnershipRefusedContent)__
\n
\n\n
\n\n __(Sincerely)__
\n __[MAIN_INFO_SOCIETE_NOM]__
\n \n');
-INSERT INTO llx_c_email_templates (entity,module,type_template,label,lang,position,topic,joinfiles,content) VALUES (0, 'partnership', 'partnership_send', '(SendingEmailOnPartnershipAccepted)', NULL, 100, '[__[MAIN_INFO_SOCIETE_NOM]__] - __(YourPartnershipAcceptedTopic)__', 0, '\n Hello,
\n__(YourPartnershipAcceptedContent)__
\n
\n\n
\n\n __(Sincerely)__
\n __[MAIN_INFO_SOCIETE_NOM]__
\n \n');
+INSERT INTO llx_c_email_templates (entity,module,type_template,label,lang,position,topic,joinfiles,content) VALUES (0, 'partnership', 'partnership_send', '(SendingEmailOnPartnershipWillExpire)', '', 100, '[__[MAIN_INFO_SOCIETE_NOM]__] - __(YourPartnershipWillSoonExpireTopic)__', 0, '\n Hello,
\n__(YourPartnershipWillSoonExpireContent)__
\n
\n\n
\n\n __(Sincerely)__
\n __[MAIN_INFO_SOCIETE_NOM]__
\n \n');
+INSERT INTO llx_c_email_templates (entity,module,type_template,label,lang,position,topic,joinfiles,content) VALUES (0, 'partnership', 'partnership_send', '(SendingEmailOnPartnershipCanceled)', '', 100, '[__[MAIN_INFO_SOCIETE_NOM]__] - __(YourPartnershipCanceledTopic)__', 0, '\n Hello,
\n__(YourPartnershipCanceledContent)__
\n
\n\n
\n\n __(Sincerely)__
\n __[MAIN_INFO_SOCIETE_NOM]__
\n \n');
+INSERT INTO llx_c_email_templates (entity,module,type_template,label,lang,position,topic,joinfiles,content) VALUES (0, 'partnership', 'partnership_send', '(SendingEmailOnPartnershipRefused)', '', 100, '[__[MAIN_INFO_SOCIETE_NOM]__] - __(YourPartnershipRefusedTopic)__', 0, '\n Hello,
\n__(YourPartnershipRefusedContent)__
\n
\n\n
\n\n __(Sincerely)__
\n __[MAIN_INFO_SOCIETE_NOM]__
\n \n');
+INSERT INTO llx_c_email_templates (entity,module,type_template,label,lang,position,topic,joinfiles,content) VALUES (0, 'partnership', 'partnership_send', '(SendingEmailOnPartnershipAccepted)', '', 100, '[__[MAIN_INFO_SOCIETE_NOM]__] - __(YourPartnershipAcceptedTopic)__', 0, '\n Hello,
\n__(YourPartnershipAcceptedContent)__
\n
\n\n
\n\n __(Sincerely)__
\n __[MAIN_INFO_SOCIETE_NOM]__
\n \n');
ALTER TABLE llx_adherent ADD COLUMN url varchar(255) NULL AFTER email;
ALTER TABLE llx_facture_fourn ADD COLUMN date_closing datetime DEFAULT NULL after date_valid;
diff --git a/htdocs/langs/en_US/partnership.lang b/htdocs/langs/en_US/partnership.lang
index 4d5b518431f..2da278dd36c 100644
--- a/htdocs/langs/en_US/partnership.lang
+++ b/htdocs/langs/en_US/partnership.lang
@@ -32,7 +32,10 @@ ListOfPartnerships=List of partnership
PartnershipSetup=Partnership setup
PartnershipAbout=About Partnership
PartnershipAboutPage=Partnership about page
-PartnershipManagedFor=Partnership managed for
+partnershipforthirdpartyormember=Partnership is for a 'thirdparty' or for a 'member'
+PARTNERSHIP_IS_MANAGED_FOR=Partnership managed for
+PARTNERSHIP_BACKLINKS_TO_CHECK=Backlinks to check
+PARTNERSHIP_NBDAYS_AFTER_MEMBER_EXPIRATION_BEFORE_CANCEL=Nb of days before cancel status of partnership
#
# Object
@@ -44,6 +47,7 @@ ReasonDecline=Decline reason
ReasonDeclineOrCancel=Decline reason
PartnershipAlreadyExist=Partnership already exist
ShowPartnership=Show partnership
+BacklinkNotFoundOnPartnerWebsite=Backlink not found on partner website
ConfirmClosePartnershipAsk=Are you sure you want to cancel this partnership?
#
diff --git a/htdocs/partnership/admin/setup.php b/htdocs/partnership/admin/setup.php
index 77edba1f21f..4cd5fe5f387 100644
--- a/htdocs/partnership/admin/setup.php
+++ b/htdocs/partnership/admin/setup.php
@@ -82,9 +82,7 @@ include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
if ($action == 'setting') {
require_once DOL_DOCUMENT_ROOT."/core/modules/modPartnership.class.php";
- $value = GETPOST('managed_for', 'alpha');
-
- $modulemenu = ($value == 'member') ? 'member' : 'thirdparty';
+ $modulemenu = (GETPOST('PARTNERSHIP_IS_MANAGED_FOR', 'alpha') == 'member') ? 'member' : 'thirdparty';
$res = dolibarr_set_const($db, "PARTNERSHIP_IS_MANAGED_FOR", $modulemenu, 'chaine', 0, '', $conf->entity);
$partnership = new modPartnership($db);
@@ -94,6 +92,10 @@ if ($action == 'setting') {
$error += $partnership->delete_menus();
$error += $partnership->insert_menus();
+
+ if(GETPOST("PARTNERSHIP_NBDAYS_AFTER_MEMBER_EXPIRATION_BEFORE_CANCEL",'int'))
+ dolibarr_set_const($db, "PARTNERSHIP_NBDAYS_AFTER_MEMBER_EXPIRATION_BEFORE_CANCEL", GETPOST("PARTNERSHIP_NBDAYS_AFTER_MEMBER_EXPIRATION_BEFORE_CANCEL",'int'), 'chaine', 0, '', $conf->entity);
+ dolibarr_set_const($db, "PARTNERSHIP_BACKLINKS_TO_CHECK", GETPOST("PARTNERSHIP_BACKLINKS_TO_CHECK"), 'chaine', 0, '', $conf->entity);
}
if ($action) {
@@ -102,6 +104,8 @@ if ($action) {
} else {
setEventMessages($langs->trans("SetupNotError"), null, 'errors');
}
+ header("Location: ".$_SERVER['PHP_SELF']);
+ exit;
}
/*
@@ -137,19 +141,48 @@ print '';
print '';
-// Default partnership price base type
-print '';
-print '| '.$langs->trans("PartnershipManagedFor").' | ';
-print '';
- print '';
-print ' | ';
+
+print '
';
+print '| '.$langs->trans("Setting").' | ';
+print ''.$langs->trans("Value").' | ';
+print ''.$langs->trans("Examples").' | ';
print '
';
-print '
';
+print '| '.$langs->trans("PARTNERSHIP_IS_MANAGED_FOR").' | ';
+print '';
+print '';
+print ' | ';
+print ''.$langs->trans("partnershipforthirdpartyormember").' | ';
+print '
';
+
+
+if($conf->global->PARTNERSHIP_IS_MANAGED_FOR == 'member'){
+ print '| '.$langs->trans("PARTNERSHIP_NBDAYS_AFTER_MEMBER_EXPIRATION_BEFORE_CANCEL").' | ';
+ print '';
+ $dnbdays = '7';
+ $backlinks = (!empty($conf->global->PARTNERSHIP_NBDAYS_AFTER_MEMBER_EXPIRATION_BEFORE_CANCEL)) ? $conf->global->PARTNERSHIP_NBDAYS_AFTER_MEMBER_EXPIRATION_BEFORE_CANCEL : $dnbdays;
+ print '';
+ print ' | ';
+ print ''.$dnbdays.' | ';
+ print '
';
+}
+
+
+print '| '.$langs->trans("PARTNERSHIP_BACKLINKS_TO_CHECK").' | ';
+print '';
+$dbacklinks = 'dolibarr.org|dolibarr.fr|dolibarr.es';
+$backlinks = (!empty($conf->global->PARTNERSHIP_BACKLINKS_TO_CHECK)) ? $conf->global->PARTNERSHIP_BACKLINKS_TO_CHECK : $dbacklinks;
+print '';
+print ' | ';
+print ''.$dbacklinks.' | ';
+print '
';
+
+
+print '';
print '';
print '';
print '
';
diff --git a/htdocs/partnership/class/partnership.class.php b/htdocs/partnership/class/partnership.class.php
index fd0233d3fef..6bf84ba38cc 100644
--- a/htdocs/partnership/class/partnership.class.php
+++ b/htdocs/partnership/class/partnership.class.php
@@ -118,6 +118,7 @@ class Partnership extends CommonObject
public $date_partnership_start;
public $date_partnership_end;
public $count_last_url_check_error;
+ public $last_check_backlink;
public $reason_decline_or_cancel;
// END MODULEBUILDER PROPERTIES
@@ -186,6 +187,7 @@ class Partnership extends CommonObject
'date_partnership_end' => array('type'=>'date', 'label'=>'DatePartnershipEnd', 'enabled'=>'1', 'position'=>53, 'notnull'=>1, 'visible'=>1,),
'status' => array('type'=>'smallint', 'label'=>'Status', 'enabled'=>'1', 'position'=>54, 'notnull'=>0, 'visible'=>2, 'index'=>1, 'arrayofkeyval'=>array('-1'=>'','0'=>$langs->trans('Draft'), '1'=>$langs->trans('Accepted'), '2'=>$langs->trans('Refused'), '9'=>$langs->trans('Canceled')),),
'count_last_url_check_error' => array('type'=>'integer', 'label'=>'CountLastUrlCheckError', 'enabled'=>'1', 'position'=>63, 'notnull'=>0, 'visible'=>-2, 'default'=>'0',),
+ 'last_check_backlink' => array('type'=>'datetime', 'label'=>'LastCheckBacklink', 'enabled'=>'1', 'position'=>65, 'notnull'=>0, 'visible'=>-2,),
'reason_decline_or_cancel' => array('type'=>'text', 'label'=>'ReasonDeclineOrCancel', 'enabled'=>'1', 'position'=>64, 'notnull'=>0, 'visible'=>-2,),
);
@@ -361,7 +363,7 @@ class Partnership extends CommonObject
$sql .= ', p.entity, p.date_partnership_start, p.date_partnership_end, p.date_creation';
$sql .= ', p.fk_user_creat, p.tms, p.fk_user_modif, p.fk_user_modif';
$sql .= ', p.note_private, p.note_public';
- $sql .= ', p.last_main_doc, p.count_last_url_check_error, p.reason_decline_or_cancel';
+ $sql .= ', p.last_main_doc, p.count_last_url_check_error, p.last_check_backlink, p.reason_decline_or_cancel';
$sql .= ', p.import_key, p.model_pdf';
$sql .= ' FROM '.MAIN_DB_PREFIX.'partnership as p';
@@ -407,6 +409,7 @@ class Partnership extends CommonObject
$this->note_public = $obj->note_public;
$this->last_main_doc = $obj->last_main_doc;
$this->count_last_url_check_error = $obj->count_last_url_check_error;
+ $this->last_check_backlink = $this->db->jdate($obj->last_check_backlink);
$this->reason_decline_or_cancel = $obj->reason_decline_or_cancel;
$this->import_key = $obj->import_key;
$this->model_pdf = $obj->model_pdf;
diff --git a/htdocs/partnership/class/partnershiputils.class.php b/htdocs/partnership/class/partnershiputils.class.php
index 08c61b3454c..64fd0f62431 100644
--- a/htdocs/partnership/class/partnershiputils.class.php
+++ b/htdocs/partnership/class/partnershiputils.class.php
@@ -26,9 +26,13 @@
require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
+require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
+
dol_include_once('partnership/lib/partnership.lib.php');
+dol_include_once('/partnership/class/partnership.class.php');
-
+require_once(DOL_DOCUMENT_ROOT."/societe/class/societe.class.php");
+require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
/**
* Class with cron tasks of Partnership module
*/
@@ -49,34 +53,422 @@ class PartnershipUtils
$this->db = $db;
return 1;
}
-
-
+
/**
- * Action executed by scheduler to cancel status of partnership when subscription is expired + x days. (Max number of cancel per call = $conf->global->PARTNERSHIP_MAX_CANCEL_PER_CALL)
+ * Action executed by scheduler to cancel status of partnership when subscription is expired + x days. (Max number of action batch per call = $conf->global->PARTNERSHIP_MAX_EXPIRATION_CANCEL_PER_CALL)
*
* CAN BE A CRON TASK
*
* @return int 0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK)
*/
- public function doCancelStatusOfPartnership()
+ public function doCancelStatusOfMemberPartnership()
{
global $conf, $langs, $user;
- $langs->load("agenda");
+ $managedfor = $conf->global->PARTNERSHIP_IS_MANAGED_FOR;
- $MAXPERCALL = (empty($conf->global->PARTNERSHIP_MAX_CANCEL_PER_CALL) ? 100 : $conf->global->PARTNERSHIP_MAX_CANCEL_PER_CALL); // Limit to 100 per call
+ if($managedfor != 'member'){
+ return 0; // If option 'PARTNERSHIP_IS_MANAGED_FOR' = 'thirdparty', this cron job does nothing.
+ }
- $error = 0;
- $this->output = '';
- $this->error='';
+ $partnership = new Partnership($this->db);
+ $MAXPERCALL = (empty($conf->global->PARTNERSHIP_MAX_EXPIRATION_CANCEL_PER_CALL) ? 25 : $conf->global->PARTNERSHIP_MAX_EXPIRATION_CANCEL_PER_CALL); // Limit to 25 per call
+
+ $langs->loadLangs(array("partnership", "member"));
+
+ $error = 0;
+ $erroremail = '';
+ $this->output = '';
+ $this->error = '';
+ $partnershipsprocessed = array();
+
+ $gracedelay=$conf->global->PARTNERSHIP_NBDAYS_AFTER_MEMBER_EXPIRATION_BEFORE_CANCEL;
+ if ($gracedelay < 1)
+ {
+ $this->error='BadValueForDelayBeforeCancelCheckSetup';
+ return -1;
+ }
+
+ dol_syslog(get_class($this)."::doCancelStatusOfMemberPartnership cancel expired partnerships with grace delay of ".$gracedelay);
+
+ $now = dol_now();
+ $datetotest = dol_time_plus_duree($now, -1 * abs($gracedelay), 'd');
+
+ $this->db->begin();
+
+ $sql = "SELECT p.rowid, p.fk_member, p.status";
+ $sql .= ", d.datefin, d.fk_adherent_type, dty.subscription";
+ $sql .= " FROM ".MAIN_DB_PREFIX."partnership as p";
+ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."adherent as d on (d.rowid = p.fk_member)";
+ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."adherent_type as dty on (dty.rowid = d.fk_adherent_type)";
+ $sql .= " WHERE fk_member > 0";
+ $sql .= " AND (d.datefin < '".$this->db->idate($datetotest)."' AND dty.subscription = 1)";
+ $sql .= " AND p.status = ".$partnership::STATUS_ACCEPTED; // Only accepted not yet canceled
+ $sql .= $this->db->order('d.rowid','ASC');
+ // Limit is managed into loop later
+
+ $resql = $this->db->query($sql);
+ if ($resql)
+ {
+ $numofexpiredmembers = $this->db->num_rows($resql);
+
+ $somethingdoneonpartnership = 0;
+ $ifetchpartner = 0;
+ while ($ifetchpartner < $numofexpiredmembers)
+ {
+ $ifetchpartner++;
+
+ $obj = $this->db->fetch_object($resql);
+ if ($obj)
+ {
+ if (! empty($partnershipsprocessed[$obj->rowid])) continue;
+
+ if ($somethingdoneonpartnership >= $MAXPERCALL)
+ {
+ dol_syslog("We reach the limit of ".$MAXPERCALL." partnership processed, so we quit loop for this batch doCancelStatusOfMemberPartnership to avoid to reach email quota.", LOG_WARNING);
+ break;
+ }
+
+ $object = new Partnership($this->db);
+ $object->fetch($obj->rowid);
+
+ // Get expiration date
+ $expirationdate = $obj->datefin;
+
+ if ($expirationdate && $expirationdate < $now) // If contract expired (we already had a test into main select, this is a security)
+ {
+ $somethingdoneonpartnership++;
+
+ $result = $object->cancel($user, 0);
+ // $conf->global->noapachereload = null;
+ if ($result < 0)
+ {
+ $error++;
+ $this->error = $object->error;
+ if (is_array($object->errors) && count($object->errors)) {
+ if (is_array($this->errors)) $this->errors = array_merge($this->errors, $object->errors);
+ else $this->errors = $object->errors;
+ }
+ }
+ else
+ {
+ $partnershipsprocessed[$object->id]=$object->ref;
+
+ // Send an email to inform member
+ $labeltemplate = '(SendingEmailOnPartnershipCanceled)';
+
+ dol_syslog("Now we will send an email to member id=".$object->fk_member." with label ".$labeltemplate);
+
+ // Send deployment email
+ include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
+ include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
+ $formmail=new FormMail($this->db);
+
+ // Define output language
+ $outputlangs = $langs;
+ $newlang = '';
+ if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09');
+ if (! empty($newlang)) {
+ $outputlangs = new Translate("", $conf);
+ $outputlangs->setDefaultLang($newlang);
+ $outputlangs->loadLangs(array('main','member','partnership'));
+ }
+
+ $arraydefaultmessage=$formmail->getEMailTemplate($this->db, 'partnership_send', $user, $outputlangs, 0, 1, $labeltemplate);
+
+ $substitutionarray=getCommonSubstitutionArray($outputlangs, 0, null, $object);
+ complete_substitutions_array($substitutionarray, $outputlangs, $object);
+
+ $subject = make_substitutions($arraydefaultmessage->topic, $substitutionarray, $outputlangs);
+ $msg = make_substitutions($arraydefaultmessage->content, $substitutionarray, $outputlangs);
+ $from = dol_string_nospecial($conf->global->MAIN_INFO_SOCIETE_NOM, ' ', array(",")).' <'.$conf->global->MAIN_INFO_SOCIETE_MAIL.'>';
+
+ $adherent = new Adherent($this->db);
+ $adherent->fetch($object->fk_member);
+ $to = $adherent->email;
+
+ $cmail = new CMailFile($subject, $to, $from, $msg, array(), array(), array(), '', '', 0, 1);
+ $result = $cmail->sendfile();
+ if (! $result || $cmail->error)
+ {
+ $erroremail .= ($erroremail ? ', ' : '').$cmail->error;
+ $this->errors[] = $cmail->error;
+ if (is_array($cmail->errors) && count($cmail->errors) > 0) $this->errors += $cmail->errors;
+ }
+ }
+
+ }
+ }
+ }
+ }
+ else
+ {
+ $error++;
+ $this->error = $this->db->lasterror();
+ }
+
+ if (! $error)
+ {
+ $this->db->commit();
+ $this->output = $numofexpiredmembers.' expired partnership members found'."\n";
+ if ($erroremail) $this->output.='. Got errors when sending some email : '.$erroremail;
+ }
+ else
+ {
+ $this->db->rollback();
+ $this->output = "Rollback after error\n";
+ $this->output.= $numofexpiredmembers.' expired partnership members found'."\n";
+ if ($erroremail) $this->output.='. Got errors when sending some email : '.$erroremail;
+ }
+
+ return ($error ? 1: 0);
+ }
- dol_syslog(__METHOD__." we cancel status of partnership ", LOG_DEBUG);
+ /**
+ * Action executed by scheduler to check if Dolibarr backlink not found on partner website. (Max number of action batch per call = $conf->global->PARTNERSHIP_MAX_WARNING_BACKLINK_PER_CALL)
+ *
+ * CAN BE A CRON TASK
+ *
+ * @return int 0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK)
+ */
+ public function doWarningOfPartnershipIfDolibarrBacklinkNotfound()
+ {
+ global $conf, $langs, $user;
- $now = dol_now();
+ $managedfor = $conf->global->PARTNERSHIP_IS_MANAGED_FOR;
- // En cours de traitement ...
+ $partnership = new Partnership($this->db);
+ $MAXPERCALL = (empty($conf->global->PARTNERSHIP_MAX_WARNING_BACKLINK_PER_CALL) ? 10 : $conf->global->PARTNERSHIP_MAX_WARNING_BACKLINK_PER_CALL); // Limit to 10 per call
- return ($error ? 1: 0);
+ $langs->loadLangs(array("partnership", "member"));
+
+ $error = 0;
+ $erroremail = '';
+ $this->output = '';
+ $this->error = '';
+ $partnershipsprocessed = array();
+
+ $gracedelay=$conf->global->PARTNERSHIP_NBDAYS_AFTER_MEMBER_EXPIRATION_BEFORE_CANCEL;
+ if ($gracedelay < 1)
+ {
+ $this->error='BadValueForDelayBeforeCancelCheckSetup';
+ return -1;
+ }
+
+ $fk_partner = ($managedfor == 'member') ? 'fk_member' : 'fk_soc';
+
+ dol_syslog(get_class($this)."::doWarningOfPartnershipIfDolibarrBacklinkNotfound Warning of partnership");
+
+ $now = dol_now();
+ $datetotest = dol_time_plus_duree($now, -1 * abs($gracedelay), 'd');
+
+ $this->db->begin();
+
+ $sql = "SELECT p.rowid, p.status, p.".$fk_partner;
+ $sql .= ", p.last_check_backlink";
+
+ $sql .= ', partner.url, partner.email';
+
+ $sql .= " FROM ".MAIN_DB_PREFIX."partnership as p";
+
+ if ($managedfor == 'member') {
+ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."adherent as partner on (partner.rowid = p.fk_member)";
+ } else {
+ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as partner on (partner.rowid = p.fk_soc)";
+ }
+
+ $sql .= " WHERE 1 = 1";
+ $sql .= " AND p.".$fk_partner." > 0";
+ $sql .= " AND p.status = ".$partnership::STATUS_ACCEPTED; // Only accepted not yet canceled
+ $sql .= " AND (p.last_check_backlink IS NULL OR p.last_check_backlink <= '".$this->db->idate($now - 7 * 24 * 3600)."')"; // Every week, check that website contains a link to dolibarr.
+ $sql .= $this->db->order('p.rowid','ASC');
+ // Limit is managed into loop later
+
+ $resql = $this->db->query($sql);
+ if ($resql)
+ {
+ $numofexpiredmembers = $this->db->num_rows($resql);
+ $somethingdoneonpartnership = 0;
+ $ifetchpartner = 0;
+ while ($ifetchpartner < $numofexpiredmembers)
+ {
+ $ifetchpartner++;
+
+ $obj = $this->db->fetch_object($resql);
+ if ($obj)
+ {
+ if (! empty($partnershipsprocessed[$obj->rowid])) continue;
+
+ if ($somethingdoneonpartnership >= $MAXPERCALL)
+ {
+ dol_syslog("We reach the limit of ".$MAXPERCALL." partnership processed, so we quit loop for this batch doWarningOfPartnershipIfDolibarrBacklinkNotfound to avoid to reach email quota.", LOG_WARNING);
+ break;
+ }
+
+ $backlinkfound = 0;
+
+ $object = new Partnership($this->db);
+ $object->fetch($obj->rowid);
+
+ if($managedfor == 'member'){
+ $fk_partner = $object->fk_member;
+ }else{
+ $fk_partner = $object->fk_soc;
+ }
+
+ $website = $obj->url;
+
+ if(empty($website)){
+ $websitenotfound .= ($websitenotfound ? ', ' : '').'Website not found for id="'.$fk_partner.'"'."\n";
+ } else {
+ $backlinkfound = $this->checkDolibarrBacklink($website);
+ }
+
+ if(!$backlinkfound){
+ $tmpcount = $object->count_last_url_check_error + 1;
+
+ if($tmpcount == 3){ // Send Warning Email
+
+ if (!empty($obj->email)){
+ $emailnotfound .= ($emailnotfound ? ', ' : '').'Email not found for id="'.$fk_partner.'"'."\n";
+
+ } else {
+
+ $labeltemplate = '(SendingEmailOnPartnershipWillExpire)';
+
+ dol_syslog("Now we will send an email to partner id=".$fk_partner." with label ".$labeltemplate);
+
+ // Send deployment email
+ include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
+ include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
+ $formmail=new FormMail($this->db);
+
+ // Define output language
+ $outputlangs = $langs;
+ $newlang = '';
+ if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09');
+ if (! empty($newlang)) {
+ $outputlangs = new Translate("", $conf);
+ $outputlangs->setDefaultLang($newlang);
+ $outputlangs->loadLangs(array('main','member','partnership'));
+ }
+
+ $arraydefaultmessage=$formmail->getEMailTemplate($this->db, 'partnership_send', $user, $outputlangs, 0, 1, $labeltemplate);
+
+ $substitutionarray=getCommonSubstitutionArray($outputlangs, 0, null, $object);
+ complete_substitutions_array($substitutionarray, $outputlangs, $object);
+
+ $subject = make_substitutions($arraydefaultmessage->topic, $substitutionarray, $outputlangs);
+ $msg = make_substitutions($arraydefaultmessage->content, $substitutionarray, $outputlangs);
+ $from = dol_string_nospecial($conf->global->MAIN_INFO_SOCIETE_NOM, ' ', array(",")).' <'.$conf->global->MAIN_INFO_SOCIETE_MAIL.'>';
+
+ $to = $obj->email;
+
+ $cmail = new CMailFile($subject, $to, $from, $msg, array(), array(), array(), '', '', 0, 1);
+ $result = $cmail->sendfile();
+ if (! $result || $cmail->error)
+ {
+ $erroremail .= ($erroremail ? ', ' : '').$cmail->error;
+ $this->errors[] = $cmail->error;
+ if (is_array($cmail->errors) && count($cmail->errors) > 0) $this->errors += $cmail->errors;
+ }
+ }
+
+
+ } elseif($tmpcount > 4) { // Cancel Partnership
+ $object->status = $object::STATUS_CANCELED;
+ $object->reason_decline_or_cancel = $langs->trans('BacklinkNotFoundOnPartnerWebsite');
+ }
+
+ $object->count_last_url_check_error = $tmpcount;
+
+ } else {
+ $object->count_last_url_check_error = 0;
+ $object->reason_decline_or_cancel = '';
+ }
+
+ $partnershipsprocessed[$object->id]=$object->ref;
+
+ $object->last_check_backlink = $this->db->idate($now);
+
+ $object->update($user);
+ }
+ }
+ }
+ else
+ {
+ $error++;
+ $this->error = $this->db->lasterror();
+ }
+
+ if (! $error)
+ {
+ $this->db->commit();
+ $this->output = $numofexpiredmembers.' partnership checked'."\n";
+ if ($erroremail) $this->output.='. Got errors when sending some email : '.$erroremail."\n";
+ if ($emailnotfound) $this->output.='. Email not found for some partner : '.$emailnotfound."\n";
+ if ($websitenotfound) $this->output.='. Website not found for some partner : '.$websitenotfound."\n";
+ }
+ else
+ {
+ $this->db->rollback();
+ $this->output = "Rollback after error\n";
+ $this->output.= $numofexpiredmembers.' partnership checked'."\n";
+ if ($erroremail) $this->output.='. Got errors when sending some email : '.$erroremail."\n";
+ if ($emailnotfound) $this->output.='. Email not found for some partner : '.$emailnotfound."\n";
+ if ($websitenotfound) $this->output.='. Website not found for some partner : '.$websitenotfound."\n";
+ }
+
+ return ($error ? 1: 0);
+ }
+
+ /**
+ * Action to check if Dolibarr backlink not found on partner website
+ *
+ * CAN BE A CRON TASK
+ *
+ * @return int 0 if KO, 1 if OK
+ */
+ public function checkDolibarrBacklink($website = null)
+ {
+ global $conf, $langs, $user;
+
+ $found = 0;
+ $error = 0;
+ $webcontent = '';
+
+ // $website = 'https://nextgestion.com/'; // For Test
+ $tmpgeturl = getURLContent($website);
+ if ($tmpgeturl['curl_error_no']) {
+ $error++;
+ dol_syslog('Error getting '.$website.': '.$tmpgeturl['curl_error_msg']);
+ } elseif ($tmpgeturl['http_code'] != '200') {
+ $error++;
+ dol_syslog('Error getting '.$website.': '.$tmpgeturl['curl_error_msg']);
+ } else {
+ $urlContent = $tmpgeturl['content'];
+ $dom = new DOMDocument();
+ @$dom->loadHTML($urlContent);
+
+ $xpath = new DOMXPath($dom);
+ $hrefs = $xpath->evaluate("//a");
+
+ for($i = 0; $i < $hrefs->length; $i++){
+ $href = $hrefs->item($i);
+ $url = $href->getAttribute('href');
+ $url = filter_var($url, FILTER_SANITIZE_URL);
+ if(!filter_var($url, FILTER_VALIDATE_URL) === false){
+ $webcontent .= $url;
+ }
+ }
+ }
+
+ if ($webcontent && !empty($conf->global->PARTNERSHIP_BACKLINKS_TO_CHECK) && preg_match('/'.$conf->global->PARTNERSHIP_BACKLINKS_TO_CHECK.'/', $webcontent))
+ {
+ $found = 1;
+ }
+
+ return $found;
}
}
diff --git a/htdocs/partnership/partnership_list.php b/htdocs/partnership/partnership_list.php
index 5ded7ae0047..1ae90d0d4cf 100644
--- a/htdocs/partnership/partnership_list.php
+++ b/htdocs/partnership/partnership_list.php
@@ -496,9 +496,9 @@ $param .= $hookmanager->resPrint;
// List of mass actions available
$arrayofmassactions = array(
'cancel'=>img_picto('', 'close_title', 'class="pictofixedwidth"').$langs->trans("Cancel"),
- //'generate_doc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("ReGeneratePDF"),
- //'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"),
- 'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"),
+ //'generate_doc'=>img_picto('', 'pdf').$langs->trans("ReGeneratePDF"),
+ //'builddoc'=>img_picto('', 'pdf').$langs->trans("PDFMerge"),
+ 'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendMail"),
);
if ($permissiontodelete) {
$arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");