1<?php 2/** 3 * DokuWiki Plugin asana (Action Component) 4 * 5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6 * @author pierre Viloutreix <pierre@elonet.fr> 7 */ 8 9include "asana_fcts.php"; 10include "../../../../inc/plugins.php"; 11include "../../remote.php"; 12//include "/usr/share/dokuwiki/inc/plugin.php"; 13//include "/usr/share/dokuwiki/lib/plugins/remote.php"; 14 15// must be run within Dokuwiki 16if (!defined('DOKU_INC')) die(); 17 18class remote_plugin_asana_APILink extends DokuWiki_Remote_Plugin { 19 20 //url de l'API d'Asana, on la garni en fonction de la requete 21 var $url_base = "https://app.asana.com/api/1.0"; 22 23 24 var $api_key = ""; 25 26 //initialisation de l'objet de requete utilisant curl 27 var $ch; 28 29 //workspace par default 30 var $workspace = ""; 31 32 //text to render 33 var $text = ""; 34 35 var $workspaces = array(); 36 37 var $projects = array(); 38 39 var $assignees = array(); 40 41 var $tags = array(); 42 43 var $workspace_filter = array(); 44 45 46 var $assignees_filter= array(); 47 48 49 var $tags_filter= array(); 50 51 52 var $projects_filter = array(); 53 54 var $strings_filter = array(); 55 56 /** 57 * Construct curl object to collecte Asana's intelligences 58 * Api from this user in prameter 59 **/ 60 public function __construct(){ 61 //echo "Initialisation de l'objet CURL\n"; 62 $this->ch= curl_init(); 63 //obtenir la réponse comme un return 64 curl_setopt($this->ch, CURLOPT_RETURNTRANSFER , true); 65 //définie le header de la requete 66 curl_setopt($this->ch, CURLOPT_HTTPHEADER , array('Content-type: application/json')); 67 //définie option ssl 68 curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER , FALSE); 69 70 71 } 72 73 public function __destruct(){ 74 curl_close($this->ch); 75 } 76 77 78 /** 79 * Register RPC methods and their arguments 80 */ 81 public function _getMethods() { 82 return array( 83 84 'plugin.asana.connecte' => array( 85 'args' => array('string'), 86 'return' => 'string', 87 'doc' => "Connecte un user à son compte Asana via sa clé API" 88 ), 89 'plugin.asana.render_user' => array( 90 'args' => array('string'), 91 'return' => 'string', 92 'doc' => "Donne le rendu des taches Asana d'un user sous forme d'un tableau" 93 ) 94 ); 95 } 96 97 98 /** 99 * Connection à l\'api via la demande de clé api pour le site Asana 100 **/ 101 function connect(){ 102 $api_key_user = $this->getConf('api_key'); 103 //echo "Définition de la clé API\n"; 104 if( $api_key_user != "Asana's API key"){ 105 $this->api_key = $api_key_user; 106 } 107 else { 108 return "<p> Vous devez spécifier une clé API d'Asana depuis le menu de configuration du plugin Asana.</p>"; 109 } 110 //définie l'utilisateur et mdp ( ici pas de mdp) 111 curl_setopt($this->ch, CURLOPT_USERPWD , $this->api_key . ":"); 112 113 114 $this->workspaces = $this->workspaces(); 115 116 //ici on ira cherché le workspace contenu dans la partie conf 117 foreach( $this->workspaces as $work_key => $work_value ){ 118 if( $work_key == $this->getConf('workspace')){ 119 $this->workspace_filter['name']= $work_key; 120 $this->workspace_filter['id']=$work_value; 121 } 122 } 123 124 if(!empty($this->workspace_filter)){ 125 $this->projects = $this->workspace_projects($this->workspace_filter['id']); 126 $this->assignees = $this->workspace_users($this->workspace_filter['id']); 127 $this->tags = $this->workspace_tags($this->workspace_filter['id']); 128 } 129 return ""; 130 } 131 132 /* 133 /** 134 * render le tableau contenant les infromations sur les taches 135 * le format du render text est surrement à modifier 136 137 **/ 138 function render_user(){ 139 if(empty($this->workspace_filter)){ 140 return "<p>Vous devez spécifier un nom de workspace. Soit dans la configuration du plugin. Soit dans la syntaxe.</p>"; 141 } 142 else{ 143 $text = "<div>"; 144 $text = $text . "<h1> Tâches Asana ( Asana's Tasks ) </h1><br/>"; 145 $text = $text . "<h2>". $this->workspace_filter['name'] . "</h2><br/>"; 146 $text = $text . "<table>".$this->render_workspaces($this->workspace_filter['id'])."</table>"; 147 $text = $text . "<br/><br/>"; 148 return $text."</div>"; 149 } 150 } 151 152 /** 153 * render un worspace, c'est à dire créé un tableau 154 * met dans text les données structurant le tableau 155 **/ 156 157 function render_workspaces($workspace){; 158 $text = "<tr><td>Project</td><td> Task Name</td><td> Assignee </td><td> Due date </td><td> Comments/Tags </td></tr>"; 159 $tasks = array(); 160 if( empty($this->assignees_filter)){ 161 if(empty($this->projects_filter)){ 162 //non assignee non project 163 $this->projects = $this->workspace_projects($workspace); 164 foreach( $this->projects as $project_key => $project_value ){ 165 $tasks_current = $this->project_tasks($project_value); 166 foreach($tasks_current as $task_key => $task_value){ 167 $task_value['project']=$project_key; 168 $tasks_current[$task_key]=$task_value; 169 } 170 $tasks = array_merge($tasks,$tasks_current); 171 172 } 173 } 174 else{ 175 //non assignee project 176 foreach( $this->projects_filter as $project_key => $project_value){ 177 $tasks_current = $this->project_tasks($project_value); 178 foreach($tasks_current as $task_key => $task_value){ 179 $task_value['project']=$project_key; 180 $tasks_current[$task_key]=$task_value; 181 } 182 $tasks = array_merge($tasks,$tasks_current); 183 } 184 } 185 } 186 else{ 187 if(empty($this->projects_filter)){ 188 //assignee non project 189 foreach( $this->assignees_filter as $assignee){ 190 foreach( $this->projects as $project_key => $project_value ){ 191 $tasks_current = $this->project_tasks_assignee($project_value, $assignee); 192 foreach($tasks_current as $task_key => $task_value){ 193 $task_value['project']=$project_key; 194 $tasks_current[$task_key]=$task_value; 195 } 196 $tasks = array_merge($tasks,$tasks_current); 197 } 198 } 199 } 200 else{ 201 //assignee project 202 foreach( $this->projects_filter as $project_key => $project_value){ 203 foreach( $this->assignees_filter as $assignee){ 204 $tasks_current = $this->project_tasks_assignee($project_value,$assignee); 205 //var_dump($tasks_current); 206 foreach($tasks_current as $task_key => $task_value){ 207 $task_value['project']=$project_key; 208 $tasks_current[$task_key]=$task_value; 209 } 210 211 $tasks = array_merge($tasks,$tasks_current); 212 } 213 } 214 } 215 } 216 if( !empty($this->tags_filter)){ 217 foreach($this->tags_filter as $tag_key => $tag_value){ 218 $tasks = $this->tag_filter($tag_key,$tasks); 219 } 220 } 221 222 if( !empty($this->strings_filter)){ 223 foreach($this->strings_filter as $string){ 224 $tasks = $this->string_filter($string, $tasks); 225 } 226 } 227 228 $tasks = $this->due_date_sort($tasks); 229 foreach( $tasks as $task){ 230 $text .= "<tr><td> ".$task['project'] . " </td><td> " . "<a href='https://app.asana.com/0/".$this->project_find($this->projects_filters,$task['project'])."/".$task['id']."' target='_blank'>".$task['name'] ."</a>". " </td><td> " .$task['assignee']['name'] . " </td><td> " . $task['due_date'] . " </td><td> " . $this->comment_head($task['id'],$this->render_comments($task['id']).$this->render_tags($task['tags']))." </td></tr>"; 231 } 232 return $text; 233 } 234 235 236 237 238 /* 239 * donne le code html pour afficher les commentaires de chaque tâches 240 * on affiche une fenêtre modale contenant les commentaires sous forme de liste 241 **/ 242 function comment_head($div_id,$text){ 243 return "<html> 244 <style> 245 #comment".$div_id."{ 246 display: none; 247 position: fixed; 248 top:0; 249 right:0; 250 bottom:0; 251 left:0; 252 background-color: rgba(0, 0, 0, 0.5); 253 z-index: 1000; 254 } 255 #comment".$div_id.":target{ 256 display: block; 257 } 258 #comment".$div_id." a{ 259 font-weight: bold; 260 padding: 10px 25px; 261 background-color: white; 262 position: absolute; 263 top: 25%; 264 left: 50px; 265 } 266 </style> 267 <div id='comment".$div_id."'> 268 <a href='#noWhere' ><p>Fermer les commentaires</p>".$text."</a> 269 </div> 270 <p><a href='#comment".$div_id."'>Afficher le masque</a></p> 271 </html>"; 272 273 } 274 275 276 277 /* render des commentaires d'une tache 278 * liste des textes des commentaires 279 **/ 280 281 function render_comments($task){ 282 $text = "<h2>Comments :</h2>"; 283 $text .= "<ul>"; 284 foreach( $this->task_comments($task) as $comment_key => $comment_value){ 285 $text = $text . "<li>" . $comment_key . "</li>"; 286 } 287 288 return $text."</ul>"; 289 } 290 291 292 /** 293 * render des tags 294 * liste des noms de tags 295 **/ 296 297 function render_tags($tags){ 298 $text = "<h2>Tags :</h2>"; 299 $text .= "<ul>"; 300 foreach( $tags as $tag){ 301 $text = $text . "<li>" . $tag['name'] . "</li>"; 302 } 303 return $text."</ul>"; 304 } 305 306 307 function addProjectFilter($project_target_name){ 308 foreach($this->projects as $project_key => $project_value){ 309 if($project_key==$project_target_name){ 310 $this->projects_filter[$project_key]=$project_value; 311 return 1; 312 } 313 } 314 return 0; 315 } 316 317 function addAssigneeFilter($assignee_target_name){ 318 foreach($this->assignees as $assignee_key => $assignee_value){ 319 if($assignee_key==$assignee_target_name){ 320 $this->assignees_filter[$assignee_key]=$assignee_value; 321 return 1; 322 } 323 } 324 return 0; 325 } 326 327 function addTagFilter($tag_target_name){ 328 foreach($this->tags as $tag_key => $tag_value){ 329 if($tag_key==$tag_target_name){ 330 $this->tags_filter[$tag_key]=$tag_value; 331 return 1; 332 } 333 } 334 return 0; 335 } 336 337 function addStringFilter($string_filter){ 338 $this->strings_filter[]= $string_filter; 339 } 340 341 function changeWorkspace($workspace_target_name){ 342 foreach($this->workspaces as $work_key => $work_value){ 343 if( $work_key == $workspace_target_name){ 344 $this->workspace_filter = array( 'name' => $work_key , 'id' => $work_value ); 345 $this->projects = $this->workspace_projects($this->workspace_filter['id']); 346 $this->assignees = $this->workspace_users($this->workspace_filter['id']); 347 $this->tags = $this->workspace_tags($this->workspace_filter['id']); 348 return 1; 349 } 350 } 351 return 0; 352 } 353 354 //donne la liste des workspace de l'utilisateur courant 355 function workspaces(){ 356 curl_setopt($this->ch, CURLOPT_URL , $this->url_base."/users/me"); 357 $data_rep = json_decode(curl_exec($this->ch),true); 358 //var_dump($data_rep); 359 $workspaces = array(); 360 foreach($data_rep['data']['workspaces'] as $workspace){ 361 $workspaces[$workspace['name']]=$workspace['id']; 362 } 363 return $workspaces; 364 } 365 366 // donne la liste des utilisateur du workspace spécifié 367 // retourne la liste sous forme clé : nom, valeur : id 368 function workspace_users($workspace_ID){ 369 curl_setopt($this->ch, CURLOPT_URL , $this->url_base."/workspaces/".$workspace_ID."/users"); 370 $data_rep = json_decode(curl_exec($this->ch),true); 371 $users = array(); 372 foreach($data_rep['data'] as $nom){ 373 $users[$nom['name']]=$nom['id']; 374 } 375 return $users; 376 } 377 378 //donne les projets d'un workspace donné 379 function workspace_projects($workspace_ID){ 380 curl_setopt($this->ch, CURLOPT_URL , $this->url_base."/workspaces/".$workspace_ID."/projects"); 381 $data_rep = json_decode(curl_exec($this->ch),true); 382 //var_dump($data_rep); 383 $projects = array(); 384 foreach($data_rep['data'] as $project){ 385 $projects[$project['name']]=$project['id']; 386 } 387 388 return $projects; 389 } 390 391 function workspace_tags($workspace_ID){ 392 curl_setopt($this->ch, CURLOPT_URL , $this->url_base."/workspaces/".$workspace_ID."/tags"); 393 $data_rep = json_decode(curl_exec($this->ch),true); 394 //var_dump($data_rep); 395 $tags = array(); 396 foreach($data_rep['data'] as $tag){ 397 $tags[$tag['name']]=$tag['id']; 398 } 399 return $tags; 400 } 401 402 //donne les tache d'un project selon un assignee 403 function project_tasks_assignee($project_ID,$assignee_id){ 404 $data_rep = $this->project_tasks($project_ID); 405 $tasks = array(); 406 foreach($data_rep as $task){ 407 if( $task['assignee']['id'] == $assignee_id ){ 408 $tasks[]=$task; 409 } 410 } 411 412 return $tasks; 413 } 414 415 416 //donne les tache d'un projet donné 417 function project_tasks($project_ID){ 418 curl_setopt($this->ch, CURLOPT_URL , $this->url_base."/projects/".$project_ID."/tasks"); 419 $data_rep = json_decode(curl_exec($this->ch),true); 420 //var_dump($data_rep); 421 $tasks = array(); 422 foreach($data_rep['data'] as $task){ 423 $tasks[]=$this->task($task['id']); 424 } 425 return $tasks; 426 } 427 428 //donne les détails d'un tache donné 429 function task($task_ID){ 430 curl_setopt($this->ch, CURLOPT_URL , $this->url_base."/tasks/".$task_ID); 431 $data_rep = json_decode(curl_exec($this->ch),true); 432 //var_dump($data_rep); 433 $task = array(); 434 $task_elt = $data_rep['data']; 435 $task=array( 'id' => $task_elt['id'] , 'name' =>$task_elt['name'], 'tags' => $task_elt['tags'], 'due_date' => $task_elt['due_on'], 'assignee' => $task_elt['assignee'], 'desc' => $task_elt['notes']); 436 return $task; 437 } 438 439 440 //donne les commentaires d'une tache 441 function task_comments($task_ID){ 442 curl_setopt($this->ch, CURLOPT_URL, $this->url_base."/tasks/".$task_ID."/stories"); 443 $data_rep = json_decode(curl_exec($this->ch),true); 444 $comments = array(); 445 foreach( $data_rep['data'] as $storie){ 446 if($storie['type'] == 'comment'){ 447 $comments[$storie['text']] = $storie['id']; 448 } 449 } 450 return $comments; 451 } 452 453 //fonction de comparaison de deux date dans un tableau de taches 454 static function compare_date($task1, $task2){ 455 date_default_timezone_set("UTC"); 456 457 if( $task1['due_date'] == "" ){ 458 //si la date 1 n'existe pas 459 if( $task2['due_date'] == "" ){ 460 //si la date 2 n'existe pas 461 return 0; 462 } 463 else{ 464 //si la date 2 existe 465 return 1; 466 } 467 } 468 else{ 469 //si la date 1 existe 470 if( $task2['due_date'] == "" ){ 471 //si la date 2 n'existe pas 472 return -1; 473 } 474 else{ 475 // les deux dates existent donc on les comparent vraiment 476 $date1 = strtotime($task1['due_date']); 477 $date2 = strtotime($task2['due_date']); 478 if( $date1<$date2){ 479 return -1; 480 } 481 elseif( $date1 == $date2){ 482 return 0; 483 } 484 else{ 485 return 1; 486 } 487 } 488 } 489 } 490 491 // trie un tableau de taches par leur deadline 492 function due_date_sort($tasks){ 493 uasort($tasks,array('remote_plugin_asana_APILink','compare_date')); 494 return $tasks; 495 } 496 497 //permet de trouver l'id du projet dans le workspace selon le nom du projet 498 function project_find($projects,$project_target_name){ 499 foreach( $projects as $project_name => $project_id ){ 500 if( $project_name == $project_target_name){ 501 return $project_id; 502 } 503 } 504 return 0; 505 } 506 507 function string_filter($string, $tasks){ 508 $tasks_cp = array(); 509 while( count($tasks) !=0 ){ 510 $task = array_shift($tasks); 511 if(strstr($task['name'],$string) or strstr($task['desc'],$string)){ 512 $tasks_cp[] = $task; 513 } 514 } 515 return $tasks_cp; 516 } 517 518 //filtre un tableau de tache selon un tag 519 function tag_filter($tag_name, $tasks){ 520 $tasks_cp = array(); 521 while( count($tasks) !=0 ){ 522 $task = array_shift($tasks); 523 if($this->tags_compare($tag_name,$task) == 1){ 524 $tasks_cp[] = $task; 525 } 526 } 527 return $tasks_cp; 528 } 529 530 //compare le tag d'une tache à un nom de tag 531 function tags_compare($tag_name,$task){ 532 foreach( $task['tags'] as $tag ){ 533 if( $tag['name'] == $tag_name ){ 534 return 1; 535 } 536 } 537 return 0; 538 } 539 540} 541 542 543