mirror of
https://github.com/LBRYFoundation/lbry.com.git
synced 2025-09-02 18:25:11 +00:00
working asana task loading + curl caching
This commit is contained in:
parent
d5fed54b19
commit
a21e9b56b5
7 changed files with 241 additions and 89 deletions
|
@ -113,9 +113,8 @@ class ContentActions extends Actions
|
||||||
|
|
||||||
public static function executeRoadmap()
|
public static function executeRoadmap()
|
||||||
{
|
{
|
||||||
print_r(Asana::listRoadmapTasks());
|
|
||||||
die('wtf');
|
|
||||||
return ['content/roadmap', [
|
return ['content/roadmap', [
|
||||||
|
'tasks' => Asana::listRoadmapTasks()
|
||||||
]];
|
]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,24 +2,110 @@
|
||||||
|
|
||||||
class Asana
|
class Asana
|
||||||
{
|
{
|
||||||
protected static $curlOptions = [];
|
protected static $curlOptions = ['json_response' => true, 'cache' => true];
|
||||||
|
|
||||||
public static function listRoadmapTasks()
|
public static function listRoadmapTasks()
|
||||||
{
|
{
|
||||||
return static::get('abc');
|
/*
|
||||||
$uri = '/projects/projectId-id/tasks';
|
* return static::get('/projects');
|
||||||
|
[55] => Array
|
||||||
|
(
|
||||||
|
[id] => 158602294500138
|
||||||
|
[name] => Browser
|
||||||
|
)
|
||||||
|
|
||||||
|
[56] => Array
|
||||||
|
(
|
||||||
|
[id] => 158602294500137
|
||||||
|
[name] => Daemon
|
||||||
|
)
|
||||||
|
|
||||||
|
[57] => Array
|
||||||
|
(
|
||||||
|
[id] => 161514803479899
|
||||||
|
[name] => Blockchain and Wallet
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
[60] => Array
|
||||||
|
(
|
||||||
|
[id] => 158829550589337
|
||||||
|
[name] => Reporting and Analytics
|
||||||
|
)
|
||||||
|
|
||||||
|
[61] => Array
|
||||||
|
(
|
||||||
|
[id] => 158602294500214
|
||||||
|
[name] => Other
|
||||||
|
)
|
||||||
|
|
||||||
|
[62] => Array
|
||||||
|
(
|
||||||
|
[id] => 136290697597644
|
||||||
|
[name] => CI
|
||||||
|
)
|
||||||
|
|
||||||
|
[63] => Array
|
||||||
|
(
|
||||||
|
[id] => 158602294500249
|
||||||
|
[name] => Documentation
|
||||||
|
)
|
||||||
|
*/
|
||||||
|
// return static::get('/projects');
|
||||||
|
$projects = [
|
||||||
|
158602294500138 => 'LBRY Browser',
|
||||||
|
158602294500137 => 'LBRYnet',
|
||||||
|
161514803479899 => 'Blockchain and Wallets',
|
||||||
|
158829550589337 => 'Reporting and Analytics',
|
||||||
|
136290697597644 => 'Integration and Building',
|
||||||
|
158602294500249 => 'Documentation',
|
||||||
|
158602294500214 => 'Other'
|
||||||
|
];
|
||||||
|
|
||||||
|
$tasks = [
|
||||||
|
'ongoing' => [],
|
||||||
|
'upcoming' => []
|
||||||
|
];
|
||||||
|
|
||||||
|
$categories = array_keys($tasks);
|
||||||
|
foreach($projects as $projectId => $projectName)
|
||||||
|
{
|
||||||
|
$projectTasks = static::get('/tasks?' . http_build_query(['completed_since' => 'now', 'project' => $projectId]));
|
||||||
|
$key = null;
|
||||||
|
foreach ($projectTasks as $task)
|
||||||
|
{
|
||||||
|
if (mb_substr($task['name'], -1) === ':') //if task ends with ":", it is a category heading so switch the active key
|
||||||
|
{
|
||||||
|
$key = array_reduce($categories, function($carry, $category) use($task) {
|
||||||
|
return $carry ?: (strcasecmp($task['name'], $category . ':') === 0 ? $category : null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
elseif ($key && $task['name'])
|
||||||
|
{
|
||||||
|
$fullTask = static::get('/tasks/' . $task['id']);
|
||||||
|
$tasks[$key][] = array_intersect_key($fullTask, ['name' => null, 'due_on' => null]) + [
|
||||||
|
'project' => $projectName,
|
||||||
|
'assignee' => $fullTask['assignee'] ? ucwords($fullTask['assignee']['name']) : ''
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tasks;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function get($endpoint, array $data = [])
|
protected static function get($endpoint, array $data = [])
|
||||||
{
|
{
|
||||||
$apiKey = '0/c85cfce3591c2a3e214408cfba7cc44c';
|
$apiKey = '0/c85cfce3591c2a3e214408cfba7cc44c';
|
||||||
$options = [];
|
|
||||||
// $apiKey = Config::get('prefinery_key');
|
// $apiKey = Config::get('prefinery_key');
|
||||||
// curl -H "Authorization: Bearer ACCESS_TOKEN" https://app.asana.com/api/1.0/users/me
|
// curl -H "Authorization: Bearer ACCESS_TOKEN" https://app.asana.com/api/1.0/users/me
|
||||||
$options['headers'] = ['Authorization: Bearer ' . $apiKey];
|
|
||||||
return
|
$options = static::$curlOptions + [
|
||||||
Curl::get('https://app.asana.com/api/1.0/users/me', $data, $options)
|
'headers' => ['Authorization: Bearer ' . $apiKey]
|
||||||
;
|
];
|
||||||
|
|
||||||
|
$responseData = Curl::get('https://app.asana.com/api/1.0' . $endpoint, $data, $options);
|
||||||
|
return isset($responseData['data']) ? $responseData['data'] : [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,8 @@ class Prefinery
|
||||||
'Accept: application/json',
|
'Accept: application/json',
|
||||||
'Content-type: application/json'
|
'Content-type: application/json'
|
||||||
],
|
],
|
||||||
'json_data' => true
|
'json_data' => true,
|
||||||
|
'json_response' => true
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
@ -106,7 +107,7 @@ class Prefinery
|
||||||
$apiKey = Config::get('prefinery_key');
|
$apiKey = Config::get('prefinery_key');
|
||||||
$options = static::$curlOptions;
|
$options = static::$curlOptions;
|
||||||
$options['headers'][] = 'X-HTTP-Method-Override: PUT';
|
$options['headers'][] = 'X-HTTP-Method-Override: PUT';
|
||||||
return static::decodePrefineryResponse(
|
return static::processPrefineryResponse(
|
||||||
Curl::put(static::DOMAIN . static::PREFIX . $endpoint . '.json?api_key=' . $apiKey, $data, $options)
|
Curl::put(static::DOMAIN . static::PREFIX . $endpoint . '.json?api_key=' . $apiKey, $data, $options)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -114,7 +115,7 @@ class Prefinery
|
||||||
protected static function get($endpoint, array $data = [])
|
protected static function get($endpoint, array $data = [])
|
||||||
{
|
{
|
||||||
$apiKey = Config::get('prefinery_key');
|
$apiKey = Config::get('prefinery_key');
|
||||||
return static::decodePrefineryResponse(
|
return static::processPrefineryResponse(
|
||||||
Curl::get(static::DOMAIN . static::PREFIX . $endpoint . '.json?api_key=' . $apiKey, $data, static::$curlOptions)
|
Curl::get(static::DOMAIN . static::PREFIX . $endpoint . '.json?api_key=' . $apiKey, $data, static::$curlOptions)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -122,22 +123,15 @@ class Prefinery
|
||||||
protected static function post($endpoint, array $data = [], $allowEmptyResponse = true)
|
protected static function post($endpoint, array $data = [], $allowEmptyResponse = true)
|
||||||
{
|
{
|
||||||
$apiKey = Config::get('prefinery_key');
|
$apiKey = Config::get('prefinery_key');
|
||||||
return static::decodePrefineryResponse(
|
return static::processPrefineryResponse(
|
||||||
Curl::post(static::DOMAIN . static::PREFIX . $endpoint . '.json?api_key=' . $apiKey, $data, static::$curlOptions),
|
Curl::post(static::DOMAIN . static::PREFIX . $endpoint . '.json?api_key=' . $apiKey, $data, static::$curlOptions),
|
||||||
$allowEmptyResponse
|
$allowEmptyResponse
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function decodePrefineryResponse($rawBody, $allowEmptyResponse = true)
|
protected static function processPrefineryResponse(array $data, $allowEmptyResponse = true)
|
||||||
{
|
{
|
||||||
if (!$rawBody)
|
if (!$allowEmptyResponse && !$data)
|
||||||
{
|
|
||||||
throw new PrefineryException('Empty cURL response.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = json_decode($rawBody, true);
|
|
||||||
|
|
||||||
if (!$allowEmptyResponse && !$data && $data !== [])
|
|
||||||
{
|
{
|
||||||
throw new PrefineryException('Received empty or improperly encoded response.');
|
throw new PrefineryException('Received empty or improperly encoded response.');
|
||||||
}
|
}
|
||||||
|
|
15
data/cache/Apc.class.php
vendored
Normal file
15
data/cache/Apc.class.php
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by PhpStorm.
|
||||||
|
* User: kauffj
|
||||||
|
* Date: 8/13/16
|
||||||
|
* Time: 2:42 PM
|
||||||
|
*/
|
||||||
|
class Apc
|
||||||
|
{
|
||||||
|
public static function isEnabled()
|
||||||
|
{
|
||||||
|
return extension_loaded('apc') && ini_get('apc.enabled');
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,8 @@ class Curl
|
||||||
{
|
{
|
||||||
const GET = 'GET',
|
const GET = 'GET',
|
||||||
POST = 'POST',
|
POST = 'POST',
|
||||||
PUT = 'PUT';
|
PUT = 'PUT',
|
||||||
|
DEFAULT_CACHE = 60000;
|
||||||
|
|
||||||
public static function get($url, $params = [], $options = [])
|
public static function get($url, $params = [], $options = [])
|
||||||
{
|
{
|
||||||
|
@ -27,6 +28,7 @@ class Curl
|
||||||
public static function doCurl($method, $url, $params = [], $options = [])
|
public static function doCurl($method, $url, $params = [], $options = [])
|
||||||
{
|
{
|
||||||
$defaults = [
|
$defaults = [
|
||||||
|
'cache' => false,
|
||||||
'headers' => [],
|
'headers' => [],
|
||||||
'verify' => true,
|
'verify' => true,
|
||||||
'timeout' => 5,
|
'timeout' => 5,
|
||||||
|
@ -36,6 +38,7 @@ class Curl
|
||||||
'password' => null,
|
'password' => null,
|
||||||
'cookie' => null,
|
'cookie' => null,
|
||||||
'json_data' => false,
|
'json_data' => false,
|
||||||
|
'json_response' => false
|
||||||
];
|
];
|
||||||
|
|
||||||
$invalid = array_diff_key($options, $defaults);
|
$invalid = array_diff_key($options, $defaults);
|
||||||
|
@ -44,13 +47,28 @@ class Curl
|
||||||
throw new DomainException('Invalid curl options: ' . join(', ', array_keys($invalid)));
|
throw new DomainException('Invalid curl options: ' . join(', ', array_keys($invalid)));
|
||||||
}
|
}
|
||||||
|
|
||||||
$options = array_merge($defaults, $options);
|
|
||||||
|
|
||||||
if (!in_array($method, [static::GET, static::POST, static::PUT]))
|
if (!in_array($method, [static::GET, static::POST, static::PUT]))
|
||||||
{
|
{
|
||||||
throw new DomainException('Invalid method: ' . $method);
|
throw new DomainException('Invalid method: ' . $method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$options = array_merge($defaults, $options);
|
||||||
|
|
||||||
|
if (!Apc::isEnabled())
|
||||||
|
{
|
||||||
|
$options['cache'] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($options['cache'])
|
||||||
|
{
|
||||||
|
$cacheKey = md5('z' . $url . $method . serialize($options) . serialize($params));
|
||||||
|
$cachedData = apc_fetch($cacheKey);
|
||||||
|
if ($cachedData)
|
||||||
|
{
|
||||||
|
return $cachedData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($options['headers'] && $options['headers'] !== array_values($options['headers'])) // associative array
|
if ($options['headers'] && $options['headers'] !== array_values($options['headers'])) // associative array
|
||||||
{
|
{
|
||||||
throw new DomainException('Headers must not be an associative array. Its a simple array with values of the form "Header: value"');
|
throw new DomainException('Headers must not be an associative array. Its a simple array with values of the form "Header: value"');
|
||||||
|
@ -95,7 +113,6 @@ class Curl
|
||||||
|
|
||||||
if (in_array($method, [static::PUT, static::POST]))
|
if (in_array($method, [static::PUT, static::POST]))
|
||||||
{
|
{
|
||||||
print_r($options['json_data'] ? json_encode($params) : http_build_query($params));
|
|
||||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $options['json_data'] ? json_encode($params) : http_build_query($params));
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $options['json_data'] ? json_encode($params) : http_build_query($params));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +153,16 @@ class Curl
|
||||||
return strlen($h);
|
return strlen($h);
|
||||||
});
|
});
|
||||||
|
|
||||||
$responseContent = curl_exec($ch);
|
$rawResponse = curl_exec($ch);
|
||||||
|
|
||||||
|
if ($options['json_response'])
|
||||||
|
{
|
||||||
|
$responseContent = $rawResponse ? json_decode($rawResponse, true) : [];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$responseContent = $rawResponse;
|
||||||
|
}
|
||||||
|
|
||||||
$statusCode = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
$statusCode = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
|
|
||||||
|
@ -147,7 +173,14 @@ class Curl
|
||||||
|
|
||||||
curl_close($ch);
|
curl_close($ch);
|
||||||
|
|
||||||
return [$statusCode, $headers, $responseContent];
|
$response = [$statusCode, $headers, $responseContent];
|
||||||
|
|
||||||
|
if ($options['cache'])
|
||||||
|
{
|
||||||
|
apc_store($cacheKey, $response, is_numeric($options['cache']) ? $options['cache'] : static::DEFAULT_CACHE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $response;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,5 +5,25 @@
|
||||||
<main>
|
<main>
|
||||||
<div class="content content-light">
|
<div class="content content-light">
|
||||||
<h1>{{roadmap.title}}</h1>
|
<h1>{{roadmap.title}}</h1>
|
||||||
|
<div class="help">
|
||||||
|
The LBRY roadmap pulls in information dynamically from our internal project management system and public
|
||||||
|
<a href="https://github.com/lbryio" class="link-primary">GitHub</a> page.
|
||||||
|
</div>
|
||||||
|
<h2>Scheduled Changes</h2>
|
||||||
|
<?php foreach($tasks as $category => $categoryTasks): ?>
|
||||||
|
<section>
|
||||||
|
<h3><?php echo ucfirst($category) ?></h3>
|
||||||
|
<table class="content full-table">
|
||||||
|
<?php foreach($categoryTasks as $task): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?php echo $task['name'] ?></td>
|
||||||
|
<td style="width: 20%"><?php echo $task['project'] ?></td>
|
||||||
|
<td style="width: 15%"><?php echo $task['due_on'] ?></td>
|
||||||
|
<td style="width: 20%"><?php echo $task['assignee'] ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach ?>
|
||||||
|
</table>
|
||||||
|
</section>
|
||||||
|
<?php endforeach ?>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
|
@ -105,74 +105,79 @@
|
||||||
{
|
{
|
||||||
margin-top: $spacing-vertical;
|
margin-top: $spacing-vertical;
|
||||||
}
|
}
|
||||||
table
|
}
|
||||||
|
.post-content table, table.content
|
||||||
|
{
|
||||||
|
margin-bottom: $spacing-vertical;
|
||||||
|
word-wrap: break-word;
|
||||||
|
max-width: 100%;
|
||||||
|
|
||||||
|
th, td
|
||||||
{
|
{
|
||||||
margin-bottom: $spacing-vertical;
|
padding: $spacing-vertical/2 8px;
|
||||||
word-wrap: break-word;
|
}
|
||||||
max-width: 100%;
|
th
|
||||||
|
{
|
||||||
th, td
|
font-weight: bold;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
td
|
||||||
|
{
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
thead th, > tr:first-child th
|
||||||
|
{
|
||||||
|
vertical-align: bottom;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 0.9em;
|
||||||
|
padding: $spacing-vertical/4+1 8px $spacing-vertical/4-2;
|
||||||
|
text-align: left;
|
||||||
|
border-bottom: 1px solid #e2e2e2;
|
||||||
|
img
|
||||||
{
|
{
|
||||||
padding: $spacing-vertical/2 8px;
|
vertical-align: text-bottom;
|
||||||
}
|
}
|
||||||
th
|
}
|
||||||
|
tr.thead:not(:first-child) th
|
||||||
|
{
|
||||||
|
border-top: 1px solid #e2e2e2;
|
||||||
|
}
|
||||||
|
tfoot td
|
||||||
|
{
|
||||||
|
padding: $spacing-vertical / 2 8px;
|
||||||
|
font-size: .85em;
|
||||||
|
}
|
||||||
|
tbody
|
||||||
|
{
|
||||||
|
tr
|
||||||
{
|
{
|
||||||
font-weight: bold;
|
&:nth-child(even):not(.odd)
|
||||||
font-size: 0.9em;
|
|
||||||
}
|
|
||||||
td
|
|
||||||
{
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
thead th, > tr:first-child th
|
|
||||||
{
|
|
||||||
vertical-align: bottom;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 0.9em;
|
|
||||||
padding: $spacing-vertical/4+1 8px $spacing-vertical/4-2;
|
|
||||||
text-align: left;
|
|
||||||
border-bottom: 1px solid #e2e2e2;
|
|
||||||
img
|
|
||||||
{
|
{
|
||||||
vertical-align: text-bottom;
|
background-color: #f4f4f4;
|
||||||
}
|
}
|
||||||
}
|
&:nth-child(odd):not(.even)
|
||||||
tr.thead:not(:first-child) th
|
{
|
||||||
{
|
background-color: white;
|
||||||
border-top: 1px solid #e2e2e2;
|
}
|
||||||
}
|
&.thead
|
||||||
tfoot td
|
{
|
||||||
{
|
background: none;
|
||||||
padding: $spacing-vertical / 2 8px;
|
}
|
||||||
font-size: .85em;
|
td
|
||||||
}
|
{
|
||||||
tbody
|
border: 0 none;
|
||||||
{
|
|
||||||
tr
|
|
||||||
{
|
|
||||||
&:nth-child(even):not(.odd)
|
|
||||||
{
|
|
||||||
background-color: #f4f4f4;
|
|
||||||
}
|
|
||||||
&:nth-child(odd):not(.even)
|
|
||||||
{
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
&.thead
|
|
||||||
{
|
|
||||||
background: none;
|
|
||||||
}
|
|
||||||
td
|
|
||||||
{
|
|
||||||
border: 0 none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&:last-child
|
&:last-child
|
||||||
{
|
{
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.full-table
|
||||||
|
{
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue