forked from Wavyzz/dolibarr
NEW API for handling mass mailing targets (#35603)
* NEW API for handling mailing targets * fix PHP Codesniffer * adding return values to make phpstan happy * Update function actually updates * defining mailing_target public function create * using a different language translation * mailing_target - phpstan fixes * mailing target - no check properties body * mailing target int typecast fk_mailing * mailing target - just 1 parameter * mailing_target phpstan fixes * mailing_target setting labelStatus * mailing target class public function delete * reveal the list of status name for the Mass mailing object in the API * set tms to now when it is set to draft * functions to set the mailing target status * hurl testing api mailings * hurl test - exit run script at first error * hurl test mailings - should cover all endpoints * using self:: in front of the CONST * Trying to find out which line evaluates to noting * API mailings can now get the targets of a mailing * Protected method name "Mailings::_cleanTargetDatas" must not be prefixed with an underscore * give me fk_project * API endpoints for: Get all targets of a mass mailing + Get information about a specific target id * API endpoint to update a mailing target * telling pre-commit check to ignore, just like done in the function I copied * be more explicit about for GUI tests we need username and password * Prevent updating fk_mailing value * API endpoint deleteTarget * post to create a mailing target does work, but need slight more testing after work * correct indent * fixing some build errors * More comprehensive hurl test of creation of a target * adding status_dest to mailing targets json --------- Co-authored-by: Jon Bendtsen <xcodeauthor@jonb.dk>
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
use Luracast\Restler\RestException;
|
use Luracast\Restler\RestException;
|
||||||
|
|
||||||
require_once DOL_DOCUMENT_ROOT.'/comm/mailing/class/mailing.class.php';
|
require_once DOL_DOCUMENT_ROOT.'/comm/mailing/class/mailing.class.php';
|
||||||
|
require_once DOL_DOCUMENT_ROOT.'/comm/mailing/class/mailing_targets.class.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API class for mass mailings
|
* API class for mass mailings
|
||||||
@@ -39,11 +40,24 @@ class Mailings extends DolibarrApi
|
|||||||
'body'
|
'body'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string[] Mandatory fields, checked when create and update object
|
||||||
|
*/
|
||||||
|
public static $TARGETFIELDS = array(
|
||||||
|
'fk_mailing',
|
||||||
|
'email'
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Mailing {@type Mailing}
|
* @var Mailing {@type Mailing}
|
||||||
*/
|
*/
|
||||||
public $mailing;
|
public $mailing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var MailingTarget {@type MailingTarget}
|
||||||
|
*/
|
||||||
|
public $mailing_target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
@@ -52,6 +66,7 @@ class Mailings extends DolibarrApi
|
|||||||
global $db;
|
global $db;
|
||||||
$this->db = $db;
|
$this->db = $db;
|
||||||
$this->mailing = new Mailing($this->db);
|
$this->mailing = new Mailing($this->db);
|
||||||
|
$this->mailing_target = new MailingTarget($this->db);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -125,7 +140,8 @@ class Mailings extends DolibarrApi
|
|||||||
* @phan-return Mailing[]|array{data:Mailing[],pagination:array{total:int,page:int,page_count:int,limit:int}}
|
* @phan-return Mailing[]|array{data:Mailing[],pagination:array{total:int,page:int,page_count:int,limit:int}}
|
||||||
* @phpstan-return Mailing[]|array{data:Mailing[],pagination:array{total:int,page:int,page_count:int,limit:int}}
|
* @phpstan-return Mailing[]|array{data:Mailing[],pagination:array{total:int,page:int,page_count:int,limit:int}}
|
||||||
*
|
*
|
||||||
* @throws RestException
|
* @throws RestException 400
|
||||||
|
* @throws RestException 403
|
||||||
*/
|
*/
|
||||||
public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $fk_projects = '', $sqlfilters = '', $properties = '', $pagination_data = false, $loadlinkedobjects = 0)
|
public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $fk_projects = '', $sqlfilters = '', $properties = '', $pagination_data = false, $loadlinkedobjects = 0)
|
||||||
{
|
{
|
||||||
@@ -213,6 +229,114 @@ class Mailings extends DolibarrApi
|
|||||||
return $obj_ret;
|
return $obj_ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List mass mailing targets
|
||||||
|
*
|
||||||
|
* Get a list of mass mailing targets
|
||||||
|
*
|
||||||
|
* @since 23.0.0 Initial implementation
|
||||||
|
*
|
||||||
|
* @param int $id Mass mailing ID
|
||||||
|
* @param string $sortfield Sort field
|
||||||
|
* @param string $sortorder Sort order
|
||||||
|
* @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.lastname:like:'John Doe') and (t.statut:=:3)"
|
||||||
|
* @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names
|
||||||
|
* @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0*
|
||||||
|
* @return array Array of order objects
|
||||||
|
* @phan-return Mailing[]|array{data:Mailing[],pagination:array{total:int,page:int,page_count:int,limit:int}}
|
||||||
|
* @phpstan-return Mailing[]|array{data:Mailing[],pagination:array{total:int,page:int,page_count:int,limit:int}}
|
||||||
|
*
|
||||||
|
* @url GET {id}/targets
|
||||||
|
*
|
||||||
|
* @throws RestException 400
|
||||||
|
* @throws RestException 403
|
||||||
|
* @throws RestException 404
|
||||||
|
*/
|
||||||
|
public function indexTargets($id, $sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $sqlfilters = '', $properties = '', $pagination_data = false)
|
||||||
|
{
|
||||||
|
if (!DolibarrApiAccess::$user->hasRight('mailing', 'read')) {
|
||||||
|
throw new RestException(403);
|
||||||
|
}
|
||||||
|
|
||||||
|
$fetchMailingResult = $this->mailing->fetch($id);
|
||||||
|
if ($fetchMailingResult < 0) {
|
||||||
|
throw new RestException(404, 'Mass mailing not found, id='.$id);
|
||||||
|
}
|
||||||
|
|
||||||
|
$fk_project = $this->mailing->fk_project;
|
||||||
|
if (!DolibarrApi::_checkAccessToResource('project', ((int) $fk_project))) {
|
||||||
|
throw new RestException(403, 'Access (project) not allowed for login '.DolibarrApiAccess::$user->login);
|
||||||
|
}
|
||||||
|
|
||||||
|
$obj_ret = array();
|
||||||
|
|
||||||
|
$sql = "SELECT t.rowid";
|
||||||
|
$sql .= " FROM ".MAIN_DB_PREFIX."mailing_cibles AS t";
|
||||||
|
$sql .= " WHERE t.fk_mailing = ".((int) $id);
|
||||||
|
|
||||||
|
// Add sql filters
|
||||||
|
if ($sqlfilters) {
|
||||||
|
$errormessage = '';
|
||||||
|
$sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
|
||||||
|
if ($errormessage) {
|
||||||
|
throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//this query will return total mass mailing targets with the filters given
|
||||||
|
$sqlTotals = str_replace('SELECT t.rowid', 'SELECT count(t.rowid) as total', $sql);
|
||||||
|
|
||||||
|
$sql .= $this->db->order($sortfield, $sortorder);
|
||||||
|
if ($limit) {
|
||||||
|
if ($page < 0) {
|
||||||
|
$page = 0;
|
||||||
|
}
|
||||||
|
$offset = $limit * $page;
|
||||||
|
|
||||||
|
$sql .= $this->db->plimit($limit + 1, $offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
dol_syslog("API Rest request mass mailing target");
|
||||||
|
$result = $this->db->query($sql);
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
$num = $this->db->num_rows($result);
|
||||||
|
$min = min($num, ($limit <= 0 ? $num : $limit));
|
||||||
|
$i = 0;
|
||||||
|
while ($i < $min) {
|
||||||
|
$obj = $this->db->fetch_object($result);
|
||||||
|
$mailing_target = new MailingTarget($this->db);
|
||||||
|
if ($mailing_target->fetch($obj->rowid) > 0) {
|
||||||
|
$obj_ret[] = $this->_filterObjectProperties($this->_cleanTargetDatas($mailing_target), $properties);
|
||||||
|
}
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new RestException(503, 'Error when retrieve list of mass mailing targetss : '.$this->db->lasterror());
|
||||||
|
}
|
||||||
|
|
||||||
|
//if $pagination_data is true the response will contain element data with all values and element pagination with pagination data(total,page,limit)
|
||||||
|
if ($pagination_data) {
|
||||||
|
$totalsResult = $this->db->query($sqlTotals);
|
||||||
|
$total = $this->db->fetch_object($totalsResult)->total;
|
||||||
|
|
||||||
|
$tmp = $obj_ret;
|
||||||
|
$obj_ret = [];
|
||||||
|
|
||||||
|
$obj_ret['data'] = $tmp;
|
||||||
|
$obj_ret['pagination'] = [
|
||||||
|
'total' => (int) $total,
|
||||||
|
'page' => $page, //count starts from 0
|
||||||
|
'page_count' => ceil((int) $total / $limit),
|
||||||
|
'limit' => $limit
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $obj_ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clone a mass mailing
|
* Clone a mass mailing
|
||||||
*
|
*
|
||||||
@@ -264,7 +388,8 @@ class Mailings extends DolibarrApi
|
|||||||
* @phpstan-param ?array<string,string> $request_data
|
* @phpstan-param ?array<string,string> $request_data
|
||||||
* @return int ID of mass mailing
|
* @return int ID of mass mailing
|
||||||
*
|
*
|
||||||
* @throws RestException
|
* @throws RestException 403
|
||||||
|
* @throws RestException 500 System error
|
||||||
*/
|
*/
|
||||||
public function post($request_data = null)
|
public function post($request_data = null)
|
||||||
{
|
{
|
||||||
@@ -307,7 +432,9 @@ class Mailings extends DolibarrApi
|
|||||||
* @phpstan-param ?array<string,string> $request_data
|
* @phpstan-param ?array<string,string> $request_data
|
||||||
* @return Object Object with cleaned properties
|
* @return Object Object with cleaned properties
|
||||||
*
|
*
|
||||||
* @throws RestException
|
* @throws RestException 403
|
||||||
|
* @throws RestException 404
|
||||||
|
* @throws RestException 500 System error
|
||||||
*/
|
*/
|
||||||
public function put($id, $request_data = null)
|
public function put($id, $request_data = null)
|
||||||
{
|
{
|
||||||
@@ -397,6 +524,254 @@ class Mailings extends DolibarrApi
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update a mass mailing general fields (won't change lines of mass mailing)
|
||||||
|
*
|
||||||
|
* @since 23.0.0 Initial implementation
|
||||||
|
*
|
||||||
|
* @param int $id Id of mass mailing with the targetid to update
|
||||||
|
* @param int $targetid Id mass mailing target to update
|
||||||
|
* @param array $request_data Datas
|
||||||
|
* @phan-param ?array<string,string> $request_data
|
||||||
|
* @phpstan-param ?array<string,string> $request_data
|
||||||
|
* @return Object Object with cleaned properties
|
||||||
|
*
|
||||||
|
* @url PUT {id}/updateTarget/{targetid}
|
||||||
|
*
|
||||||
|
* @throws RestException 403
|
||||||
|
* @throws RestException 404
|
||||||
|
* @throws RestException 500 System error
|
||||||
|
*/
|
||||||
|
public function updateTarget($id, $targetid, $request_data = null)
|
||||||
|
{
|
||||||
|
if (!DolibarrApiAccess::$user->hasRight('mailing', 'write')) {
|
||||||
|
throw new RestException(403);
|
||||||
|
}
|
||||||
|
|
||||||
|
$fetchMailingResult = $this->mailing->fetch($id);
|
||||||
|
if ($fetchMailingResult < 0) {
|
||||||
|
throw new RestException(404, 'Mass mailing not found, id='.$id);
|
||||||
|
}
|
||||||
|
$result = $this->mailing_target->fetch($targetid);
|
||||||
|
if ($result < 0) {
|
||||||
|
throw new RestException(404, 'Mass mailing target not found, id='.$targetid);
|
||||||
|
}
|
||||||
|
if ($id != $this->mailing_target->fk_mailing) {
|
||||||
|
throw new RestException(404, 'Target id='.$targetid.' is does not belong to mailing id='.$id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DolibarrApi::_checkAccessToResource('project', ((int) $this->mailing->fk_project))) {
|
||||||
|
throw new RestException(403, 'Access (project) not allowed for login '.DolibarrApiAccess::$user->login);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DolibarrApi::_checkAccessToResource('mailing', $this->mailing->id)) {
|
||||||
|
throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
|
||||||
|
}
|
||||||
|
foreach ($request_data as $field => $value) {
|
||||||
|
if ($field == 'id') {
|
||||||
|
throw new RestException(400, 'Changing id field is forbidden');
|
||||||
|
}
|
||||||
|
if ($field == 'fk_mailing') {
|
||||||
|
throw new RestException(400, 'Changing fk_mailing field is forbidden to protect inserting a wrong fk_mailing number. Use a POST to create a new mailing target with the correct mailing id, then an PUT to update the new target in the right mailing id, and finally a delete to remove the old target');
|
||||||
|
}
|
||||||
|
if ($field === 'caller') {
|
||||||
|
// Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller
|
||||||
|
$this->mailing_target->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->mailing_target->$field = $this->_checkValForAPI($field, $value, $this->mailing_target);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->mailing_target->update(DolibarrApiAccess::$user) > 0) {
|
||||||
|
return $this->getTarget($id, $targetid);
|
||||||
|
} else {
|
||||||
|
throw new RestException(500, $this->mailing_target->error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a mass mailing
|
||||||
|
*
|
||||||
|
* @since 23.0.0 Initial implementation
|
||||||
|
*
|
||||||
|
* @param int $id Id of mass mailing to create a target for
|
||||||
|
* @param array $request_data Request data
|
||||||
|
* @phan-param ?array<string,string> $request_data
|
||||||
|
* @phpstan-param ?array<string,string> $request_data
|
||||||
|
* @return int ID of mass mailing
|
||||||
|
*
|
||||||
|
* @url POST {id}/createTarget
|
||||||
|
*
|
||||||
|
* @throws RestException 400
|
||||||
|
* @throws RestException 403
|
||||||
|
* @throws RestException 404
|
||||||
|
* @throws RestException 500 System error
|
||||||
|
*/
|
||||||
|
public function postTarget($id, $request_data = null)
|
||||||
|
{
|
||||||
|
if (!DolibarrApiAccess::$user->hasRight('mailing', 'write')) {
|
||||||
|
throw new RestException(403, "Insufficiant rights");
|
||||||
|
}
|
||||||
|
// Check mandatory fields
|
||||||
|
$result = $this->_validateTarget($request_data);
|
||||||
|
|
||||||
|
$fk_mailing_id = 0;
|
||||||
|
|
||||||
|
foreach ($request_data as $field => $value) {
|
||||||
|
if ($field === 'caller') {
|
||||||
|
// Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller
|
||||||
|
$this->mailing_target->context['caller'] = sanitizeVal($request_data['caller'], 'aZ09');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($field === 'fk_project') {
|
||||||
|
if (!DolibarrApi::_checkAccessToResource('project', ((int) $value))) {
|
||||||
|
throw new RestException(403, 'Access (project) not allowed for login '.DolibarrApiAccess::$user->login);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($field == 'id') {
|
||||||
|
throw new RestException(400, 'Creating with id field is forbidden');
|
||||||
|
}
|
||||||
|
if ($field == 'fk_mailing') {
|
||||||
|
$fetchMailingResult = $this->mailing->fetch((int) $value);
|
||||||
|
if ($fetchMailingResult < 0) {
|
||||||
|
throw new RestException(404, 'Mass mailing not found, id='.((int) $value));
|
||||||
|
}
|
||||||
|
if (!DolibarrApi::_checkAccessToResource('project', ((int) $this->mailing->fk_project))) {
|
||||||
|
throw new RestException(403, 'Access (project) not allowed for login '.DolibarrApiAccess::$user->login);
|
||||||
|
}
|
||||||
|
$fk_mailing_id = ((int) $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->mailing_target->$field = $this->_checkValForAPI($field, $value, $this->mailing_target);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == $fk_mailing_id) {
|
||||||
|
throw new RestException(404, 'Mass mailing not found, id='.((int) $fk_mailing_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->mailing_target->create(DolibarrApiAccess::$user) < 0) {
|
||||||
|
throw new RestException(500, "Error creating mass mailing target", array_merge(array($this->mailing->error), $this->mailing->errors));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((int) $this->mailing_target->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a target in a mass mailing
|
||||||
|
*
|
||||||
|
* Return an array with info about a mass mailing target
|
||||||
|
*
|
||||||
|
* @since 23.0.0 Initial implementation
|
||||||
|
*
|
||||||
|
* @param int $id Id of mass mailing with the targetid to get
|
||||||
|
* @param int $targetid Id mass mailing target to get
|
||||||
|
* @return Object Object with cleaned properties
|
||||||
|
*
|
||||||
|
* @url GET {id}/getTarget/{targetid}
|
||||||
|
*
|
||||||
|
* @throws RestException
|
||||||
|
*/
|
||||||
|
public function getTarget($id, $targetid)
|
||||||
|
{
|
||||||
|
return $this->_fetchTarget($id, $targetid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get properties of an mailing object
|
||||||
|
*
|
||||||
|
* Return an array with mailing information
|
||||||
|
*
|
||||||
|
* @param int $id ID of mailing object
|
||||||
|
* @param int $targetid Id mass mailing target
|
||||||
|
* @return Object Object with cleaned properties
|
||||||
|
*
|
||||||
|
* @throws RestException 403
|
||||||
|
* @throws RestException 404
|
||||||
|
*/
|
||||||
|
private function _fetchTarget($id, $targetid)
|
||||||
|
{
|
||||||
|
if (!DolibarrApiAccess::$user->hasRight('mailing', 'read')) {
|
||||||
|
throw new RestException(403);
|
||||||
|
}
|
||||||
|
|
||||||
|
$fetchMailingResult = $this->mailing->fetch($id);
|
||||||
|
if ($fetchMailingResult < 0) {
|
||||||
|
throw new RestException(404, 'Mass mailing not found, id='.$id);
|
||||||
|
}
|
||||||
|
$result = $this->mailing_target->fetch($targetid);
|
||||||
|
if ($result < 0) {
|
||||||
|
throw new RestException(404, 'Mass mailing target not found, id='.$targetid);
|
||||||
|
}
|
||||||
|
if ($id != $this->mailing_target->fk_mailing) {
|
||||||
|
throw new RestException(404, 'Target id='.$targetid.' is does not belong to mailing id='.$id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DolibarrApi::_checkAccessToResource('project', ((int) $this->mailing->fk_project))) {
|
||||||
|
throw new RestException(403, 'Access (project) not allowed for login '.DolibarrApiAccess::$user->login);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DolibarrApi::_checkAccessToResource('mailing', $this->mailing->id)) {
|
||||||
|
throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->_cleanTargetDatas($this->mailing_target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a mass mailing general fields (won't change lines of mass mailing)
|
||||||
|
*
|
||||||
|
* @since 23.0.0 Initial implementation
|
||||||
|
*
|
||||||
|
* @param int $id Id of mass mailing with the targetid to delete
|
||||||
|
* @param int $targetid Id mass mailing target to delete
|
||||||
|
* @return array
|
||||||
|
* @phan-return array{success:array{code:int,message:string}}
|
||||||
|
* @phpstan-return array{success:array{code:int,message:string}}
|
||||||
|
*
|
||||||
|
* @url DELETE {id}/deleteTarget/{targetid}
|
||||||
|
*
|
||||||
|
* @throws RestException 403
|
||||||
|
* @throws RestException 404
|
||||||
|
* @throws RestException 500 System error
|
||||||
|
*/
|
||||||
|
public function deleteTarget($id, $targetid)
|
||||||
|
{
|
||||||
|
if (!DolibarrApiAccess::$user->hasRight('mailing', 'delete')) {
|
||||||
|
throw new RestException(403);
|
||||||
|
}
|
||||||
|
|
||||||
|
$fetchMailingResult = $this->mailing->fetch($id);
|
||||||
|
if ($fetchMailingResult < 0) {
|
||||||
|
throw new RestException(404, 'Mass mailing not found, id='.$id);
|
||||||
|
}
|
||||||
|
$result = $this->mailing_target->fetch($targetid);
|
||||||
|
if ($result < 0) {
|
||||||
|
throw new RestException(404, 'Mass mailing target not found, id='.$targetid);
|
||||||
|
}
|
||||||
|
if ($id != $this->mailing_target->fk_mailing) {
|
||||||
|
throw new RestException(404, 'Target id='.$targetid.' is does not belong to mailing id='.$id);
|
||||||
|
}
|
||||||
|
if (!DolibarrApi::_checkAccessToResource('project', ((int) $this->mailing->fk_project))) {
|
||||||
|
throw new RestException(403, 'Access (project) not allowed for login '.DolibarrApiAccess::$user->login);
|
||||||
|
}
|
||||||
|
if (!DolibarrApi::_checkAccessToResource('mailing', $this->mailing->id)) {
|
||||||
|
throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->mailing_target->delete(DolibarrApiAccess::$user)) {
|
||||||
|
throw new RestException(500, 'Error when delete Mass mailing target: '.$this->mailing->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'success' => array(
|
||||||
|
'code' => 200,
|
||||||
|
'message' => 'Deleting target id='.$targetid.' belonging to mailing id='.$id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete targets of a mass mailing
|
* Delete targets of a mass mailing
|
||||||
*
|
*
|
||||||
@@ -612,6 +987,162 @@ class Mailings extends DolibarrApi
|
|||||||
return $mailing;
|
return $mailing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate fields before create or update object
|
||||||
|
*
|
||||||
|
* @param ?array<string,string> $data Array with data to verify
|
||||||
|
* @return array<string,string>
|
||||||
|
*
|
||||||
|
* @throws RestException
|
||||||
|
*/
|
||||||
|
private function _validateTarget($data)
|
||||||
|
{
|
||||||
|
if ($data === null) {
|
||||||
|
$data = array();
|
||||||
|
}
|
||||||
|
$mailing_target = array();
|
||||||
|
foreach (Mailings::$TARGETFIELDS as $field) {
|
||||||
|
if (!isset($data[$field])) {
|
||||||
|
throw new RestException(400, "$field field missing");
|
||||||
|
}
|
||||||
|
$mailing_target[$field] = $data[$field];
|
||||||
|
}
|
||||||
|
return $mailing_target;
|
||||||
|
}
|
||||||
|
|
||||||
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
|
||||||
|
/**
|
||||||
|
* Clean sensible object (mailing target) datas
|
||||||
|
*
|
||||||
|
* @param Object $object Object to clean
|
||||||
|
* @return Object Object with cleaned properties
|
||||||
|
*/
|
||||||
|
protected function _cleanTargetDatas($object)
|
||||||
|
{
|
||||||
|
// phpcs:enable
|
||||||
|
$object = parent::_cleanObjectDatas($object);
|
||||||
|
|
||||||
|
unset($object->TRIGGER_PREFIX);
|
||||||
|
unset($object->actionmsg);
|
||||||
|
unset($object->actionmsg2);
|
||||||
|
unset($object->actiontypecode);
|
||||||
|
unset($object->alreadypaid);
|
||||||
|
unset($object->array_options);
|
||||||
|
unset($object->array_languages);
|
||||||
|
unset($object->barcode_type_code);
|
||||||
|
unset($object->barcode_type_coder);
|
||||||
|
unset($object->barcode_type_label);
|
||||||
|
unset($object->barcode_type);
|
||||||
|
unset($object->canvas);
|
||||||
|
unset($object->civility_code);
|
||||||
|
unset($object->civility_id);
|
||||||
|
unset($object->comments);
|
||||||
|
unset($object->cond_reglement_id);
|
||||||
|
unset($object->cond_reglement_supplier_id);
|
||||||
|
unset($object->contact_id);
|
||||||
|
unset($object->contact);
|
||||||
|
unset($object->contacts_ids_internal);
|
||||||
|
unset($object->contacts_ids);
|
||||||
|
unset($object->context);
|
||||||
|
unset($object->country_code);
|
||||||
|
unset($object->country_id);
|
||||||
|
unset($object->country);
|
||||||
|
unset($object->date_cloture);
|
||||||
|
unset($object->date_creation);
|
||||||
|
unset($object->date_validation);
|
||||||
|
unset($object->db);
|
||||||
|
unset($object->demand_reason_id);
|
||||||
|
unset($object->deposit_percent);
|
||||||
|
unset($object->element_for_permission);
|
||||||
|
unset($object->element);
|
||||||
|
unset($object->entity);
|
||||||
|
unset($object->error);
|
||||||
|
unset($object->errorhidden);
|
||||||
|
unset($object->errors);
|
||||||
|
unset($object->extraparams);
|
||||||
|
unset($object->fields);
|
||||||
|
unset($object->fk_account);
|
||||||
|
unset($object->fk_bank);
|
||||||
|
unset($object->fk_delivery_address);
|
||||||
|
unset($object->fk_element);
|
||||||
|
unset($object->fk_multicurrency);
|
||||||
|
unset($object->fk_projet);
|
||||||
|
unset($object->fk_project);
|
||||||
|
unset($object->fk_user_creat);
|
||||||
|
unset($object->fk_user_modif);
|
||||||
|
unset($object->import_key);
|
||||||
|
unset($object->isextrafieldmanaged);
|
||||||
|
unset($object->ismultientitymanaged);
|
||||||
|
unset($object->last_main_doc);
|
||||||
|
unset($object->lines);
|
||||||
|
unset($object->linked_objects);
|
||||||
|
unset($object->linkedObjects);
|
||||||
|
unset($object->linkedObjectsIds);
|
||||||
|
unset($object->mode_reglement_id);
|
||||||
|
unset($object->model_pdf);
|
||||||
|
unset($object->module);
|
||||||
|
unset($object->multicurrency_code);
|
||||||
|
unset($object->multicurrency_total_ht);
|
||||||
|
unset($object->multicurrency_total_localtax1);
|
||||||
|
unset($object->multicurrency_total_localtax2);
|
||||||
|
unset($object->multicurrency_total_ttc);
|
||||||
|
unset($object->multicurrency_total_tva);
|
||||||
|
unset($object->multicurrency_tx);
|
||||||
|
unset($object->name);
|
||||||
|
unset($object->nb);
|
||||||
|
unset($object->nbphoto);
|
||||||
|
unset($object->newref);
|
||||||
|
unset($object->next_prev_filter);
|
||||||
|
unset($object->note);
|
||||||
|
unset($object->note_public);
|
||||||
|
unset($object->note_private);
|
||||||
|
unset($object->oldcopy);
|
||||||
|
unset($object->oldref);
|
||||||
|
unset($object->origin_id);
|
||||||
|
unset($object->origin_object);
|
||||||
|
unset($object->origin_type);
|
||||||
|
unset($object->origin);
|
||||||
|
unset($object->output);
|
||||||
|
unset($object->product);
|
||||||
|
unset($object->project);
|
||||||
|
unset($object->ref_ext);
|
||||||
|
unset($object->ref_next);
|
||||||
|
unset($object->ref_previous);
|
||||||
|
unset($object->ref);
|
||||||
|
unset($object->region_code);
|
||||||
|
unset($object->region_id);
|
||||||
|
unset($object->region);
|
||||||
|
unset($object->restrictiononfksoc);
|
||||||
|
unset($object->retained_warranty_fk_cond_reglement);
|
||||||
|
unset($object->sendtoid);
|
||||||
|
unset($object->shipping_method_id);
|
||||||
|
unset($object->shipping_method);
|
||||||
|
unset($object->showphoto_on_popup);
|
||||||
|
unset($object->specimen);
|
||||||
|
unset($object->state_code);
|
||||||
|
unset($object->state_id);
|
||||||
|
unset($object->state);
|
||||||
|
unset($object->table_element_line);
|
||||||
|
unset($object->table_element);
|
||||||
|
unset($object->thirdparty);
|
||||||
|
unset($object->total_ht);
|
||||||
|
unset($object->total_localtax1);
|
||||||
|
unset($object->total_localtax2);
|
||||||
|
unset($object->total_ttc);
|
||||||
|
unset($object->total_tva);
|
||||||
|
unset($object->totalpaid_multicurrency);
|
||||||
|
unset($object->totalpaid);
|
||||||
|
unset($object->tpl);
|
||||||
|
unset($object->transport_mode_id);
|
||||||
|
unset($object->user);
|
||||||
|
unset($object->user_creation_id);
|
||||||
|
unset($object->user_validation_id);
|
||||||
|
unset($object->user_closing_id);
|
||||||
|
unset($object->user_modification_id);
|
||||||
|
unset($object->warehouse_id);
|
||||||
|
|
||||||
|
return $object;
|
||||||
|
}
|
||||||
|
|
||||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
|
||||||
/**
|
/**
|
||||||
@@ -666,8 +1197,6 @@ class Mailings extends DolibarrApi
|
|||||||
unset($object->import_key);
|
unset($object->import_key);
|
||||||
unset($object->isextrafieldmanaged);
|
unset($object->isextrafieldmanaged);
|
||||||
unset($object->ismultientitymanaged);
|
unset($object->ismultientitymanaged);
|
||||||
unset($object->labelStatus);
|
|
||||||
unset($object->labelStatusShort);
|
|
||||||
unset($object->last_main_doc);
|
unset($object->last_main_doc);
|
||||||
unset($object->lastname);
|
unset($object->lastname);
|
||||||
unset($object->lines);
|
unset($object->lines);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
|
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
|
||||||
|
require_once DOL_DOCUMENT_ROOT.'/comm/mailing/class/mailing_targets.class.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to manage emailings module
|
* Class to manage emailings module
|
||||||
@@ -174,6 +174,11 @@ class Mailing extends CommonObject
|
|||||||
*/
|
*/
|
||||||
public $substitutionarrayfortest;
|
public $substitutionarrayfortest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var MailingTarget[]
|
||||||
|
*/
|
||||||
|
public $targets = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var ?int The related project ID
|
* @var ?int The related project ID
|
||||||
* @see setProject(), project
|
* @see setProject(), project
|
||||||
@@ -621,7 +626,7 @@ class Mailing extends CommonObject
|
|||||||
$now = dol_now();
|
$now = dol_now();
|
||||||
|
|
||||||
$sql = "UPDATE ".MAIN_DB_PREFIX."mailing ";
|
$sql = "UPDATE ".MAIN_DB_PREFIX."mailing ";
|
||||||
$sql .= " SET statut = 0, fk_user_modif=".$user->id;
|
$sql .= " SET statut = 0, tms = '".$this->db->idate($now)."', fk_user_modif=".$user->id;
|
||||||
$sql .= " WHERE rowid = ".((int) $this->id);
|
$sql .= " WHERE rowid = ".((int) $this->id);
|
||||||
|
|
||||||
dol_syslog("Mailing::valid", LOG_DEBUG);
|
dol_syslog("Mailing::valid", LOG_DEBUG);
|
||||||
|
|||||||
505
htdocs/comm/mailing/class/mailing_targets.class.php
Normal file
505
htdocs/comm/mailing/class/mailing_targets.class.php
Normal file
@@ -0,0 +1,505 @@
|
|||||||
|
<?php
|
||||||
|
/* Copyright (C) 2025 Cloned from htdocs/comm/mailing/class/mailing.class.php then modified
|
||||||
|
* Copyright (C) 2025 Jon Bendtsen <jon.bendtsen.github@jonb.dk>
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file htdocs/comm/mailing/class/mailing_target.class.php
|
||||||
|
* \ingroup mailing
|
||||||
|
* \brief File of class to manage emailing targets module
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to manage emailings module
|
||||||
|
*/
|
||||||
|
class MailingTarget extends CommonObject
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string ID to identify managed object
|
||||||
|
*/
|
||||||
|
public $element = 'mailing_target';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Name of table without prefix where object is stored
|
||||||
|
*/
|
||||||
|
public $table_element = 'mailing_cibles';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
|
||||||
|
*/
|
||||||
|
public $picto = 'contact';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int Mailing id that this mailing_target is related to.
|
||||||
|
*/
|
||||||
|
public $fk_mailing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int Contact id that this mailing_target is related to.
|
||||||
|
*/
|
||||||
|
public $fk_contact;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string lastname of the mailing_target
|
||||||
|
*/
|
||||||
|
public $lastname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string firstname of the mailing_target
|
||||||
|
*/
|
||||||
|
public $firstname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string email of the mailing_target
|
||||||
|
*/
|
||||||
|
public $email;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string other
|
||||||
|
*/
|
||||||
|
public $other;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string tag
|
||||||
|
*/
|
||||||
|
public $tag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int status
|
||||||
|
* @deprecated Use $status
|
||||||
|
*/
|
||||||
|
public $statut; // Status 0=Not sent, 1=Sent, 2=Read, 3=Read and unsubscribed, -1=Error
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int status
|
||||||
|
*/
|
||||||
|
public $status; // Status 0=Not sent, 1=Sent, 2=Read, 3=Read and unsubscribed, -1=Error
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<int,string> statut dest
|
||||||
|
*/
|
||||||
|
public $statut_dest = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string source_url of the mailing_target
|
||||||
|
*/
|
||||||
|
public $source_url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int source_id of the mailing_target
|
||||||
|
*/
|
||||||
|
public $source_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string source_type
|
||||||
|
*/
|
||||||
|
public $source_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var integer|''|null date sending
|
||||||
|
*/
|
||||||
|
public $date_envoi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update timestamp record (tms)
|
||||||
|
* @var integer
|
||||||
|
* @deprecated Use $date_modification
|
||||||
|
*/
|
||||||
|
public $tms;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string error_text from trying to send email
|
||||||
|
*/
|
||||||
|
public $error_text;
|
||||||
|
|
||||||
|
const STATUS_NOTSENT = 0;
|
||||||
|
const STATUS_SENT = 1;
|
||||||
|
const STATUS_READ = 2;
|
||||||
|
const STATUS_READANDUNSUBSCRIBED = 3;
|
||||||
|
const STATUS_ERROR = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param DoliDB $db Database handler
|
||||||
|
*/
|
||||||
|
public function __construct($db)
|
||||||
|
{
|
||||||
|
$this->db = $db;
|
||||||
|
|
||||||
|
// List of language codes for status
|
||||||
|
$this->labelStatus[0] = 'TargetStatusNotSent';
|
||||||
|
$this->labelStatus[1] = 'TargetStatusSent';
|
||||||
|
$this->labelStatus[2] = 'TargetStatusRead';
|
||||||
|
$this->labelStatus[3] = 'TargetStatusReadAndUnsubscribed';
|
||||||
|
$this->labelStatus[-1] = 'TargetStatusError';
|
||||||
|
|
||||||
|
$this->statut_dest[0] = 'TargetStatusNotSent';
|
||||||
|
$this->statut_dest[1] = 'TargetStatusSent';
|
||||||
|
$this->statut_dest[2] = 'TargetStatusRead';
|
||||||
|
$this->statut_dest[3] = 'TargetStatusReadAndUnsubscribed'; // Read but ask to not be contacted anymore
|
||||||
|
$this->statut_dest[-1] = 'TargetStatusError';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an Mailing Target
|
||||||
|
*
|
||||||
|
* @param User $user Object of user making creation
|
||||||
|
* @return int Return integer <0 if KO, Id of created object if OK
|
||||||
|
*/
|
||||||
|
public function create($user)
|
||||||
|
{
|
||||||
|
global $conf, $langs;
|
||||||
|
|
||||||
|
if (empty($this->fk_mailing)) {
|
||||||
|
$this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Mailing"));
|
||||||
|
return -2;
|
||||||
|
// we probably should also check that this number actually exists in ".MAIN_DB_PREFIX."mailing";
|
||||||
|
}
|
||||||
|
if (0 == $this->fk_mailing) {
|
||||||
|
$this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Mailing"));
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
if (empty($this->email)) {
|
||||||
|
$this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Email"));
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
if (empty($this->statut)) {
|
||||||
|
$statut = 0;
|
||||||
|
}
|
||||||
|
if (empty($this->status)) {
|
||||||
|
$status = 0;
|
||||||
|
}
|
||||||
|
if ($this->status !== $this->statut) {
|
||||||
|
$this->error = 'Status='.$this->status.' and Statut='.$this->statut.' field must be identical';
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
if (empty($this->fk_contact)) {
|
||||||
|
$fk_contact = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$error = 0;
|
||||||
|
|
||||||
|
$this->db->begin();
|
||||||
|
|
||||||
|
|
||||||
|
// 2025-10-09 06:33:26 DEBUG 192.168.127.1 52 33 sql=INSERT INTO llx_mailing_cibles (fk_mailing, fk_contact, email, statut) VALUES ('4', .((int) 0)., 'jon@jonb.dk', .((int) )).
|
||||||
|
//2025-10-09 06:35:13 DEBUG 192.168.127.1 54 33 sql=INSERT INTO llx_mailing_cibles (fk_mailing, fk_contact, email, statut) VALUES (4, .((int) 0)., 'jon@jonb.dk', .((int) )).
|
||||||
|
|
||||||
|
$sql = "INSERT INTO ".MAIN_DB_PREFIX."mailing_cibles";
|
||||||
|
$sql .= " (fk_mailing, fk_contact, email, statut)";
|
||||||
|
$sql .= " VALUES (".((int) $this->fk_mailing).", ";
|
||||||
|
$sql .= ((int) $this->fk_contact).", ";
|
||||||
|
$sql .= "'".$this->db->escape($this->email)."', ";
|
||||||
|
$sql .= ((int) $conf->statut)." )";
|
||||||
|
|
||||||
|
dol_syslog(__METHOD__, LOG_DEBUG);
|
||||||
|
|
||||||
|
$resql = $this->db->query($sql);
|
||||||
|
if ($resql) {
|
||||||
|
$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."mailing_cibles");
|
||||||
|
|
||||||
|
$result = $this->update($user);
|
||||||
|
if ($result < 0) {
|
||||||
|
$error++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$error) {
|
||||||
|
$this->db->commit();
|
||||||
|
return $this->id;
|
||||||
|
} else {
|
||||||
|
$this->db->rollback();
|
||||||
|
dol_syslog(__METHOD__ . ' ' . $this->error, LOG_ERR);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->error = $this->db->lasterror();
|
||||||
|
$this->db->rollback();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete Mailing target
|
||||||
|
*
|
||||||
|
* @param User $user User that delete
|
||||||
|
* @return int >0 if OK, <0 if KO
|
||||||
|
*/
|
||||||
|
public function delete($user)
|
||||||
|
{
|
||||||
|
$error = 0;
|
||||||
|
|
||||||
|
$this->db->begin();
|
||||||
|
|
||||||
|
$sql = "DELETE FROM ".MAIN_DB_PREFIX."mailing_cibles";
|
||||||
|
$sql .= " WHERE rowid = " . ((int) $this->id);
|
||||||
|
|
||||||
|
dol_syslog(__METHOD__, LOG_DEBUG);
|
||||||
|
$resql = $this->db->query($sql);
|
||||||
|
if ($resql) {
|
||||||
|
dol_syslog(__METHOD__ . ' success');
|
||||||
|
$this->db->commit();
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
$this->db->rollback();
|
||||||
|
$this->error = $this->db->lasterror();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set notsent mailing target
|
||||||
|
*
|
||||||
|
* @return int Return integer <0 if KO, >0 if OK
|
||||||
|
*/
|
||||||
|
public function setNotSent()
|
||||||
|
{
|
||||||
|
$now = dol_now();
|
||||||
|
|
||||||
|
$sql = "UPDATE ".MAIN_DB_PREFIX."mailing_cibles ";
|
||||||
|
$sql .= " SET statut = ".((int) self::STATUS_NOTSENT).", tms = '".$this->db->idate($now)."'";
|
||||||
|
$sql .= " WHERE rowid = ".((int) $this->id);
|
||||||
|
|
||||||
|
dol_syslog("Mailing::valid", LOG_DEBUG);
|
||||||
|
if ($this->db->query($sql)) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
$this->error = $this->db->lasterror();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set sent mailing target
|
||||||
|
*
|
||||||
|
* @return int Return integer <0 if KO, >0 if OK
|
||||||
|
*/
|
||||||
|
public function setSent()
|
||||||
|
{
|
||||||
|
$now = dol_now();
|
||||||
|
|
||||||
|
$sql = "UPDATE ".MAIN_DB_PREFIX."mailing_cibles ";
|
||||||
|
$sql .= " SET statut = ".((int) self::STATUS_SENT).", tms = '".$this->db->idate($now)."'";
|
||||||
|
$sql .= " WHERE rowid = ".((int) $this->id);
|
||||||
|
|
||||||
|
dol_syslog("Mailing::valid", LOG_DEBUG);
|
||||||
|
if ($this->db->query($sql)) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
$this->error = $this->db->lasterror();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set read mailing target
|
||||||
|
*
|
||||||
|
* @return int Return integer <0 if KO, >0 if OK
|
||||||
|
*/
|
||||||
|
public function setRead()
|
||||||
|
{
|
||||||
|
$now = dol_now();
|
||||||
|
|
||||||
|
$sql = "UPDATE ".MAIN_DB_PREFIX."mailing_cibles ";
|
||||||
|
$sql .= " SET statut = ".((int) self::STATUS_READ).", tms = '".$this->db->idate($now)."'";
|
||||||
|
$sql .= " WHERE rowid = ".((int) $this->id);
|
||||||
|
|
||||||
|
dol_syslog("Mailing::valid", LOG_DEBUG);
|
||||||
|
if ($this->db->query($sql)) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
$this->error = $this->db->lasterror();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set read and unsubscribed mailing target
|
||||||
|
*
|
||||||
|
* @return int Return integer <0 if KO, >0 if OK
|
||||||
|
*/
|
||||||
|
public function setReadAndUnsubscribed()
|
||||||
|
{
|
||||||
|
$now = dol_now();
|
||||||
|
|
||||||
|
$sql = "UPDATE ".MAIN_DB_PREFIX."mailing_cibles ";
|
||||||
|
$sql .= " SET statut = ".((int) self::STATUS_READANDUNSUBSCRIBED).", tms = '".$this->db->idate($now)."'";
|
||||||
|
$sql .= " WHERE rowid = ".((int) $this->id);
|
||||||
|
|
||||||
|
dol_syslog("Mailing::valid", LOG_DEBUG);
|
||||||
|
if ($this->db->query($sql)) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
$this->error = $this->db->lasterror();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set error mailing target
|
||||||
|
*
|
||||||
|
* @return int Return integer <0 if KO, >0 if OK
|
||||||
|
*/
|
||||||
|
public function setError()
|
||||||
|
{
|
||||||
|
$now = dol_now();
|
||||||
|
|
||||||
|
$sql = "UPDATE ".MAIN_DB_PREFIX."mailing_cibles ";
|
||||||
|
$sql .= " SET statut = ".((int) self::STATUS_ERROR).", tms = '".$this->db->idate($now)."'";
|
||||||
|
$sql .= " WHERE rowid = ".((int) $this->id);
|
||||||
|
|
||||||
|
dol_syslog("Mailing::valid", LOG_DEBUG);
|
||||||
|
if ($this->db->query($sql)) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
$this->error = $this->db->lasterror();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update an Mailing Target
|
||||||
|
*
|
||||||
|
* @param User $user Object of user making change
|
||||||
|
* @return int Return integer < 0 if KO, > 0 if OK
|
||||||
|
*/
|
||||||
|
public function update($user)
|
||||||
|
{
|
||||||
|
global $langs;
|
||||||
|
|
||||||
|
if (empty($this->fk_mailing)) {
|
||||||
|
return -2;
|
||||||
|
// we probably should also check that this number actually exists in ".MAIN_DB_PREFIX."mailing";
|
||||||
|
}
|
||||||
|
if (empty($this->email)) {
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
if (empty($this->statut)) {
|
||||||
|
$statut = 0;
|
||||||
|
}
|
||||||
|
if (empty($this->status)) {
|
||||||
|
$status = 0;
|
||||||
|
}
|
||||||
|
if ($this->status !== $this->statut) {
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
if (empty($this->fk_contact)) {
|
||||||
|
$fk_contact = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$now = dol_now();
|
||||||
|
$error = 0;
|
||||||
|
$this->db->begin();
|
||||||
|
|
||||||
|
$sql = "UPDATE ".MAIN_DB_PREFIX."mailing_cibles";
|
||||||
|
$sql .= " SET fk_mailing = '".((int) $this->fk_mailing)."'";
|
||||||
|
$sql .= ", fk_contact = '".((int) $this->fk_contact)."'";
|
||||||
|
$sql .= ", lastname = '".$this->db->escape($this->lastname)."'";
|
||||||
|
$sql .= ", firstname = '".$this->db->escape($this->firstname)."'";
|
||||||
|
$sql .= ", email = '".$this->db->escape($this->email)."'";
|
||||||
|
$sql .= ", other = '".$this->db->escape($this->other)."'";
|
||||||
|
$sql .= ", tag = '".$this->db->escape($this->tag)."'";
|
||||||
|
$sql .= ", statut = '".((int) $this->statut)."'";
|
||||||
|
$sql .= ", source_url = '".$this->db->escape($this->source_url)."'";
|
||||||
|
$sql .= ", source_id = '".((int) $this->source_id)."'";
|
||||||
|
$sql .= ", source_type = '".$this->db->escape($this->source_type)."'";
|
||||||
|
if ($this->date_envoi) {
|
||||||
|
$sql .= ", date_envoi = '".$this->db->idate($this->date_envoi)."'";
|
||||||
|
}
|
||||||
|
$sql .= ", error_text = '".($this->error_text ? $this->db->escape($this->error_text) : null)."'";
|
||||||
|
$sql .= " WHERE rowid = ".(int) $this->id;
|
||||||
|
|
||||||
|
dol_syslog(__METHOD__, LOG_DEBUG);
|
||||||
|
$resql = $this->db->query($sql);
|
||||||
|
if ($resql) {
|
||||||
|
dol_syslog(__METHOD__ . ' success');
|
||||||
|
$this->db->commit();
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
if ($this->db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
|
||||||
|
$this->error = $langs->trans("ErrorRecordAlreadyExists", $this->email);
|
||||||
|
} else {
|
||||||
|
$this->error = $this->db->lasterror();
|
||||||
|
}
|
||||||
|
$this->db->rollback();
|
||||||
|
return -6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get object from database
|
||||||
|
*
|
||||||
|
* @param int $rowid Id of Mailing Target
|
||||||
|
* @return int Return integer <0 if KO, >0 if OK
|
||||||
|
*/
|
||||||
|
public function fetch($rowid)
|
||||||
|
{
|
||||||
|
$sql = "SELECT t.rowid";
|
||||||
|
$sql .= ", t.fk_mailing";
|
||||||
|
$sql .= ", t.fk_contact";
|
||||||
|
$sql .= ", t.lastname";
|
||||||
|
$sql .= ", t.firstname";
|
||||||
|
$sql .= ", t.email";
|
||||||
|
$sql .= ", t.other";
|
||||||
|
$sql .= ", t.tag";
|
||||||
|
$sql .= ", t.statut as status";
|
||||||
|
$sql .= ", t.source_url";
|
||||||
|
$sql .= ", t.source_id";
|
||||||
|
$sql .= ", t.source_type";
|
||||||
|
$sql .= ", t.date_envoi";
|
||||||
|
$sql .= ", t.tms as date_modification";
|
||||||
|
$sql .= ", t.error_text";
|
||||||
|
$sql .= " FROM ".MAIN_DB_PREFIX."mailing_cibles as t";
|
||||||
|
$sql .= " WHERE t.rowid = ".(int) $rowid;
|
||||||
|
|
||||||
|
dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
|
||||||
|
$result = $this->db->query($sql);
|
||||||
|
if ($result) {
|
||||||
|
if ($this->db->num_rows($result)) {
|
||||||
|
$obj = $this->db->fetch_object($result);
|
||||||
|
|
||||||
|
$this->id = $obj->rowid;
|
||||||
|
$this->fk_mailing = $obj->fk_mailing;
|
||||||
|
$this->fk_contact = $obj->fk_contact;
|
||||||
|
$this->lastname = $obj->lastname;
|
||||||
|
$this->firstname = $obj->firstname;
|
||||||
|
$this->email = $obj->email;
|
||||||
|
$this->other = $obj->other;
|
||||||
|
$this->tag = $obj->tag;
|
||||||
|
$this->statut = $obj->status; // deprecated
|
||||||
|
$this->status = $obj->status;
|
||||||
|
$this->source_url = $obj->source_url;
|
||||||
|
$this->source_id = $obj->source_id;
|
||||||
|
$this->source_type = $obj->source_type;
|
||||||
|
$this->date_envoi = $this->db->jdate($obj->date_envoi);
|
||||||
|
$this->date_modification = $this->db->jdate($obj->date_modification); // tms
|
||||||
|
$this->tms = $this->db->jdate($obj->date_modification); // tms
|
||||||
|
$this->error_text = $obj->error_text;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
dol_syslog(get_class($this)."::fetch Error -1");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dol_syslog(get_class($this)."::fetch Error -2");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
187
test/hurl/api/mailings/10_mailings.hurl
Normal file
187
test/hurl/api/mailings/10_mailings.hurl
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
# GET mass mailings
|
||||||
|
GET http://{{hostnport}}/api/index.php/mailings
|
||||||
|
HTTP 200
|
||||||
|
|
||||||
|
# GET mass sorted mailings
|
||||||
|
GET http://{{hostnport}}/api/index.php/mailings?sortfield=t.rowid&sortorder=ASC
|
||||||
|
HTTP 200
|
||||||
|
|
||||||
|
# GET mass sorted mailings
|
||||||
|
GET http://{{hostnport}}/api/index.php/mailings?sortfield=t.rowid&sortorder=ASC
|
||||||
|
HTTP 200
|
||||||
|
|
||||||
|
# GET with limit and page
|
||||||
|
GET http://{{hostnport}}/api/index.php/mailings?limit=100&page=1
|
||||||
|
HTTP 200
|
||||||
|
|
||||||
|
# GET with fk_project
|
||||||
|
GET http://{{hostnport}}/api/index.php/mailings?fk_projects=1
|
||||||
|
HTTP 200
|
||||||
|
|
||||||
|
# GET with properties=id%2Cstatus
|
||||||
|
GET http://{{hostnport}}/api/index.php/mailings?properties=id%2Cstatus
|
||||||
|
HTTP 200
|
||||||
|
|
||||||
|
# GET with pagination_data=false
|
||||||
|
GET http://{{hostnport}}/api/index.php/mailings?pagination_data=false
|
||||||
|
HTTP 200
|
||||||
|
|
||||||
|
# GET with pagination_data=true
|
||||||
|
GET http://{{hostnport}}/api/index.php/mailings?pagination_data=true
|
||||||
|
HTTP 200
|
||||||
|
[Asserts]
|
||||||
|
jsonpath "$.data" exists
|
||||||
|
jsonpath "$.pagination.total" >= 0
|
||||||
|
jsonpath "$.pagination.page" >= 0
|
||||||
|
jsonpath "$.pagination.page_count" >= 0
|
||||||
|
jsonpath "$.pagination.limit" == 100
|
||||||
|
|
||||||
|
# GET mailing with ID 0 - which should not exist
|
||||||
|
GET http://{{hostnport}}/api/index.php/mailings/0
|
||||||
|
HTTP 404
|
||||||
|
{"error":{"code":404,"message":"Not Found: Mass mailing not found, id=0"}}
|
||||||
|
|
||||||
|
# POST {}
|
||||||
|
POST http://{{hostnport}}/api/index.php/mailings
|
||||||
|
{}
|
||||||
|
HTTP 400
|
||||||
|
{"error":{"code":400,"message":"Bad Request: title field missing"}}
|
||||||
|
|
||||||
|
# DELETE
|
||||||
|
DELETE http://{{hostnport}}/api/index.php/mailings/
|
||||||
|
HTTP 405
|
||||||
|
|
||||||
|
# DELETE mailing with ID 0 - which should not exist
|
||||||
|
DELETE http://{{hostnport}}/api/index.php/mailings/0
|
||||||
|
HTTP 404
|
||||||
|
{"error":{"code":404,"message":"Not Found: Mass mailing not found, id=0"}}
|
||||||
|
|
||||||
|
# PUT
|
||||||
|
PUT http://{{hostnport}}/api/index.php/mailings/
|
||||||
|
{}
|
||||||
|
HTTP 405
|
||||||
|
|
||||||
|
# PUT
|
||||||
|
PUT http://{{hostnport}}/api/index.php/mailings/0
|
||||||
|
{}
|
||||||
|
HTTP 404
|
||||||
|
{"error":{"code":404,"message":"Not Found: Mass mailing not found, id=0"}}
|
||||||
|
|
||||||
|
DELETE http://{{hostnport}}/api/index.php/mailings//deleteTargets
|
||||||
|
HTTP 400
|
||||||
|
|
||||||
|
# DELETE targets of mailing with ID 0 - which should not exist
|
||||||
|
DELETE http://{{hostnport}}/api/index.php/mailings/0/deleteTargets
|
||||||
|
HTTP 404
|
||||||
|
{"error":{"code":404,"message":"Not Found: Mass mailing not found, id=0"}}
|
||||||
|
|
||||||
|
|
||||||
|
PUT http://{{hostnport}}/api/index.php/mailings//resetTargetsStatus
|
||||||
|
HTTP 400
|
||||||
|
|
||||||
|
# reset target status of mailing with ID 0 - which should not exist
|
||||||
|
PUT http://{{hostnport}}/api/index.php/mailings/0/resetTargetsStatus
|
||||||
|
HTTP 404
|
||||||
|
{"error":{"code":404,"message":"Not Found: Mass mailing not found, id=0"}}
|
||||||
|
|
||||||
|
|
||||||
|
PUT http://{{hostnport}}/api/index.php/mailings//settodraft
|
||||||
|
HTTP 400
|
||||||
|
|
||||||
|
# set mailing to draft with ID 0 - which should not exist
|
||||||
|
PUT http://{{hostnport}}/api/index.php/mailings/0/settodraft
|
||||||
|
HTTP 404
|
||||||
|
{"error":{"code":404,"message":"Not Found: Mass mailing not found, id=0"}}
|
||||||
|
|
||||||
|
|
||||||
|
PUT http://{{hostnport}}/api/index.php/mailings//validate
|
||||||
|
HTTP 400
|
||||||
|
|
||||||
|
# validate mailing with ID 0 - which should not exist
|
||||||
|
PUT http://{{hostnport}}/api/index.php/mailings/0/validate
|
||||||
|
HTTP 404
|
||||||
|
{"error":{"code":404,"message":"Not Found: Mass mailing not found, id=0"}}
|
||||||
|
|
||||||
|
GET http://{{hostnport}}/api/index.php/mailings/clone/
|
||||||
|
HTTP 400
|
||||||
|
|
||||||
|
GET http://{{hostnport}}/api/index.php/mailings/clone/0
|
||||||
|
HTTP 404
|
||||||
|
{"error":{"code":404,"message":"Not Found: Mass mailing to clone not found, id=0"}}
|
||||||
|
|
||||||
|
|
||||||
|
GET http://{{hostnport}}/api/index.php/mailings//targets
|
||||||
|
HTTP 400
|
||||||
|
|
||||||
|
# get targets of mailing with ID 0 - which should not exist
|
||||||
|
GET http://{{hostnport}}/api/index.php/mailings/0/targets
|
||||||
|
HTTP 404
|
||||||
|
{"error":{"code":404,"message":"Not Found: Mass mailing not found, id=0"}}
|
||||||
|
|
||||||
|
# get a target in a mailing
|
||||||
|
GET http://{{hostnport}}/api/index.php/mailings/0/getTarget/0
|
||||||
|
HTTP 404
|
||||||
|
|
||||||
|
# get a target in a mailing
|
||||||
|
PUT http://{{hostnport}}/api/index.php/mailings/0/updateTarget/0
|
||||||
|
{}
|
||||||
|
HTTP 404
|
||||||
|
|
||||||
|
# Delete a target in a mailing
|
||||||
|
DELETE http://{{hostnport}}/api/index.php/mailings/0/deleteTarget/0
|
||||||
|
{}
|
||||||
|
HTTP 404
|
||||||
|
|
||||||
|
# Create a target in a mailing
|
||||||
|
POST http://{{hostnport}}/api/index.php/mailings/0/createTarget
|
||||||
|
{}
|
||||||
|
HTTP 400
|
||||||
|
|
||||||
|
# Create a target in a mailing
|
||||||
|
POST http://{{hostnport}}/api/index.php/mailings/0/createTarget
|
||||||
|
{
|
||||||
|
"statut": "0",
|
||||||
|
"status": "0",
|
||||||
|
"lastname": "Example",
|
||||||
|
"firstname": "Bad",
|
||||||
|
"date_modification": 1759051258,
|
||||||
|
"tms": 1759051258,
|
||||||
|
"fk_mailing": "0",
|
||||||
|
"fk_contact": "0",
|
||||||
|
"email": "bad@example.com",
|
||||||
|
"other": "",
|
||||||
|
"tag": "acaa266a6b12a85a7db47a377a10333b",
|
||||||
|
"source_url": "",
|
||||||
|
"source_id": null,
|
||||||
|
"source_type": "file",
|
||||||
|
"date_envoi": "",
|
||||||
|
"error_text": null
|
||||||
|
}
|
||||||
|
HTTP 404
|
||||||
|
|
||||||
|
# Create a target in a mailing
|
||||||
|
POST http://{{hostnport}}/api/index.php/mailings/0/createTarget
|
||||||
|
{
|
||||||
|
"id": "0"
|
||||||
|
}
|
||||||
|
HTTP 400
|
||||||
|
{"error":{"code":400,"message":"Bad Request: fk_mailing field missing"}}
|
||||||
|
|
||||||
|
# Create a target in a mailing
|
||||||
|
POST http://{{hostnport}}/api/index.php/mailings/0/createTarget
|
||||||
|
{
|
||||||
|
"id": "0",
|
||||||
|
"fk_mailing" : "0"
|
||||||
|
}
|
||||||
|
HTTP 400
|
||||||
|
{"error":{"code":400,"message":"Bad Request: email field missing"}}
|
||||||
|
|
||||||
|
# Create a target in a mailing
|
||||||
|
POST http://{{hostnport}}/api/index.php/mailings/0/createTarget
|
||||||
|
{
|
||||||
|
"id": "0",
|
||||||
|
"email": "bad@example.com",
|
||||||
|
"fk_mailing" : "0"
|
||||||
|
}
|
||||||
|
HTTP 400
|
||||||
|
{"error":{"code":400,"message":"Bad Request: Creating with id field is forbidden"}}
|
||||||
@@ -17,14 +17,14 @@ if [[ "" != "${DOLISUBURL}" ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo "First we run tests that do not require authentication"
|
echo "First we run tests that do not require authentication"
|
||||||
find api/ gui/ public/ -type f -iname '00*.hurl' -exec hurl --variable "hostnport=${hostnport}" --test "{}" \;
|
find api/ gui/ public/ -type f -iname '00*.hurl' -exec hurl --variable "hostnport=${hostnport}" --test "{}" + || exit 1
|
||||||
|
|
||||||
# Now we get ready to run tests that do require authentication
|
# Now we get ready to run tests that do require authentication
|
||||||
if [[ -z ${DOLAPIKEY+x} ]]; then
|
if [[ -z ${DOLAPIKEY+x} ]]; then
|
||||||
echo "DOLAPIKEY bash variable is unset, no API tests that require authentication"
|
echo "DOLAPIKEY bash variable is unset, no API tests that require authentication"
|
||||||
else
|
else
|
||||||
echo "Now we are ready to run API tests that do require authentication"
|
echo "Now we are ready to run API tests that do require authentication"
|
||||||
find api/ -type f -iname '10*.hurl' -not -iname '00*.hurl' -exec hurl --variable "hostnport=${hostnport}" --header "${DOLAPIKEY}" --test "{}" \;
|
find api/ -type f -iname '10*.hurl' -not -iname '00*.hurl' -exec hurl --variable "hostnport=${hostnport}" --header "${DOLAPIKEY}" --test "{}" + || exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
./save_login_cookie.sh
|
./save_login_cookie.sh
|
||||||
@@ -32,5 +32,5 @@ if [[ -z ${COOKIEJAR+x} ]]; then
|
|||||||
COOKIEJAR=/tmp/cookie.jar
|
COOKIEJAR=/tmp/cookie.jar
|
||||||
fi
|
fi
|
||||||
echo "Now we are ready to run GUI tests that do require authentication"
|
echo "Now we are ready to run GUI tests that do require authentication"
|
||||||
find gui/ -type f -iname '10*.hurl' -not -iname 'save_login_cookie.hurl' -not -iname '00*.hurl' -exec hurl --variable "hostnport=${hostnport}" --cookie "${COOKIEJAR}" --test "{}" \;
|
find gui/ -type f -iname '10*.hurl' -not -iname 'save_login_cookie.hurl' -not -iname '00*.hurl' -exec hurl --variable "hostnport=${hostnport}" --cookie "${COOKIEJAR}" --test "{}" + || exit 3
|
||||||
rm -rf "${COOKIEJAR}"
|
rm -rf "${COOKIEJAR}"
|
||||||
|
|||||||
@@ -17,10 +17,12 @@ if [[ "" != "${DOLISUBURL}" ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z ${DOLIUSERNAME+x} ]]; then
|
if [[ -z ${DOLIUSERNAME+x} ]]; then
|
||||||
read -rp "Your Dolibarr Username: " DOLIUSERNAME
|
echo "To do GUI tests we need:"
|
||||||
|
read -rp " Your Dolibarr Username: " DOLIUSERNAME
|
||||||
fi
|
fi
|
||||||
if [[ -z ${DOLIPASSWORD+x} ]]; then
|
if [[ -z ${DOLIPASSWORD+x} ]]; then
|
||||||
read -rsp "Your Dolibarr Password: " DOLIPASSWORD
|
echo "To do GUI tests we need:"
|
||||||
|
read -rsp " Your Dolibarr Password: " DOLIPASSWORD
|
||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user