Ctrl K
ComunidadGuías…

api.php

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
<?php
if(empty($_REQUEST['api'])) {
  http_response_code(400);
  exit();
}
$scon = new mysqli('localhost', 'telloruser', 'tellorpasswd', 'tellordb');
$scon->set_charset('utf8mb4');
header("content-type: application/json");
header("cache-control: no-store");

switch ($_REQUEST['api']) {
  case 'getBoards': getBoards(); break;
  case 'getBoard': getBoard(); break;
  case 'newBoard': newBoard(); break;
  case 'editBoard': editBoard(); break;
  case 'addList': addList(); break;
  case 'renameList': renameList(); break;
  case 'moveList': moveList(); break;
  case 'newCard': newCard(); break;
  case 'addTag': addTag(); break;
  case 'getCard': getCard(); break;
  case 'saveCard': saveCard(); break;
  case 'moveCard': moveCard(); break;
  case 'deleteList': deleteList(); break;
  case 'delTag': delTag(); break;
  case 'cardColor': cardColor(); break;
  case 'archiveCard': archiveCard(); break;
  case 'deleteBoard': deleteBoard(); break;
  case 'export': export(); break;
  case 'import': import(); break;
  default: http_response_code(400);
}
$scon->close();


function getBoards() { //Get Boards
  global $scon;
  $res = $scon->query('SELECT * FROM boards');
  if(!empty($res) && mysqli_num_rows($res) > 0) {
    $rows = mysqli_fetch_all($res, MYSQLI_ASSOC);
    echo json_encode($rows);
  }
  else echo '[]';
}


function getCard() { //Get Card
  global $scon;
  $res = $scon->query('SELECT date_format(cdate,"%e %b %Y") AS cdate,date_format(mdate,"%e %b %Y") AS mdate,description FROM cards WHERE board="'.$_REQUEST['bid'].'" AND list="'.$_REQUEST['listid'].'" AND id="'.$_REQUEST['cardid'].'" LIMIT 1');
  if(!empty($res) && mysqli_num_rows($res) === 1) {
    $row = mysqli_fetch_assoc($res);
    echo json_encode($row);
  }
  else http_response_code(404);
}


function getBoard() { //Get Board (lists + cards)
  global $scon;
  $res = $scon->query('SELECT 1 FROM boards WHERE id="'.$_REQUEST['bid'].'"');
  if(!$res || !mysqli_num_rows($res)) {
    http_response_code(404);
    return;
  }
  $resL = $scon->query('SELECT id,ordr,name,0 as "start",0 as "end" FROM lists WHERE board="'.$_REQUEST['bid'].'" ORDER BY ordr asc');
  $resC = $scon->query('SELECT list,id,parent,title,tags,color,IF(description IS NULL,null,1) AS description FROM cards WHERE board="'.$_REQUEST['bid'].'"');
  $rowsL = mysqli_fetch_all($resL, MYSQLI_ASSOC);
  $rowsC = mysqli_fetch_all($resC, MYSQLI_ASSOC);
  $res = new stdClass();
  $res->lists = $rowsL;
  $res->cards = $rowsC;
  echo json_encode($res);
}


function newBoard() { //New Board
  global $scon;
  $bid = idGen32();
  $bgimg = $_REQUEST['imgurl'] ?: null;

  $sq = $scon->prepare('INSERT INTO boards(id,name,bgimg) VALUES(?,?,?)');
  $sq->bind_param('sss', $bid, $_REQUEST['name'], $bgimg);
  $sq->execute();
  $sq->close();

  if($sq) echo $bid;
  else http_response_code(500);
}


function editBoard() { //Edit Board
  global $scon;
  $name = $_REQUEST['name'];

  $sq = $scon->prepare('UPDATE boards SET name=?,bgimg=? WHERE id=?');
  $sq->bind_param('sss', $name, $_REQUEST['imgurl'], $_REQUEST['bid']);
  $sq->execute();
  $sq->close();

  if(!$sq) http_response_code(500);
}


function addList() { //Add List
  global $scon;
  $lid = idGen32();
  //idempotency check
  $res = $scon->query('SELECT 1 FROM lists WHERE board="'.$_REQUEST['bid'].'" AND ordr >= '.$_REQUEST['pos'].' LIMIT 1');
  if(mysqli_num_rows($res) !== 0) {http_response_code(409); return;}

  $sq = $scon->prepare('INSERT INTO lists(board,id,ordr,name) VALUES("'.$_REQUEST['bid'].'","'.$lid.'",'.$_REQUEST['pos'].',?)');
  $sq->bind_param('s', $_REQUEST['name']);
  $sq->execute();
  $sq->close();

  if($sq) echo $lid;
  else http_response_code(500);
}


