yes remove this part.
Thank you very much!
Now, I will put this in production!
Really appreciate your help !
]]>if(count($obj['data']) < 1){
print_r("\n\nDoesn't exist tickets to be processed to redmine\n");
exit;
}this is not correct : if no ticket $obj['data'] dosent exist !
you Don't need to count tickets : "foreach" loop do it for you and if no ticket in search, no issue will be created.
if you really want to count tickets use
$obj['count'] ( and not << count($obj['data']) >>)
So, Can I remove this or comment?
if(count($obj['data']) < 1){
print_r("\n\nDoesn't exist tickets to be processed to redmine\n");
exit;
}
I did new tests without this "if" and still working fine.
]]>this is not correct : if no ticket $obj['data'] dosent exist !
you Don't need to count tickets : "foreach" loop do it for you and if no ticket in search, no issue will be created.
if you really want to count tickets use
$obj['count'] ( and not << count($obj['data']) >>)
]]>i adviced you to set request type to "redmine" after redminsAP call so you can filter processed tickets :
-if request type=redmine there is an issue in redmine allready created
-if request type<> redmine you should create an issue in redmine..I dont understand your ticket search : you dont exclude processed tickets ( requestype=redmine).
no sure that $data_update_glpi='{
"input": {
"requesttypes_id": 10
}
}';
is correct.
I'm doing tests, creates a ticket in glpi with that category.
when the first time I run the script (considering having opened tickets with category X and with requesttype=helpdesk) I have this:
root@glpisrv:/var/tmp# php script.php
######SENT TO REDMINE ######### 161
######CHANGE THE REQUESTTYPE OF THE TICKET IN GLPI #########
[{"161":true,"message":""}]
########kill session #########
After send the task to redmine, the ticket in glpi is changed the field requesttype from "helpdesk" to "redmine".
Even if have other ticket in glpi with same category (that will be forwarded to redmine), only the remaining ticket goes to redmine.
And when i try execute the script without ticket with that category, I have this:
root@glpisrv:/var/tmp# php script.php
PHP Warning: count(): Parameter must be an array or an object that implements Countable in /var/tmp/script.php on line 46
Doesn't exist tickets to be processed to redmine
I think that's correct.
What do you think? Possibility of an error occurring at some future time?
Thanks by your reply.
]]>-if request type=redmine there is an issue in redmine allready created
-if request type<> redmine you should create an issue in redmine..
I dont understand your ticket search : you dont exclude processed tickets ( requestype=redmine).
no sure that $data_update_glpi='{
"input": {
"requesttypes_id": 10
}
}';
is correct.
LaDenrée wrote:edit : cleaner code
First need say thanks to you again by the help
first create a new requesttype called "redmine" --> done, created
create functions to call api --> I'm testing all steps before put in a function, I think will need adapt to functions.
then search for ticket to process, create redmine issue, change ticket requesttype to redmine.
I'm doing this:
//glpi consumes own API $app_token='xxxxxxxxxx'; //app-token for localhost glpi $user_token='yyyyyyyyy'; //authentication of glpi user $api_url_glpi='IP/apirest.php'; $api_url_redmine='IP/redmine-api/api.php'; //initSession for glpi-user; $url=$api_url_glpi."/initSession?Content-Type=application/json&app_token=".$app_token ."&user_token=".$user_token; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,$url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $json = curl_exec($ch); //print_r($json); curl_close ($ch); $obj = json_decode($json,true); $sess_token = $obj['session_token']; $headers = array( 'Content-Type: application/json', 'App-Token: ' .$app_token, 'Session-Token: '.$sess_token ); //doing a simple request to validate and bypass the login screen by API $url=$api_url_glpi."/apirest.php/getFullSession"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,$url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $json = curl_exec($ch); //print_r($json); curl_close ($ch); //search tickets with a specific category and different from "redmine" requesttype and description not empty $url=$api_url_glpi."/search/Ticket?criteria[0][itemtype]=Ticket&criteria[0][field]=7&criteria[0][searchtype]=equals&criteria[0][value]=117&criteria[1][link]=AND&criteria[1][field]=9&criteria[1][searchtype]=notequals&criteria[1][value]=10&expand_dropdowns=true&criteria[2][link]=OR&criteria[2][field]=21&criteria[2][searchtype]=notcontains&criteria[2][value]"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,$url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $json = curl_exec($ch); // print_r("\n\n######## SEARCH TICKETS ################" . $json); curl_close ($ch); $obj = json_decode($json,true); //var_dump($obj["data"][0]); if(count($obj['data']) < 1){ print_r("\n\nDoesn't exist tickets to be processed to redmine\n"); exit; } // FOR EVERY TICKET ... foreach($obj['data'] as $ticket){ $ticket_id = $ticket["2"]; $ticket_titulo = $ticket["1"]; $ticket_descricao = $ticket["21"]; // *********************** CREATE TICKET ON REDMINE *********************** $data_redmine = array( "id" => "7f8018df-bafc-41c3-9736-d9718c59a653", "id_chamado" => "'".$ticket_id."'", "por" => "completename from an user of glpi", "status" => "New", "titulo" => "'".$ticket_titulo."'", "descricao" => "'".$ticket_descricao."'" ); $ch = curl_init(); $url=$api_url_redmine; curl_setopt($ch, CURLOPT_URL,$url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data_redmine)); $json = curl_exec($ch); print_r("\n\n######SENT TO Redmine ######### " . $ticket_id . "\n\n"); curl_close ($ch); $obj = json_decode($json,true); // *********************** CHANGE TICKET STATUS FOR DON'T PROCESS AGAIN *********************** //input json FOR CHANGE THE requesttypes_id $data_update_glpi='{ "input": { "requesttypes_id": 10 } }'; //changes request source from "helpdesk" to "redmine" of the ticket that was sent to redmine $url=$api_url_glpi."/Ticket/".$ticket_id; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,$url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH'); curl_setopt($ch, CURLOPT_POSTFIELDS, $data_update_glpi); $json = curl_exec($ch); print_r("\n\n######CHANGE REQUEST SOURCE OF THE TICKET ######### \n" . $json); curl_close ($ch); //$obj = json_decode($json,true); } $url=$api_url_glpi."/killSession/"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,$url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $json = curl_exec($ch); print_r("\n\n########finalizar sessão #########\n\n" . $json . "\n"); curl_close ($ch);
It's working, but I cannot confirm yet if these tickets (when exists), if they're will be inserted as duplicated as you say on previous posts.
I'm beginner with php, with this code, do you think it will work well?
This script is hosted on glpi server, and I'm testing not in production yet. The test I'm doing it's: php script.php by bash on terminal
edit : cleaner code
first create a new requesttype called "redmine" --> done, created
create functions to call api --> I'm testing all steps before put in a function, I think will need adapt to functions.
then search for ticket to process, create redmine issue, change ticket requesttype to redmine.
I'm doing this:
//glpi consumes own API
$app_token='xxxxxxxxxx'; //app-token for localhost glpi
$user_token='yyyyyyyyy'; //authentication of glpi user
$api_url_glpi='IP/apirest.php';
$api_url_redmine='IP/redmine-api/api.php';
//initSession for glpi-user;
$url=$api_url_glpi."/initSession?Content-Type=application/json&app_token=".$app_token ."&user_token=".$user_token;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$json = curl_exec($ch);
//print_r($json);
curl_close ($ch);
$obj = json_decode($json,true);
$sess_token = $obj['session_token'];
$headers = array(
'Content-Type: application/json',
'App-Token: ' .$app_token,
'Session-Token: '.$sess_token
);
//doing a simple request to validate and bypass the login screen by API
$url=$api_url_glpi."/apirest.php/getFullSession";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$json = curl_exec($ch);
//print_r($json);
curl_close ($ch);
//search tickets with a specific category and different from "redmine" requesttype and description not empty
$url=$api_url_glpi."/search/Ticket?criteria[0][itemtype]=Ticket&criteria[0][field]=7&criteria[0][searchtype]=equals&criteria[0][value]=117&criteria[1][link]=AND&criteria[1][field]=9&criteria[1][searchtype]=notequals&criteria[1][value]=10&expand_dropdowns=true&criteria[2][link]=OR&criteria[2][field]=21&criteria[2][searchtype]=notcontains&criteria[2][value]";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$json = curl_exec($ch);
// print_r("\n\n######## SEARCH TICKETS ################" . $json);
curl_close ($ch);
$obj = json_decode($json,true);
//var_dump($obj["data"][0]);
if(count($obj['data']) < 1){
print_r("\n\nDoesn't exist tickets to be processed to redmine\n");
exit;
}
// FOR EVERY TICKET ...
foreach($obj['data'] as $ticket){
$ticket_id = $ticket["2"];
$ticket_titulo = $ticket["1"];
$ticket_descricao = $ticket["21"];
// *********************** CREATE TICKET ON REDMINE ***********************
$data_redmine = array(
"id" => "7f8018df-bafc-41c3-9736-d9718c59a653",
"id_chamado" => "'".$ticket_id."'",
"por" => "completename from an user of glpi",
"status" => "New",
"titulo" => "'".$ticket_titulo."'",
"descricao" => "'".$ticket_descricao."'"
);
$ch = curl_init();
$url=$api_url_redmine;
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data_redmine));
$json = curl_exec($ch);
print_r("\n\n######SENT TO Redmine ######### " . $ticket_id . "\n\n");
curl_close ($ch);
$obj = json_decode($json,true);
// *********************** CHANGE TICKET STATUS FOR DON'T PROCESS AGAIN ***********************
//input json FOR CHANGE THE requesttypes_id
$data_update_glpi='{
"input": {
"requesttypes_id": 10
}
}';
//changes request source from "helpdesk" to "redmine" of the ticket that was sent to redmine
$url=$api_url_glpi."/Ticket/".$ticket_id;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_update_glpi);
$json = curl_exec($ch);
print_r("\n\n######CHANGE REQUEST SOURCE OF THE TICKET ######### \n" . $json);
curl_close ($ch);
//$obj = json_decode($json,true);
}
$url=$api_url_glpi."/killSession/";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$json = curl_exec($ch);
print_r("\n\n########finalizar sessão #########\n\n" . $json . "\n");
curl_close ($ch);
It's working, but I cannot confirm yet if these tickets (when exists), if they're will be inserted as duplicated as you say on previous posts.
I'm beginner with php, with this code, do you think it will work well?
]]>first create a new requesttype called "redmine"
create functions to call api
function glpi_get($itemtype){
$url=$_SESSION['api_url'] .$itemtype;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $_SESSION['headers']);
$json = curl_exec($ch);
//print_r($json);
curl_close ($ch);
$obj = json_decode($json,true);
return $obj;
}
function glpi_post($itemtype,$fields){
$url=$_SESSION['api_url'] .$itemtype;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $_SESSION['headers']);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
$json = curl_exec($ch);
//print_r($json);
curl_close ($ch);
$obj = json_decode($json,true);
return $obj;
}
function glpi_put($itemtype,$fields){
$url=$_SESSION['api_url'] .$itemtype;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $_SESSION['headers']);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
$json = curl_exec($ch);
//print_r($json);
curl_close ($ch);
$obj = json_decode($json,true);
return $obj;
}
then search for ticket to process, create redmine issue, change ticket requesttype to redmine.
//setting variables;
$_SESSION['headers']=$headers;
$_SESSION['api_url']="localhost/glpi/apirest.php";
//id corresponding to Mycat
$categories_id=26;
// id corresponding to redmine : requestype changed to redmine means issue created in redmine.
$requesttypes_id=8;
//searching for not closed tickets, with no issue in redmnie and category=Mycat
$url="/search/Ticket?ticket.php?is_deleted=0&as_map=0
&criteria[0][link]=AND&criteria[0][field]=12&criteria[0][searchtype]=equals&criteria[0][value]=notold
&criteria[1][link]=AND&criteria[1][field]=7&criteria[1][searchtype]=equals&criteria[1][value]='.$categories_id.'
&criteria[2][link]=AND&criteria[2][field]=9&criteria[2][searchtype]=notequals&criteria[2][value]=".$requesttypes_id;
$obj=glpi_get($url);
//print_r($obj);
foreach($obj['data'] as $ticket){
$ticketid=$ticket["2"];
$obj=glpi_get( "/Ticket/".$ticketid."/");
//print_r($obj);
$name=$obj["name"];
$content=strip_tags($obj["content"]);
// insert some code to call redmine API here//
echo "*******<br/>";
echo "call redmine API to create issue with ".$name." and ".$content ."<br/>";
$input='{"input":{"id": '.$ticketid.',"requesttypes_id": "'.$requesttypes_id.'"}}';
$url="/ticket/".$ticketid."/";
$obj=glpi_put($url,$input);
//print_r($obj);
}
to search by category :
http://myIP/apirest.php/search/Ticket?criteria[0][link]=AND&criteria[0][field]=7&criteria[0][searchtype]=contains&criteria[0][value]=^mycat$
In GUI GLPI i make my search and returned 5 results, that's correct.
By API, I'm using that URL like you say and I obtained this:
{
"totalcount": 5,
"count": 5,
"sort": 1,
"order": "ASC",
"data": [
{
"2": 2415,
"1": "title",
"12": 6,
"15": "2020-01-09 08:56:47",
"18": null,
"3": 3,
"14": 2,
"7": "Category",
"83": "City",
"25": null,
"22": 2999130155,
"4": 3282,
"5": 1408,
"8": [
"N1 - Help Desk",
"Desenvolvimento"
],
"19": "2020-01-09 09:44:41",
"13": null
},
{
"2": 313,
"1": "title",
"12": 6,
"15": "2019-12-04 10:08:34",
"18": null,
"3": 3,
"14": 2,
"7": "category",
"83": "location",
"25": "<p>Inclusão de usuário e grupo.</p>",
"22": 2742259139,
"4": 1389,
"5": 1408,
"8": [
"N1 - Help Desk",
"Desenvolvimento"
],
"19": "2019-12-18 10:58:08",
"13": null
},
{
"2": 1980,
"1": "title",
"12": 6,
"15": "2020-01-02 14:53:56",
"18": null,
"3": 3,
"14": 2,
"7": "category",
"83": "location",
"25": null,
"22": 81857497104,
"4": 3282,
"5": 1408,
"8": [
"N1 - Help Desk",
"Desenvolvimento"
],
"19": "2020-01-07 16:00:39",
"13": null
},
{
"2": 2603,
"1": "title",
"12": 6,
"15": "2020-01-13 12:34:04",
"18": null,
"3": 3,
"14": 2,
"7": "category",
"83": "location",
"25": null,
"22": 2999130155,
"4": 3282,
"5": 1408,
"8": [
"N1 - Help Desk",
"Desenvolvimento"
],
"19": "2020-01-16 15:04:35",
"13": null
},
{
"2": 707,
"1": "title",
"12": 6,
"15": "2019-12-10 08:37:13",
"18": null,
"3": 3,
"14": 2,
"7": "category",
"83": "location",
"25": "<p>Inclusão de usuário e grupo.</p>",
"22": 2742259139,
"4": 3314,
"5": 1408,
"8": [
"N1 - Help Desk",
"Desenvolvimento"
],
"19": "2019-12-18 10:59:16",
"13": null
}
],
"content-range": "0-4/5"
}
I think it's correct, but how I can pass through
"1 - get these tickets and call redmine api. //now I have the tickets returned by API, but how store it?
2 - flag these tickets (or store max ticket id) //do I need remember those ID's?
3 - add a line in crontab that launch this script every hour. //already have it for other tasks running all time
...what is a bit tricky is how not to create duplicate redmine issue.
i think i would write last ticket ID in a text file ( or in DB) and search for tickets with id>last ID. //what table can I save it ?
and increase last ID each time i run script." //need do some code to do that?
]]>I dont Believe you can trigger script with business ticket rules.
what i would do :
write a php script that
search for tickets with category X and applicant Y ( use glpi API)
get these tickets and call redmine api.
flag these tickets (or store max ticket id)
add a line in crontab that launch this script every hour.
what is a bit tricky is how not to create duplicate redmine issue.
i think i would write last ticket ID in a text file ( or in DB) and search for tickets with id>last ID.
and increase last ID each time i run script.
I understand, but only some tickets needs to be forwarded to redmine, not all.
I have no idea how do to that with webservices or native API from GLPI and Redmine.
]]>Is there a way to do this integration using webservices?
]]>http://myIP/apirest.php/search/Ticket?criteria[0][field]=2&criteria[0][searchtype]=contains&criteria[0][value]="288"&forcedisplay[0]=2
to search by source : (by label)
http://myIP/apirest.php/search/Ticket?criteria[0][link]=AND&criteria[0][field]=9&criteria[0][searchtype]=contains&criteria[0][value]=^mysource$
to search by category :
http://myIP/apirest.php/search/Ticket?criteria[0][link]=AND&criteria[0][field]=7&criteria[0][searchtype]=contains&criteria[0][value]=^mycat$
to search by category and by source
http://myIP/apirest.php/search/Ticket?is_deleted=0&as_map=0&criteria[0][link]=AND&criteria[0][field]=7&criteria[0][searchtype]=contains&criteria[0][value]=^mycat$
&criteria[1][link]=AND&criteria[1][field]=9&criteria[1][searchtype]=contains&criteria[1][value]=^mysource$:
if you know cat_id and source_id
to search by category and by source
http://myIP/apirest.php/search/Ticket?is_deleted=0&as_map=0&criteria[0][link]=AND&criteria[0][field]=7&criteria[0][searchtype]=equals&criteria[0][value]=cat_ID&criteria[1][link]=AND&criteria[1][field]=9&criteria[1][searchtype]=equals&criteria[1][value]=SourceID
]]>I'm trying to do a search by ticket_id
Like that http://myIP/apirest.php/search/Ticket?criteria[0][field]=1&criteria[0][searchtype]=contains&criteria[0][value]="288"&forcedisplay[0]=2
Return status 200 but no content
Have this response --> {
"totalcount": 0,
"count": 0,
"sort": 1,
"order": "ASC",
"content-range": "0--1/0"
}