Initial implementation
This commit is contained in:
commit
bcbde6359a
21
composer.json
Normal file
21
composer.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "leenooks/trello",
|
||||
"description": "Trello API",
|
||||
"keywords": ["laravel","leenooks","trello"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Deon George",
|
||||
"email": "deon@leenooks.net"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
},
|
||||
"require-dev": {
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Trello\\": "src"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
294
src/API.php
Normal file
294
src/API.php
Normal file
@ -0,0 +1,294 @@
|
||||
<?php
|
||||
|
||||
namespace Trello;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Trello\Models\{Board,BoardList,Card,CustomField,Token};
|
||||
use Trello\Models\CustomFields\{ListList,Options\Option};
|
||||
use Trello\Response\Generic;
|
||||
|
||||
final class API
|
||||
{
|
||||
private const LOGKEY = 'API';
|
||||
private const VERSION = 1;
|
||||
private const CACHE_TIME = 600;
|
||||
private const URL = 'https://api.trello.com';
|
||||
|
||||
// Our trello token to use
|
||||
private $_token;
|
||||
|
||||
public function __construct(Token $o)
|
||||
{
|
||||
$this->_token = $o;
|
||||
|
||||
Log::debug(sprintf('%s:Trello API with token [%s]',static::LOGKEY,$this->_token ? $this->_token->token_hidden() : NULL));
|
||||
}
|
||||
|
||||
public function createCard(Card $card): Card
|
||||
{
|
||||
Log::debug(sprintf('%s:Create Card [%s] on list [%s]',static::LOGKEY,$card->name,$card->idList));
|
||||
|
||||
return (new Card)->forceFill((array)$this->execute('cards',array_merge($card->toArray(),['method'=>'POST']))) ;
|
||||
}
|
||||
|
||||
public function createCustomField(Board $board,string $name,string $type): CustomField
|
||||
{
|
||||
Log::debug(sprintf('%s:Create CustomField [%s] in Boards [%s]',static::LOGKEY,$name,$board->id));
|
||||
if (! in_array($type,['checkbox','list','number','text','date']))
|
||||
throw new \Exception('Invalid type: '.$type);
|
||||
|
||||
// Invalidate any cache
|
||||
Cache::forget(md5(sprintf('boards/%s/customFields',$board->id).serialize([])));
|
||||
|
||||
return CustomField::factory($this->execute('customFields',[
|
||||
'name'=>$name,
|
||||
'type'=>$type,
|
||||
'idModel'=>$board->id,
|
||||
'display_cardFront'=>'true',
|
||||
'modelType'=>'board',
|
||||
'method'=>'POST'
|
||||
]));
|
||||
}
|
||||
|
||||
public function createCustomFieldOptions(ListList $field,Collection $options): ListList
|
||||
{
|
||||
Log::debug(sprintf('%s:Create CustomField Options to [%s] (%s)',static::LOGKEY,$field->name,$options->pluck('value.text')->join('|')));
|
||||
|
||||
// Invalidate any cache
|
||||
Cache::forget(md5(sprintf('boards/%s/customFields',$field->idModel).serialize([])));
|
||||
|
||||
foreach ($options as $option) {
|
||||
Log::debug(sprintf('%s: Adding (%s)',static::LOGKEY,Arr::get($option,'value.text')));
|
||||
|
||||
$field->addOption((new Option)->forceFill((array)$this->execute(
|
||||
sprintf('customFields/%s/options',$field->id),
|
||||
array_merge(
|
||||
$option,
|
||||
['method'=>'POST']
|
||||
))));
|
||||
}
|
||||
|
||||
return $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a list on a board
|
||||
*
|
||||
* @param Board $board
|
||||
* @param string $name
|
||||
* @return BoardList
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function createList(Board $board,string $name): BoardList
|
||||
{
|
||||
Log::debug(sprintf('%s:Create List [%s] in Boards [%s]',static::LOGKEY,$name,$board->id));
|
||||
|
||||
// Invalidate any cache
|
||||
Cache::forget(md5(sprintf('boards/%s/lists',$board->id).serialize([])));
|
||||
|
||||
return (new BoardList)->forceFill((array)$this->execute('lists',['name'=>$name,'idBoard'=>$board->id,'method'=>'POST']))->syncOriginal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the Slack API
|
||||
*
|
||||
* @param string $path // @todo this should really be called $path, since it isnt the HTTP method
|
||||
* @param array $parameters
|
||||
* @return object|array
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function execute(string $path,array $parameters=[])
|
||||
{
|
||||
$url = sprintf('%s/%d/%s',self::URL,self::VERSION,$path);
|
||||
$method = Arr::get($parameters,'method','GET');
|
||||
|
||||
if ($parameters)
|
||||
Arr::forget($parameters,'method');
|
||||
|
||||
// If we are passed an array, we'll do a normal post.
|
||||
switch ($method) {
|
||||
case 'GET':
|
||||
$request = $this->prepareRequest(
|
||||
$url,
|
||||
$parameters,
|
||||
[
|
||||
'Content-Type: application/json; charset=utf-8',
|
||||
sprintf('Authorization: OAuth oauth_consumer_key="%s", oauth_token="%s"',$this->_token->key,$this->_token->token),
|
||||
]
|
||||
);
|
||||
break;
|
||||
|
||||
case 'POST':
|
||||
$request = $this->prepareRequestPost(
|
||||
$url,
|
||||
$parameters,
|
||||
[
|
||||
'Content-Type: application/json; charset=utf-8',
|
||||
sprintf('Authorization: OAuth oauth_consumer_key="%s", oauth_token="%s"',$this->_token->key,$this->_token->token),
|
||||
]
|
||||
);
|
||||
break;
|
||||
|
||||
case 'PUT':
|
||||
$request = $this->prepareRequestPut(
|
||||
$url,
|
||||
$parameters,
|
||||
[
|
||||
'Content-Type: application/json; charset=utf-8',
|
||||
sprintf('Authorization: OAuth oauth_consumer_key="%s", oauth_token="%s"',$this->_token->key,$this->_token->token),
|
||||
]
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \Exception(sprintf('Unknown method: %s',$method));
|
||||
}
|
||||
|
||||
$key = md5($path.serialize($parameters));
|
||||
|
||||
//Cache::forget($key);
|
||||
$result = Cache::remember($key,self::CACHE_TIME,function() use ($request,$url) {
|
||||
try {
|
||||
$response = curl_exec($request);
|
||||
|
||||
switch($x=curl_getinfo($request,CURLINFO_HTTP_CODE)) {
|
||||
case 400:
|
||||
case 404:
|
||||
dump([$xx=curl_getinfo($request),'response'=>$response]);
|
||||
|
||||
throw new \Exception(sprintf('CURL exec returned %d: %s (%s)',$x,curl_error($request),serialize($xx)));
|
||||
}
|
||||
|
||||
curl_close($request);
|
||||
return json_decode($response);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error(sprintf('%s:Got an error while posting to [%s] (%s)',static::LOGKEY,$url,$e->getMessage()),['m'=>__METHOD__]);
|
||||
|
||||
curl_close($request);
|
||||
throw new \Exception($e->getMessage());
|
||||
}
|
||||
});
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getBoards(): Collection
|
||||
{
|
||||
Log::debug(sprintf('%s:Get Boards',static::LOGKEY));
|
||||
|
||||
return Board::hydrate($this->execute('members/me/boards'));
|
||||
}
|
||||
|
||||
public function getCard(string $id): Card
|
||||
{
|
||||
Log::debug(sprintf('%s:Get Card [%s]',static::LOGKEY,$id));
|
||||
|
||||
return (new Card)->forceFill((array)$this->execute(sprintf('cards/%s?%s',$id,http_build_query(['all','customFieldItems'=>'true']))))->syncOriginal();
|
||||
}
|
||||
|
||||
public function getCustomFields(Board $board): Collection
|
||||
{
|
||||
Log::debug(sprintf('%s:Get CustomFields from [%s]',static::LOGKEY,$board->id));
|
||||
|
||||
$result = collect();
|
||||
foreach ($this->execute(sprintf('boards/%s/customFields',$board->id)) as $cf)
|
||||
$result->push(CustomField::factory($cf));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of Cards for a Board
|
||||
*
|
||||
* @param Board $board
|
||||
* @return Collection
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getCards(Board $board): Collection
|
||||
{
|
||||
Log::debug(sprintf('%s:Get Board Cards [%s]',static::LOGKEY,$board->id));
|
||||
|
||||
return Card::hydrate($this->execute(sprintf('boards/%s/cards',$board->id)));
|
||||
}
|
||||
|
||||
public function getLists(Board $board): Collection
|
||||
{
|
||||
Log::debug(sprintf('%s:Get Board Lists [%s]',static::LOGKEY,$board->id));
|
||||
|
||||
return BoardList::hydrate($this->execute(sprintf('boards/%s/lists',$board->id)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the API call
|
||||
*
|
||||
* @param $url
|
||||
* @param array $parameters
|
||||
* @param array $headers
|
||||
* @return resource
|
||||
*/
|
||||
private function prepareRequest($url,array $parameters=[],array $headers=[])
|
||||
{
|
||||
$request = curl_init();
|
||||
|
||||
curl_setopt($request,CURLOPT_URL,$url.($parameters ? '?'.http_build_query($parameters) : ''));
|
||||
curl_setopt($request,CURLOPT_RETURNTRANSFER,TRUE);
|
||||
if ($headers)
|
||||
curl_setopt($request,CURLOPT_HTTPHEADER,$headers);
|
||||
curl_setopt($request,CURLINFO_HEADER_OUT,TRUE);
|
||||
curl_setopt($request,CURLOPT_SSL_VERIFYPEER,FALSE);
|
||||
curl_setopt($request,CURLOPT_HTTPGET,TRUE);
|
||||
|
||||
return $request;
|
||||
}
|
||||
|
||||
private function prepareRequestPost($url,$parameters='',$headers=[])
|
||||
{
|
||||
$request = $this->prepareRequest($url,[],$headers);
|
||||
curl_setopt($request,CURLOPT_POST,TRUE);
|
||||
curl_setopt($request,CURLOPT_POSTFIELDS,json_encode($parameters));
|
||||
|
||||
return $request;
|
||||
}
|
||||
|
||||
private function prepareRequestPut($url,$parameters='',$headers=[])
|
||||
{
|
||||
$request = $this->prepareRequest($url,[],$headers);
|
||||
//curl_setopt($request,CURLOPT_PUT,TRUE);
|
||||
curl_setopt($request,CURLOPT_CUSTOMREQUEST,'PUT');
|
||||
curl_setopt($request,CURLOPT_POSTFIELDS,json_encode($parameters));
|
||||
|
||||
return $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a card's value
|
||||
*
|
||||
* @param Card $card
|
||||
* @param CustomField $cf
|
||||
* @param string $value
|
||||
* @return Generic
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function setFieldValue(Card $card,CustomField $cf,array $value)
|
||||
{
|
||||
if (! $card->id)
|
||||
throw new \Exception('Card doesnt have an id?');
|
||||
|
||||
$x = $this->execute(sprintf('card/%s/customField/%s/item',$card->id,$cf->id),array_merge($value,['method'=>'PUT']));
|
||||
|
||||
return new Generic((array)$x);
|
||||
}
|
||||
|
||||
public function updateCard(Card $card): Card
|
||||
{
|
||||
Log::debug(sprintf('%s:Update Card [%s] on list [%s]',static::LOGKEY,$card->name,$card->idList));
|
||||
|
||||
$x = $this->execute(sprintf('cards/%s',$card->id),array_merge($card->getDirty(),['method'=>'PUT']));
|
||||
|
||||
return (new Card)->forceFill((array)$this->execute(sprintf('cards/%s',$card->id),array_merge($card->getDirty(),['method'=>'PUT'])));
|
||||
}
|
||||
}
|
7
src/Exceptions/TrelloException.php
Normal file
7
src/Exceptions/TrelloException.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Trello\Exceptions;
|
||||
|
||||
class TrelloException extends \Exception
|
||||
{
|
||||
}
|
142
src/Models/Board.php
Normal file
142
src/Models/Board.php
Normal file
@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
namespace Trello\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Trello\API;
|
||||
use Trello\Models\CustomFields\ListList;
|
||||
|
||||
final class Board extends Model
|
||||
{
|
||||
protected $keyType = 'string';
|
||||
protected const LOGKEY = 'MTB';
|
||||
|
||||
public Collection $customfields;
|
||||
private API $api;
|
||||
public ?BoardList $newopslist = NULL;
|
||||
public const newopslist = 'New Ops';
|
||||
|
||||
/**
|
||||
* Use the API to store/retrieve values
|
||||
*
|
||||
* @return API
|
||||
* @todo This should be kept private, and we should call functions to retrieve the items we are interested in
|
||||
*/
|
||||
public function api(): API
|
||||
{
|
||||
return $this->api;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a specific custom field
|
||||
*
|
||||
* @param string $name
|
||||
* @return CustomField
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function customField(string $name): ?CustomField
|
||||
{
|
||||
return $this->customFields()->filter(function($item) use ($name) { return $item->name == $name;})->pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this boards custom fields.
|
||||
*
|
||||
* @return Collection
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function customFields(): Collection
|
||||
{
|
||||
if (! $this->customfields->count()) {
|
||||
$cf = $this->api->getCustomFields($this);
|
||||
|
||||
// Check all our customFields are of the types we need:
|
||||
foreach ($cf as $key => $field) {
|
||||
if ($x=config('trello.customfields.'.$field->name)) {
|
||||
|
||||
if ($field instanceof $x) {
|
||||
dump(['m'=>__METHOD__,'EXISTS','x'=>$x,'field'=>$field,'listlsit'=>$field instanceof ListList]);
|
||||
|
||||
// If it is a list item, we need to check that the list has all the options
|
||||
if ($field instanceof ListList) {
|
||||
if (! $field->hasAllOptions()) {
|
||||
$this->api->createCustomFieldOptions($field,collect($field->missingOptions())->transform(function($item) { return ['pos'=>'bottom','value'=>['text'=>$item]]; }));
|
||||
//dd(['m'=>__METHOD__,'has failed?'=>collect($field->missingOptions())->transform(function($item,$key) { return ['pos'=>$key,'value'=>['text'=>$item]]; }),'x'=>$x]);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
Log::error(sprintf('%s:Field [%s] is not of the right type [%s] (%s)',self::LOGKEY,$field->name,$field->type,$x));
|
||||
|
||||
throw new \Exception(sprintf('Invalid field type: %s (%s), should be [%s]',$field->name,get_class($field),$x));
|
||||
}
|
||||
|
||||
// Not one of our fields
|
||||
} else {
|
||||
Log::debug(sprintf('%s:Ignoring custom field [%s]',self::LOGKEY,$field->name));
|
||||
|
||||
$cf->forget($key);
|
||||
}
|
||||
}
|
||||
|
||||
// Any missing fields we need to create.
|
||||
foreach (collect(config('trello.customfields'))->filter(function($item,$key) use ($cf) { return $cf->pluck('attributes.name')->search($key) === FALSE; }) as $key => $field) {
|
||||
Log::debug(sprintf('%s:Creating field [%s] (%s)',self::LOGKEY,$key,$field));
|
||||
|
||||
$o = new $field(new \stdClass);
|
||||
dump(['o'=>$o]);
|
||||
$cf->push($x=$this->api->createCustomField($this,$key,$o->trello_type));
|
||||
//dd(['M'=>__METHOD__,'addkey'=>$key,'addfield'=>$field,'x'=>$x]);
|
||||
|
||||
// If it is a list, we'll need to create our options too
|
||||
if ($x instanceof ListList) {
|
||||
$this->api->createCustomFieldOptions($x,collect($x->missingOptions())->transform(function($item) { return ['pos'=>'bottom','value'=>['text'=>$item]]; }));
|
||||
}
|
||||
}
|
||||
|
||||
$this->customfields = $cf;
|
||||
}
|
||||
|
||||
return $this->customfields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the list that we use to create new cards in
|
||||
*
|
||||
* @return BoardList
|
||||
*/
|
||||
public function listNewOps(): BoardList
|
||||
{
|
||||
if (! $this->newopslist) {
|
||||
// Find our "New Opps" List in Trello
|
||||
$newoplist = $this->api
|
||||
->getLists($this)
|
||||
->filter(function($item) { return $item->name == self::newopslist; });
|
||||
|
||||
// If list doesnt exist, we'll create it.
|
||||
if (! $newoplist->count()) {
|
||||
//$newoplist = $api->createList($b,$newopslist);
|
||||
dd([__METHOD__=>$newoplist,'todo'=>'create this']);
|
||||
|
||||
} else {
|
||||
$this->newoplist = $newoplist->pop();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->newoplist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Record the API that this board is stored/retrieved with
|
||||
*
|
||||
* @param API $api
|
||||
* @return void
|
||||
*/
|
||||
public function setAPI(API $api): void
|
||||
{
|
||||
$this->api = $api;
|
||||
$this->customfields = collect();
|
||||
}
|
||||
}
|
10
src/Models/BoardList.php
Normal file
10
src/Models/BoardList.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Trello\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
final class BoardList extends Model
|
||||
{
|
||||
protected $keyType = 'string';
|
||||
}
|
58
src/Models/Card.php
Normal file
58
src/Models/Card.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Trello\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use App\Trello\Models\CustomFields\{Action,SalesStage};
|
||||
|
||||
final class Card extends Model
|
||||
{
|
||||
protected $keyType = 'string';
|
||||
|
||||
/**
|
||||
* Get this card's custom field value.
|
||||
*
|
||||
* @param CustomField $o
|
||||
* @return object|null
|
||||
*/
|
||||
public function getCustomFieldValue(CustomField $o): ?object
|
||||
{
|
||||
return collect($this->customFieldItems)->filter(function($item) use ($o) { return $item->idCustomField == $o->id; })->pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this card should be ignored.
|
||||
*
|
||||
* @param Board $b
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function shouldIgnore(Board $b): bool
|
||||
{
|
||||
// Check Stages
|
||||
$cf = $b->customField('Stage');
|
||||
$y = '';
|
||||
|
||||
if (($x=$this->getCustomFieldValue($cf)) && (! in_array($y=$cf->value($x),SalesStage::options))) {
|
||||
Log::info(sprintf('Card [%s] Stage value is not one of ours [%s]',$this->id,$y));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
Log::debug(sprintf('Card [%s] Stage value is [%s]',$this->id,$y ?: 'Not Set'));
|
||||
|
||||
// Check Actions
|
||||
$cf = $b->customField('Action');
|
||||
$y = '';
|
||||
|
||||
if (($x=$this->getCustomFieldValue($cf)) && (! in_array($y=$cf->value($x),Action::options)) || ($y === 'Ignore')) {
|
||||
Log::info(sprintf('Card [%s] Action value is not one of ours [%s]',$this->id,$y));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
Log::debug(sprintf('Card [%s] Action value is [%s]',$this->id,$y ?: 'Not Set'));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
68
src/Models/CustomField.php
Normal file
68
src/Models/CustomField.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Trello\Models;
|
||||
|
||||
use Trello\Models\CustomFields\{Base,Checkbox,Date,ListList,Number,Text};
|
||||
|
||||
abstract class CustomField extends Base
|
||||
{
|
||||
protected $keyType = 'string';
|
||||
private const LOGKEY = 'TCF';
|
||||
|
||||
/**
|
||||
* Resolve the data into a CustomField Object
|
||||
*
|
||||
* @param object $data
|
||||
* @return mixed|Checkbox|Date|ListList|Number|Text
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function factory(object $data) {
|
||||
// See if the field name is one we have configured
|
||||
if (collect(config('trello.customfields'))->has($x=object_get($data,'name'))) {
|
||||
$xx = config('trello.customfields.'.$x);
|
||||
$o = new $xx($data);
|
||||
|
||||
if ($o->trello_type !== ($y=object_get($data,'type')))
|
||||
throw new \Exception(sprintf('%s:! ERROR - Custom field [%s] (%s) is not the right type [%s]',self::LOGKEY,$x,$o->trello_type,$y));
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
switch ($x=object_get($data,'type')) {
|
||||
case 'checkbox':
|
||||
return new Checkbox($data);
|
||||
|
||||
case 'date':
|
||||
return new Date($data);
|
||||
|
||||
case 'list':
|
||||
return new ListList($data);
|
||||
|
||||
case 'number':
|
||||
return new Number($data);
|
||||
|
||||
case 'text':
|
||||
return new Text($data);
|
||||
|
||||
default:
|
||||
dump($data);
|
||||
throw new \Exception('Unknown data type: '.$x);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a customfield's value
|
||||
*
|
||||
* @param string $value
|
||||
* @return array
|
||||
*/
|
||||
abstract public function set(string $value): array;
|
||||
|
||||
/**
|
||||
* Get a customfield's value
|
||||
*
|
||||
* @param object $key
|
||||
* @return string|null
|
||||
*/
|
||||
abstract public function value(object $key): ?string;
|
||||
}
|
28
src/Models/CustomFields/Base.php
Normal file
28
src/Models/CustomFields/Base.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Trello\Models\CustomFields;
|
||||
|
||||
abstract class Base
|
||||
{
|
||||
public object $attributes;
|
||||
public const options = NULL;
|
||||
|
||||
public function __construct(object $attributes)
|
||||
{
|
||||
$this->attributes = $attributes;
|
||||
}
|
||||
|
||||
public function __get($key)
|
||||
{
|
||||
switch ($key) {
|
||||
case 'trello_type':
|
||||
return object_get($this->attributes,'type');
|
||||
|
||||
case 'type':
|
||||
return get_class($this);
|
||||
|
||||
default:
|
||||
return object_get($this->attributes,$key);
|
||||
}
|
||||
}
|
||||
}
|
22
src/Models/CustomFields/Checkbox.php
Normal file
22
src/Models/CustomFields/Checkbox.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Trello\Models\CustomFields;
|
||||
|
||||
use Trello\Models\CustomField;
|
||||
|
||||
class Checkbox extends CustomField
|
||||
{
|
||||
/* ABSTRACT METHODS */
|
||||
|
||||
public function set(string $value): array
|
||||
{
|
||||
// @todo TO TEST
|
||||
return ['value'=>['checked'=>$value ? 'true' : 'false']];
|
||||
}
|
||||
|
||||
public function value(object $key): ?string
|
||||
{
|
||||
// @todo TO TEST
|
||||
return (string)$key->value->checked;
|
||||
}
|
||||
}
|
23
src/Models/CustomFields/Date.php
Normal file
23
src/Models/CustomFields/Date.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Trello\Models\CustomFields;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Trello\Models\CustomField;
|
||||
|
||||
class Date extends CustomField
|
||||
{
|
||||
/* ABSTRACT METHODS */
|
||||
|
||||
public function set(string $value): array
|
||||
{
|
||||
// @todo TO TEST
|
||||
return ['value'=>['date'=>Carbon::createFromTimeString($value)->toISOString()]];
|
||||
}
|
||||
|
||||
public function value(object $key): ?string
|
||||
{
|
||||
// @todo TO TEST
|
||||
return $key->value->date;
|
||||
}
|
||||
}
|
70
src/Models/CustomFields/ListList.php
Normal file
70
src/Models/CustomFields/ListList.php
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Trello\Models\CustomFields;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Trello\Models\CustomField;
|
||||
use Trello\Models\CustomFields\Options\Option;
|
||||
|
||||
class ListList extends CustomField
|
||||
{
|
||||
public Collection $options;
|
||||
|
||||
public function __construct(object $attributes)
|
||||
{
|
||||
parent::__construct($attributes);
|
||||
|
||||
$this->options = collect();
|
||||
|
||||
foreach (object_get($attributes,'options',[]) as $option)
|
||||
$this->addOption((new Option)->forceFill((array)$option)->syncOriginal());
|
||||
|
||||
unset($this->attributes->options);
|
||||
}
|
||||
|
||||
/* ABSTRACT METHODS */
|
||||
|
||||
public function set(string $value): array
|
||||
{
|
||||
return ['idValue'=>$this->id($value)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value, given a customfield key
|
||||
*
|
||||
* @param object $key
|
||||
* @return string|null
|
||||
*/
|
||||
public function value(object $key): ?string
|
||||
{
|
||||
return ($x=$this->options->filter(function($item) use ($key) { return $item->id == $key->idValue; })->pop()) ? $x->value->text : NULL;
|
||||
}
|
||||
|
||||
/* METHODS */
|
||||
|
||||
public function addOption(Option $option): void
|
||||
{
|
||||
$this->options->push($option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure our list has all the option values
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasAllOptions(): bool
|
||||
{
|
||||
return $this->missingOptions()->count() == 0;
|
||||
}
|
||||
|
||||
private function id(string $name): ?string
|
||||
{
|
||||
return ($x=$this->options->filter(function($item) use ($name) { return $item->name == $name; })->pop()) ? $x->id : NULL;
|
||||
}
|
||||
|
||||
public function missingOptions(): Collection
|
||||
{
|
||||
return collect(static::options)->diff($this->options->pluck('name'));
|
||||
}
|
||||
|
||||
}
|
20
src/Models/CustomFields/Number.php
Normal file
20
src/Models/CustomFields/Number.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Trello\Models\CustomFields;
|
||||
|
||||
use Trello\Models\CustomField;
|
||||
|
||||
class Number extends CustomField
|
||||
{
|
||||
/* ABSTRACT METHODS */
|
||||
|
||||
public function set(string $value): array
|
||||
{
|
||||
return ['value'=>['number'=>$value]];
|
||||
}
|
||||
|
||||
public function value(object $key): ?string
|
||||
{
|
||||
return (string)$key->value->number;
|
||||
}
|
||||
}
|
16
src/Models/CustomFields/Options/Option.php
Normal file
16
src/Models/CustomFields/Options/Option.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Trello\Models\CustomFields\Options;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class Option extends Model
|
||||
{
|
||||
protected $keyType = 'string';
|
||||
|
||||
public function getNameAttribute(): ?string
|
||||
{
|
||||
return ($x=Arr::get($this->attributes,'value')) ? $x->text : NULL;
|
||||
}
|
||||
}
|
20
src/Models/CustomFields/Text.php
Normal file
20
src/Models/CustomFields/Text.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Trello\Models\CustomFields;
|
||||
|
||||
use Trello\Models\CustomField;
|
||||
|
||||
class Text extends CustomField
|
||||
{
|
||||
/* ABSTRACT METHODS */
|
||||
|
||||
public function set(string $value): array
|
||||
{
|
||||
return ['value'=>['text'=>$value]];
|
||||
}
|
||||
|
||||
public function value(object $key): ?string
|
||||
{
|
||||
return $key->value->text;
|
||||
}
|
||||
}
|
20
src/Models/Token.php
Normal file
20
src/Models/Token.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Trello\Models;
|
||||
|
||||
final class Token
|
||||
{
|
||||
public string $key;
|
||||
public string $token;
|
||||
|
||||
public function __construct(string $key,string $token)
|
||||
{
|
||||
$this->key = $key;
|
||||
$this->token = $token;
|
||||
}
|
||||
|
||||
public function token_hidden(): string
|
||||
{
|
||||
return '...'.substr($this->token,-5);
|
||||
}
|
||||
}
|
60
src/Response/Base.php
Normal file
60
src/Response/Base.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Trello\Response;
|
||||
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* This parent class handles responses received from Trello
|
||||
*
|
||||
* @note: This class is used for events not specifically created.
|
||||
*/
|
||||
class Base implements \JsonSerializable
|
||||
{
|
||||
protected const LOGKEY = 'RB-';
|
||||
|
||||
/**
|
||||
* Default Constructor Setup
|
||||
*
|
||||
* @param object $response
|
||||
*/
|
||||
public function __construct(array $response)
|
||||
{
|
||||
$this->_data = $response;
|
||||
|
||||
// This is only for child classes
|
||||
if (get_class($this) == Base::class) {
|
||||
Log::debug(sprintf('%s:Trello RESPONSE Initialised [%s]',static::LOGKEY,get_class($this)),['m'=>__METHOD__]);
|
||||
|
||||
if (App::environment() == 'dev')
|
||||
file_put_contents('/tmp/response',print_r($this,TRUE),FILE_APPEND);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable getting values for keys in the response
|
||||
*
|
||||
* @note: This method is limited to certain values to ensure integrity reasons
|
||||
* @note: Classes should return:
|
||||
* + channel_id,
|
||||
* + team_id,
|
||||
* + ts,
|
||||
* + user_id
|
||||
*/
|
||||
public function __get($key)
|
||||
{
|
||||
switch ($key) {
|
||||
case 'id':
|
||||
return object_get($this->_data,$key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When we json_encode this object, this is the data that will be returned
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->_data ? $this->_data : new \stdClass;
|
||||
}
|
||||
}
|
11
src/Response/Generic.php
Normal file
11
src/Response/Generic.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Trello\Response;
|
||||
|
||||
/**
|
||||
* This is a Generic Slack Response to API calls
|
||||
*/
|
||||
class Generic extends Base
|
||||
{
|
||||
protected const LOGKEY = 'RGE';
|
||||
}
|
Loading…
Reference in New Issue
Block a user