function renameList() { //Rename List
  global $scon;
  $sq = $scon->prepare('UPDATE lists SET name=? WHERE board="'.$_REQUEST['bid'].'" AND id="'.$_REQUEST['listid'].'" LIMIT 1');
  $sq->bind_param('s', $_REQUEST['title']);
  $sq->execute();
  $sq->close();

  if(!$sq) http_response_code(500);
}


function moveList() { //Move List
  global $scon;
  //idempotency check
  $res = $scon->query('SELECT 1 FROM lists WHERE board="'.$_REQUEST['bid'].'" AND id="'.$_REQUEST['lid1'].'" AND ordr='.$_REQUEST['ordr1'].' LIMIT 1');
  if(mysqli_num_rows($res) !== 1) {http_response_code(409); return;}
  $res = $scon->query('SELECT 1 FROM lists WHERE board="'.$_REQUEST['bid'].'" AND id="'.$_REQUEST['lid2'].'" AND ordr='.$_REQUEST['ordr2'].' LIMIT 1');
  if(mysqli_num_rows($res) !== 1) {http_response_code(409); return;}

  $res = $scon->query('UPDATE lists SET ordr="'.$_REQUEST['ordr2'].'" WHERE board="'.$_REQUEST['bid'].'" AND id="'.$_REQUEST['lid1'].'" LIMIT 1');
  $res = $scon->query('UPDATE lists SET ordr="'.$_REQUEST['ordr1'].'" WHERE board="'.$_REQUEST['bid'].'" AND id="'.$_REQUEST['lid2'].'" LIMIT 1');
  if(!$res)
    http_response_code(500);
}


function newCard() { //Add Card
  global $scon;
  $cardid = idGen32();
  //idempotency check
  if($_REQUEST['pid'] === '0') { //only card in list
    $res = $scon->query('SELECT 1 FROM lists WHERE board="'.$_REQUEST['bid'].'" AND id="'.$_REQUEST['listid'].'" LIMIT 1');
    if(mysqli_num_rows($res) !== 1) {http_response_code(409); return;}
    $res = $scon->query('SELECT 1 FROM cards WHERE board="'.$_REQUEST['bid'].'" AND list="'.$_REQUEST['listid'].'" LIMIT 1');
    if(mysqli_num_rows($res) !== 0) {http_response_code(409); return;}
  }
  else { 
    $res = $scon->query('SELECT 1 FROM cards WHERE board="'.$_REQUEST['bid'].'" AND list="'.$_REQUEST['listid'].'" AND id="'.$_REQUEST['pid'].'" LIMIT 1');
    if(mysqli_num_rows($res) !== 1) {http_response_code(409); return;}
    $res = $scon->query('SELECT 1 FROM cards WHERE board="'.$_REQUEST['bid'].'" AND list="'.$_REQUEST['listid'].'" AND parent="'.$_REQUEST['pid'].'" LIMIT 1');
    if(mysqli_num_rows($res) !== 0) {http_response_code(409); return;}
  }
  $res = $scon->query('INSERT INTO cards(board,list,id,parent,title,tags,description) VALUES("'.$_REQUEST['bid'].'","'.$_REQUEST['listid'].'","'.$cardid.'","'.$_REQUEST['pid'].'","'.$_REQUEST['title'].'",null,null)');
  if($res) echo $cardid;
  else http_response_code(500);
}


function addTag() { //Add Tag
  global $scon;
  $color = $_REQUEST['color'];
  if(preg_match("/^[a-zA-Z0-9#]{3,7}$/", $color)) {
    $res = $scon->query('UPDATE cards SET tags=CONCAT_WS(" ", tags, "'.$color.'") WHERE board="'.$_REQUEST['bid'].'" AND list="'.$_REQUEST['listid'].'" AND id="'.$_REQUEST['cardid'].'" LIMIT 1');
    if(!$res) http_response_code(500);
  }
  else http_response_code(400);
}


