[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 final class DoorkeeperBridgeAsana extends DoorkeeperBridge { 4 5 const APPTYPE_ASANA = 'asana'; 6 const APPDOMAIN_ASANA = 'asana.com'; 7 const OBJTYPE_TASK = 'asana:task'; 8 9 public function canPullRef(DoorkeeperObjectRef $ref) { 10 if ($ref->getApplicationType() != self::APPTYPE_ASANA) { 11 return false; 12 } 13 14 if ($ref->getApplicationDomain() != self::APPDOMAIN_ASANA) { 15 return false; 16 } 17 18 $types = array( 19 self::OBJTYPE_TASK => true, 20 ); 21 22 return isset($types[$ref->getObjectType()]); 23 } 24 25 public function pullRefs(array $refs) { 26 27 $id_map = mpull($refs, 'getObjectID', 'getObjectKey'); 28 $viewer = $this->getViewer(); 29 30 $provider = PhabricatorAsanaAuthProvider::getAsanaProvider(); 31 if (!$provider) { 32 return; 33 } 34 35 $accounts = id(new PhabricatorExternalAccountQuery()) 36 ->setViewer($viewer) 37 ->withUserPHIDs(array($viewer->getPHID())) 38 ->withAccountTypes(array($provider->getProviderType())) 39 ->withAccountDomains(array($provider->getProviderDomain())) 40 ->requireCapabilities( 41 array( 42 PhabricatorPolicyCapability::CAN_VIEW, 43 PhabricatorPolicyCapability::CAN_EDIT, 44 )) 45 ->execute(); 46 47 if (!$accounts) { 48 return $this->didFailOnMissingLink(); 49 } 50 51 // TODO: If the user has several linked Asana accounts, we just pick the 52 // first one arbitrarily. We might want to try using all of them or do 53 // something with more finesse. There's no UI way to link multiple accounts 54 // right now so this is currently moot. 55 $account = head($accounts); 56 57 $token = $provider->getOAuthAccessToken($account); 58 if (!$token) { 59 return; 60 } 61 62 $template = id(new PhutilAsanaFuture()) 63 ->setAccessToken($token); 64 65 $futures = array(); 66 foreach ($id_map as $key => $id) { 67 $futures[$key] = id(clone $template) 68 ->setRawAsanaQuery("tasks/{$id}"); 69 } 70 71 $results = array(); 72 $failed = array(); 73 foreach (Futures($futures) as $key => $future) { 74 try { 75 $results[$key] = $future->resolve(); 76 } catch (Exception $ex) { 77 if (($ex instanceof HTTPFutureResponseStatus) && 78 ($ex->getStatusCode() == 404)) { 79 // This indicates that the object has been deleted (or never existed, 80 // or isn't visible to the current user) but it's a successful sync of 81 // an object which isn't visible. 82 } else { 83 // This is something else, so consider it a synchronization failure. 84 phlog($ex); 85 $failed[$key] = $ex; 86 } 87 } 88 } 89 90 foreach ($refs as $ref) { 91 $ref->setAttribute('name', pht('Asana Task %s', $ref->getObjectID())); 92 93 $did_fail = idx($failed, $ref->getObjectKey()); 94 if ($did_fail) { 95 $ref->setSyncFailed(true); 96 continue; 97 } 98 99 $result = idx($results, $ref->getObjectKey()); 100 if (!$result) { 101 continue; 102 } 103 104 $ref->setIsVisible(true); 105 $ref->setAttribute('asana.data', $result); 106 $ref->setAttribute('fullname', pht('Asana: %s', $result['name'])); 107 $ref->setAttribute('title', $result['name']); 108 $ref->setAttribute('description', $result['notes']); 109 110 $obj = $ref->getExternalObject(); 111 if ($obj->getID()) { 112 continue; 113 } 114 115 $this->fillObjectFromData($obj, $result); 116 117 $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); 118 $obj->save(); 119 unset($unguarded); 120 } 121 } 122 123 public function fillObjectFromData(DoorkeeperExternalObject $obj, $result) { 124 $id = $result['id']; 125 $uri = "https://app.asana.com/0/{$id}/{$id}"; 126 $obj->setObjectURI($uri); 127 } 128 129 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |