diff --git a/cli/clickup-folders.php b/cli/clickup-folders.php
index cbab27a..8c58093 100755
--- a/cli/clickup-folders.php
+++ b/cli/clickup-folders.php
@@ -1,90 +1,109 @@
#!/usr/bin/php
ClickUp bot
# Copyright (C) 2023 Valerio Bozzolan, contributors
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
/**
* Get ClickUp folders
*/
// autoload libraries
require __DIR__ . '/../autoload.php';
+// ask data
+$populate = true;
+
$cache = ClickUpPhabricatorCache::instance();
// import all ClickUp Folders from all Spaces
$clickup_spaces = ClickUpAPI::getSpaces();
foreach( $clickup_spaces as $space ) {
// $space->id
// $space->name
// save each folder in the cache
$cache->lock();
$folders = ClickUpAPI::getSpaceFolders( $space->id );
foreach( $folders as $folder ) {
// $folder->id
// $folder->name
$cache->importClickupFolder( $folder );
}
$cache->save();
}
// loop cached folders
foreach( $cache->getClickUpFolders() as $folder ) {
$phab_tag_id = $cache->getPhabricatorTagIDFromClickupFolderID( $folder->id );
$phab_tag_phid = $cache->getPhabricatorTagPHIDFromClickupFolderID( $folder->id );
- if( $phab_tag_id ) {
+
+ if( !$phab_tag_id && $populate ) {
+ $phab_tag_id = readline( "Specify the Phabricator Tag name for {$folder->name} (example: pippo_pluto): " );
+ }
+
+ if( $phab_tag_id && !$phab_tag_phid ) {
// find fresh project from its slug
$phab_project = PhabricatorAPI::querySingle( 'project.search', [
'constraints' => [
'slugs' => [ $phab_tag_id, ]
],
] );
- // associate the ClickUp folder to the Phabricator Tag PHID
- $cache
- ->lock()
- ->associateClickupFolderIDPhabricatorPHID( $folder->id, $phab_project['phid'] )
- ->save();
-
- /*
- // find columns from this project
- $phab_columns = PhabricatorAPI::query( 'project.column.search', [
- 'constraints' => [
- 'projects' => [ $phab_project['phid'] ],
- ],
- ] );
-
- $cache->lock();
- foreach( $phab_columns['data'] as $phab_column ) {
- $cache->associateClickupFolderIDPhabricatorColumnPHID( $folder->id, $phab_column['phid'] );
+ if( $phab_project ) {
+
+ // associate the ClickUp folder to the Phabricator Tag PHID
+ $cache
+ ->lock()
+ ->associateClickupFolderIDPhabricatorID( $folder->id, $phab_project['fields']['slug'] )
+ ->associateClickupFolderIDPhabricatorPHID( $folder->id, $phab_project['phid'] )
+ ->save();
+
+ /*
+ // find columns from this project
+ $phab_columns = PhabricatorAPI::query( 'project.column.search', [
+ 'constraints' => [
+ 'projects' => [ $phab_project['phid'] ],
+ ],
+ ] );
+
+ $cache->lock();
+ foreach( $phab_columns['data'] as $phab_column ) {
+ $cache->associateClickupFolderIDPhabricatorColumnPHID( $folder->id, $phab_column['phid'] );
+ }
+ $cache->save();
+ */
}
- $cache->save();
- */
}
+}
+
+// loop cached folders
+foreach( $cache->getClickUpFolders() as $folder ) {
+
+ $phab_tag_id = $cache->getPhabricatorTagIDFromClickupFolderID( $folder->id );
+ $phab_tag_phid = $cache->getPhabricatorTagPHIDFromClickupFolderID( $folder->id );
$phab_tag_id_msg = $phab_tag_id
? "HAS Phab ID"
: "MISSING Phab ID";
// print something nice to see
echo $folder->id . "\t|" . $phab_tag_id_msg . "\t|" . $folder->name . "\n";
}
diff --git a/cli/clickup-users.php b/cli/clickup-users.php
index 3183847..bc63402 100755
--- a/cli/clickup-users.php
+++ b/cli/clickup-users.php
@@ -1,47 +1,86 @@
#!/usr/bin/php
ClickUp bot
# Copyright (C) 2023 Valerio Bozzolan, contributors
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
/**
* Get ClickUp users
*/
// autoload libraries
require __DIR__ . '/../autoload.php';
$cache = ClickUpPhabricatorCache::instance();
-$max = 5;
-$i = 0;
+$populate = true;
-$clickup_users = $cache->getClickUpUsers();
-foreach( $clickup_users as $clickup_user ) {
+if( $populate ) {
+ foreach( $cache->getIterableClickupTasks() as $clickup_task ) {
+
+ $clickup_task_details = ClickUpAPI::queryTaskData( $clickup_task->id );
+ if( $clickup_task_details ) {
+ echo "Import users from ClickUp Task {$clickup_task->id}\n";
+ }
+
+ sleep( 1 );
+ }
}
-$clickup_tasks = $cache->getAllClickupTasks();
-foreach( $clickup_tasks as $clickup_task_id => $clickup_task ) {
+foreach( $cache->getIterableClickupUsers() as $clickup_user ) {
+
+ $clickup_user_id = $clickup_user->id;
+ $phab_username = $cache->getClickUpUserPhabUsernameByID( $clickup_user_id );
+ $phab_phid = $cache->getClickUpUserPHIDByID( $clickup_user_id );
+
+ if( !$phab_username ) {
+ $phab_username = readline("# Type Phabricator nickname of user {$clickup_user->username} (example: ciccio.franco): ");
+ }
+
+ if( !$phab_phid && $phab_username ) {
+ $phab_user = PhabricatorAPI::getUserByUsername( $phab_username );
+ if( $phab_user ) {
+
+ $phab_phid = $phab_user['phid'];
+ $phab_username = $phab_user['fields']['username'];
+
+ $cache
+ ->lock()
+ ->setClickUpUserPhabUsernameByID( $clickup_user_id, $phab_username )
+ ->setClickUpUserPHIDByID( $clickup_user_id, $phab_phid )
+ ->save();
- $clickup_task_details = ClickUpAPI::queryTaskData( $clickup_task_id );
- if( $clickup_task_details ) {
- print_r( $clickup_task_details->creator );
- print_r( $clickup_task_details->assignees );
- print_r( $clickup_task_details->watchers );
- exit;
+ echo "# Saved\n\n";
+ } else {
+ echo "# Not found\n\n";
+ }
}
+}
+
+foreach( $cache->getIterableClickupUsers() as $clickup_user ) {
+
+ $clickup_user_id = $clickup_user->id;
+ $phab_username = $cache->getClickUpUserPhabUsernameByID( $clickup_user_id );
+ $phab_phid = $cache->getClickUpUserPHIDByID( $clickup_user_id );
- sleep( 1 );
+ echo $clickup_user->id;
+ echo "\t|";
+ echo $clickup_user->username;
+ echo "\t|";
+ echo $phab_username
+ ? 'id CONNECTED TO PHAB'
+ : 'id NOT CONNECTED TO PHAB';
+ echo "\n";
}
diff --git a/include/class-PhabricatorAPI.php b/include/class-PhabricatorAPI.php
index 74c7777..5f63469 100644
--- a/include/class-PhabricatorAPI.php
+++ b/include/class-PhabricatorAPI.php
@@ -1,210 +1,228 @@
ClickUp bot
# Copyright (C) 2023 Valerio Bozzolan, contributors
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
/**
* Utility to run HTTP queries against Phabricator / Phorge
*/
class PhabricatorAPI {
public static function query( $entry_point, $query = [] ) {
$client = new ConduitClient( PHABRICATOR_URL );
$client->setConduitToken( PHABRICATOR_CONDUIT_API_TOKEN );
return $client->callMethodSynchronous( $entry_point, $query );
}
/**
* Simplified query to the maniphest.edit Conduit Phabricator API
*
* https://sviluppo.erinformatica.it/conduit/method/maniphest.edit/
*
* @param $transaction_values array Example: [ 'title' => 'ASD' ]
* @param $extra_query array Example: ['objectIdentifier' => 'PHID--...'] to edit
* @return mixed
*/
public static function createTask( $transaction_values = [], $query = [] ) {
// build transactions
$query['transactions'] = [];
foreach( $transaction_values as $key => $value ) {
$query['transactions'][] = self::transaction( $key, $value );
}
return self::query( 'maniphest.edit', $query );
}
/**
* Simplified query to the maniphest.edit Conduit Phabricator API
*
* https://sviluppo.erinformatica.it/conduit/method/maniphest.edit/
*
* @param $id string Task ID (e.g. 123 for T123)
* @param $transaction_values array Example: [ 'title' => 'ASD' ]
* @return mixed
*/
public static function editTask( $id, $transaction_values = [] ) {
return self::createTask( $transaction_values, [
'objectIdentifier' => $id,
] );
}
/**
* Check if a Phabricator status is equivalent to "closed"
*
* @return self
*/
public static function isStatusClosed( $task_status ) {
// TODO: read from "maniphest.status.search" and set in cache and read from there
$closed_statuses = [
'resolved',
'wontfix',
'invalid',
'duplicate',
'spite',
];
return in_array( $task_status, $closed_statuses, true );
}
/**
* Convert a Phabricator status to a Clickup status
*
* @return "closed" or "open"
*/
public static function status2clickup( $task_status ) {
$is_closed = self::isStatusClosed( $task_status );
if( $is_closed ) {
return 'closed';
}
return 'open';
}
/**
* Get a Task by its ID
*
* It returns just one element.
*
* https://sviluppo.erinformatica.it/conduit/method/maniphest.search/
*
* @param $task_id mixed
*/
public static function getTask( $task_id ) {
$task_id = self::sanitize_task_id( $task_id );
$query = [
'constraints' => [
'ids' => [ $task_id ],
],
'attachments' => [
'columns' => true,
'projects' => true,
],
];
return self::searchSingleTask( $query );
}
+ public static function getUserByPHID( $phid ) {
+ $query = [
+ 'constraints' => [
+ 'phids' => [ $phid ],
+ ],
+ ];
+ return self::querySingle( 'user.search', $query );
+ }
+
+ public static function getUserByUsername( $username ) {
+ $query = [
+ 'constraints' => [
+ 'usernames' => [ $username ],
+ ],
+ ];
+ return self::querySingle( 'user.search', $query );
+ }
+
public static function getTaskByPHID( $phid ) {
$query = [
'constraints' => [
'phids' => [ $phid ],
],
'attachments' => [
'columns' => true,
'projects' => true,
],
];
return self::searchSingleTask( $query );
}
public static function searchSingleUserByPHID( $phid ) {
$query = [
'constraints' => [
'phids' => [ $phid ],
],
];
return self::searchSingleUser( $query );
}
public static function searchSingleTask( $query ) {
return self::querySingle( 'maniphest.search', $query );
}
public static function searchSingleUser( $query ) {
return self::querySingle( 'user.search', $query );
}
public static function querySingle( $method, $query ) {
$results = self::query( $method, $query );
// just the first one is OK
foreach( $results['data'] as $entry ) {
return $entry;
}
throw new Exception( "Phabricator result not found from $method using: " . json_encode( $query ) );
}
public static function searchObjectTransactionsFromTransactions( $phab_object_id, $transactions ) {
$transaction_phids = [];
foreach( $transactions as $transaction ) {
$transaction_phids[] = $transaction['phid'];
}
return self::searchObjectTransactionsFromPHIDs( $phab_object_id, $transaction_phids );
}
public static function searchObjectTransactionsFromPHIDs( $phab_object_id, $transaction_phids ) {
$query = [
'objectIdentifier' => $phab_object_id,
'constraints' => [
'phids' => $transaction_phids,
],
];
$results = self::query( 'transaction.search', $query );
return $results['data'];
}
private static function transaction( $type, $value ) {
return [
'type' => $type,
'value' => $value,
];
}
/**
* Sanitize a Task ID
*
* @param $task_id mixed
* @return int
*/
public static function sanitize_task_id( $task_id ) {
// strip the damn 'T' since the 'id' API only accepts numeric
$task_id = ltrim( $task_id, 'T' );
// no numeric no party
$task_id = (int)$task_id;
if( !$task_id ) {
throw new Exception( "invalid Task ID" );
}
return $task_id;
}
}