function saveCard() { //Save Card
  global $scon;
  if($_SERVER['REQUEST_METHOD'] !== 'POST') {http_response_code(400); return;}
  $desc = file_get_contents('php://input') ?: null;
  $sq = $scon->prepare('UPDATE cards SET title=?,description=? WHERE board=? AND list=? AND id=? LIMIT 1');
  $sq->bind_param('sssss', $_REQUEST['title'], $desc, $_REQUEST['bid'], $_REQUEST['listid'], $_REQUEST['cardid']);
  $sq->execute();
  $sq->close();

  if(!$sq) http_response_code(500);
}


function moveCard() { //Move Card
  global $scon;
  if($_REQUEST['stid'] === $_REQUEST['dpid'] || $_REQUEST['stid'] === $_REQUEST['dtid']) {
    http_response_code(400);
    return;
  }
  //idempotency check
  //source
  $res = $scon->query('SELECT parent FROM cards WHERE board="'.$_REQUEST['bid'].'" AND list="'.$_REQUEST['slid'].'" AND id="'.$_REQUEST['stid'].'" LIMIT 1');
  if(mysqli_num_rows($res) !== 1) {http_response_code(409); return;}
  $parent = mysqli_fetch_array($res)[0];
  if($parent !== $_REQUEST['spid']) {http_response_code(409); return;}
  //void
  if($_REQUEST['vtid'] !== '0') { //src not last in list
    $res = $scon->query('SELECT parent FROM cards WHERE board="'.$_REQUEST['bid'].'" AND list="'.$_REQUEST['slid'].'" AND id="'.$_REQUEST['vtid'].'" LIMIT 1');
    if(mysqli_num_rows($res) !== 1) {http_response_code(409); return;}
    $parent = mysqli_fetch_array($res)[0];
    if($parent !== $_REQUEST['stid']) {http_response_code(409); return;}
  }
  else { //src is last in list
    $res = $scon->query('SELECT 1 FROM cards WHERE board="'.$_REQUEST['bid'].'" AND parent="'.$_REQUEST['stid'].'" LIMIT 1');
    if(mysqli_num_rows($res) !== 0) {http_response_code(409); return;}
  }
  //dest
  if($_REQUEST['dtid'] === '0') { //dest last in list
    if($_REQUEST['dpid'] !== '0') {
      $res = $scon->query('SELECT 1 FROM cards WHERE board="'.$_REQUEST['bid'].'" AND list="'.$_REQUEST['dlid'].'" AND id="'.$_REQUEST['dpid'].'" LIMIT 1');
      if(mysqli_num_rows($res) !== 1) {http_response_code(409); return;}
      $res = $scon->query('SELECT 1 FROM cards WHERE board="'.$_REQUEST['bid'].'" AND list="'.$_REQUEST['dlid'].'" AND parent="'.$_REQUEST['dpid'].'" LIMIT 1');
      if(mysqli_num_rows($res) !== 0) {http_response_code(409); return;}
    }
    else { //dest only in list
      $res = $scon->query('SELECT 1 FROM lists WHERE board="'.$_REQUEST['bid'].'" AND id="'.$_REQUEST['dlid'].'" LIMIT 1');
      if(mysqli_num_rows($res) !== 1) {http_response_code(409); return;}
    }
  }
  else { //dest not last in list
    $res = $scon->query('SELECT parent FROM cards WHERE board="'.$_REQUEST['bid'].'" AND list="'.$_REQUEST['dlid'].'" AND id="'.$_REQUEST['dtid'].'" LIMIT 1');
    if(mysqli_num_rows($res) !== 1) {http_response_code(409); return;}
    $parent = mysqli_fetch_array($res)[0];
    if($parent !== $_REQUEST['dpid']) {http_response_code(409); return;}
  }

  //set src pid to dest pid
  $scon->query('UPDATE cards SET parent="'.$_REQUEST['dpid'].'",list="'.$_REQUEST['dlid'].'" WHERE board="'.$_REQUEST['bid'].'" AND id="'.$_REQUEST['stid'].'" LIMIT 1');
  //set dest pid to src id
  if($_REQUEST['dtid'] !== '0')
    $scon->query('UPDATE cards SET parent="'.$_REQUEST['stid'].'" WHERE board="'.$_REQUEST['bid'].'" AND id="'.$_REQUEST['dtid'].'" LIMIT 1');
  //set void pid to src pid
  if($_REQUEST['vtid'] !== '0')
    $scon->query('UPDATE cards SET parent="'.$_REQUEST['spid'].'" WHERE board="'.$_REQUEST['bid'].'" AND id="'.$_REQUEST['vtid'].'" LIMIT 1');
}


function deleteList() { //Delete List
  global $scon;
  if($_SERVER['REQUEST_METHOD'] !== 'PUT') {http_response_code(400); return;}
  $res = $scon->query('INSERT INTO archive SELECT * FROM cards WHERE board="'.$_REQUEST['bid'].'" AND list="'.$_REQUEST['listid'].'"');
  $res = $scon->query('DELETE FROM cards WHERE board="'.$_REQUEST['bid'].'" AND list="'.$_REQUEST['listid'].'"');
  $res = $scon->query('DELETE FROM lists WHERE board="'.$_REQUEST['bid'].'" AND id="'.$_REQUEST['listid'].'"');
  if(!$res) http_response_code(500);
}


function delTag() { //Delete Tag
  global $scon;
  $color = $_REQUEST['color'];
  $res = $scon->query('SELECT tags FROM cards WHERE board="'.$_REQUEST['bid'].'" AND list="'.$_REQUEST['listid'].'" AND id="'.$_REQUEST['cardid'].'" LIMIT 1');
  if(empty($res) || mysqli_num_rows($res) !== 1) {
    http_response_code(404);
    return;
  }
  $tag = mysqli_fetch_array($res)[0];
  $tag = preg_replace("/\B$color\b\s?/", '', $tag);
  $tag = trim($tag);
  $tag = empty($tag) ? 'null' : '"'.$tag.'"';

  $res = $scon->query('UPDATE cards SET tags='.$tag.' WHERE board="'.$_REQUEST['bid'].'" AND list="'.$_REQUEST['listid'].'" AND id="'.$_REQUEST['cardid'].'" LIMIT 1');
  if(!$res) http_response_code(500);
}


function cardColor() { //Card Color
  global $scon;
  $color = (empty($_REQUEST['color']) || $_REQUEST['color'] === '#f0f0f0') ? 'null' : '"'.$_REQUEST['color'].'"';
  $res = $scon->query('UPDATE cards SET color='.$color.' WHERE board="'.$_REQUEST['bid'].'" AND list="'.$_REQUEST['listid'].'" AND id="'.$_REQUEST['cardid'].'" LIMIT 1');
  if(!$res) http_response_code(500);
}


function archiveCard() { //Archive Card
  global $scon;
  $res = $scon->query('INSERT INTO archive SELECT * FROM cards WHERE board="'.$_REQUEST['bid'].'" AND list="'.$_REQUEST['listid'].'" AND id="'.$_REQUEST['cardid'].'" LIMIT 1');
  $res = $scon->query('UPDATE cards SET parent="'.$_REQUEST['pid'].'" WHERE board="'.$_REQUEST['bid'].'" AND list="'.$_REQUEST['listid'].'" AND parent="'.$_REQUEST['cardid'].'" LIMIT 1');
  $res = $scon->query('DELETE FROM cards WHERE board="'.$_REQUEST['bid'].'" AND list="'.$_REQUEST['listid'].'" AND id="'.$_REQUEST['cardid'].'" LIMIT 1');
  if(!$res)
    http_response_code(500);
}


function deleteBoard() { //Delete Board
  global $scon;
  if($_SERVER['REQUEST_METHOD'] !== 'PUT') {http_response_code(400); return;}
  $scon->query('INSERT INTO archive SELECT * FROM cards WHERE board="'.$_REQUEST['bid'].'"');
  $scon->query('DELETE FROM cards WHERE board="'.$_REQUEST['bid'].'"');
  $scon->query('DELETE FROM lists WHERE board="'.$_REQUEST['bid'].'"');
  $res = $scon->query('DELETE FROM boards WHERE id="'.$_REQUEST['bid'].'"');
  if(!$res) http_response_code(404);
}


function export() { //Export Board
  global $scon;
  $res = $scon->query('SELECT * FROM boards WHERE id="'.$_REQUEST['bid'].'"');
  if(empty($res) || mysqli_num_rows($res) !== 1) {
    http_response_code(404);
    return;
  }
  $data = (object)mysqli_fetch_assoc($res);
  $resL = $scon->query('SELECT id,ordr,name FROM lists WHERE board="'.$_REQUEST['bid'].'" ORDER BY ordr asc');
  $resC = $scon->query('SELECT list,id,parent,title,tags,color,cdate,mdate,description FROM cards WHERE board="'.$_REQUEST['bid'].'"');
  $rowsL = mysqli_fetch_all($resL, MYSQLI_ASSOC);
  $rowsC = mysqli_fetch_all($resC, MYSQLI_ASSOC);
  $data->lists = $rowsL;
  $data->cards = $rowsC;

  header('content-disposition: attachment; filename="tellor_'.$data->id.'.json"');
  echo json_encode($data);
}


function import() { //Import Board
  if($_SERVER['REQUEST_METHOD'] !== 'POST') {http_response_code(400); return;}
  $dataRaw = file_get_contents('php://input');
  $data = json_decode($dataRaw);
  if(!$data) {
    http_response_code(400);
    return;
  }
  if(isset($data->nodeId)) importTrello($data);
  else if(isset($data->name)) importTellor($data);
  else http_response_code(400);
}


function importTellor($data) { //Import Tellor
  global $scon;
  $res = $scon->query('INSERT INTO boards(id,name,bgimg) VALUES("'.$data->id.'","'.$data->name.'","'.$data->bgimg.'")');
  if(!$res) {http_response_code(500); return;}

  $sq = $scon->prepare('INSERT INTO lists(board,id,ordr,name) VALUES(?,?,?,?)');
  foreach($data->lists as $list) {
    $sq->bind_param('ssssi', $data->id, $list->id, $list->ordr, $list->name);
    $sq->execute();
  }
  $sq->close();
  $sq = $scon->prepare('INSERT INTO cards VALUES(?,?,?,?,?,?,?,?,?,?)');
  foreach($data->cards as $card) {
    $sq->bind_param('ssssssssss', $data->id, $card->list, $card->id, $card->parent, $card->title, $card->tags, $card->color, $card->cdate, $card->mdate, $card->description);
    $sq->execute();
  }
  $sq->close();
  echo $data->id;
}


function importTrello($data) { //Import Trello
  global $scon;
  $colorCodes = array("black" => "#000", "silver" => "#BBB", "gray" => "#888", "white" => "#FFF", "maroon" => "#900", "red" => "#F00", "purple" => "#808", "fuchsia" => "#F0F", "green" => "#080", "lime" => "#0F0", "olive" => "#880", "yellow" => "#FF0", "navy" => "#008", "blue" => "#00F", "teal" => "#088", "aqua" => "#0FF");

  $bid = idGen32();
  $boardName = str_replace(['\\','"','<','\n'], '', $data->name);
  $res = $scon->query('INSERT INTO boards(id,name,bgimg) VALUES("'.$bid.'","'.$boardName.'","'.$data->perfs->backgroundImage.'")');
  if(!$res) {http_response_code(500); return;}

  usort($data->cards, function($a, $b) {return $a->pos - $b->pos;});

  $sqlCards = $scon->prepare('INSERT INTO cards VALUES(?,?,?,?,?,?,null,default,?,?)');
  $sqlLists = $scon->prepare('INSERT INTO lists(board,id,ordr,name) VALUES(?,?,?,?)');

  foreach($data->lists as $list) {
    if($list->closed) continue;
    $lid = idGen32();
    $sqlLists->bind_param('sssis', $bid, $lid, $list->pos, $list->name);
    $sqlLists->execute();

    $pid = "0";
    foreach($data->cards as $card) {
      if($card->closed || $card->idList	!== $list->id) continue;
      $cid = idGen32();

      $tags = "";
      foreach($card->labels as $label) { //tags
        if(empty($label->color)) continue;
        if(str_starts_with($label->color, '#'))
          $tag = substr($label->color, 1);
        else
          $tag = $colorCodes[$label->color];
        if($tag)
          $tags .= $tag . ' ';
      }
      $tags = trim($tags);

      $sqlCards->bind_param('ssssssss', $bid, $lid, $cid, $pid, $card->name, $tags, $card->dateLastActivity, $card->desc);
      $sqlCards->execute();
      $pid = $cid;
    }
  }

  $sqlLists->close();
  $sqlCards->close();
  echo $bid;
}


function idGen32() {
  $chars = '';
  $bytes = random_bytes(16);

  for($i = 0; $i < 16; $i++) {
    $byte = ord($bytes[$i]) & 31;
    $byte += ($byte > 9) ? 87 : 48;
    $chars .= chr($byte);
  }
  return $chars;
}

?>