PhabricatorObjectHandle.php 9.66 KB
Newer Older
epriestley's avatar
epriestley committed
1 2
<?php

3
final class PhabricatorObjectHandle
Joshua Spence's avatar
Joshua Spence committed
4
  extends Phobject
5
  implements PhabricatorPolicyInterface {
epriestley's avatar
epriestley committed
6

7 8 9 10 11 12 13 14
  const AVAILABILITY_FULL = 'full';
  const AVAILABILITY_NONE = 'none';
  const AVAILABILITY_PARTIAL = 'partial';
  const AVAILABILITY_DISABLED = 'disabled';

  const STATUS_OPEN = 'open';
  const STATUS_CLOSED = 'closed';

epriestley's avatar
epriestley committed
15 16 17 18
  private $uri;
  private $phid;
  private $type;
  private $name;
19
  private $fullName;
20
  private $title;
epriestley's avatar
epriestley committed
21
  private $imageURI;
22
  private $icon;
23
  private $tagColor;
24
  private $timestamp;
25 26
  private $status = self::STATUS_OPEN;
  private $availability = self::AVAILABILITY_FULL;
27
  private $complete;
28
  private $objectName;
29
  private $policyFiltered;
epriestley's avatar
epriestley committed
30
  private $subtitle;
31
  private $tokenIcon;
32
  private $commandLineObjectName;
33

34 35 36 37
  private $stateIcon;
  private $stateColor;
  private $stateName;

38 39 40 41 42 43
  public function setIcon($icon) {
    $this->icon = $icon;
    return $this;
  }

  public function getIcon() {
44 45 46 47
    if ($this->getPolicyFiltered()) {
      return 'fa-lock';
    }

48 49 50 51 52 53
    if ($this->icon) {
      return $this->icon;
    }
    return $this->getTypeIcon();
  }

epriestley's avatar
epriestley committed
54 55 56 57 58 59 60 61 62
  public function setSubtitle($subtitle) {
    $this->subtitle = $subtitle;
    return $this;
  }

  public function getSubtitle() {
    return $this->subtitle;
  }

63 64 65 66 67 68 69 70 71 72 73 74 75 76
  public function setTagColor($color) {
    static $colors;
    if (!$colors) {
      $colors = array_fuse(array_keys(PHUITagView::getShadeMap()));
    }

    if (isset($colors[$color])) {
      $this->tagColor = $color;
    }

    return $this;
  }

  public function getTagColor() {
77 78 79 80
    if ($this->getPolicyFiltered()) {
      return 'disabled';
    }

81 82 83
    if ($this->tagColor) {
      return $this->tagColor;
    }
84

85
    return 'blue';
86 87
  }

88 89 90 91 92 93 94
  public function getIconColor() {
    if ($this->tagColor) {
      return $this->tagColor;
    }
    return null;
  }

95 96 97 98 99 100 101 102 103 104 105 106 107
  public function setTokenIcon($icon) {
    $this->tokenIcon = $icon;
    return $this;
  }

  public function getTokenIcon() {
    if ($this->tokenIcon !== null) {
      return $this->tokenIcon;
    }

    return $this->getIcon();
  }

108 109 110 111 112 113 114
  public function getTypeIcon() {
    if ($this->getPHIDType()) {
      return $this->getPHIDType()->getTypeIcon();
    }
    return null;
  }

115 116 117 118 119 120 121 122
  public function setPolicyFiltered($policy_filered) {
    $this->policyFiltered = $policy_filered;
    return $this;
  }

  public function getPolicyFiltered() {
    return $this->policyFiltered;
  }
123 124 125 126 127 128 129 130 131 132 133 134

  public function setObjectName($object_name) {
    $this->objectName = $object_name;
    return $this;
  }

  public function getObjectName() {
    if (!$this->objectName) {
      return $this->getName();
    }
    return $this->objectName;
  }
epriestley's avatar
epriestley committed
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159

  public function setURI($uri) {
    $this->uri = $uri;
    return $this;
  }

  public function getURI() {
    return $this->uri;
  }

  public function setPHID($phid) {
    $this->phid = $phid;
    return $this;
  }

  public function getPHID() {
    return $this->phid;
  }

  public function setName($name) {
    $this->name = $name;
    return $this;
  }

  public function getName() {
160
    if ($this->name === null) {
161 162 163 164 165
      if ($this->getPolicyFiltered()) {
        return pht('Restricted %s', $this->getTypeName());
      } else {
        return pht('Unknown Object (%s)', $this->getTypeName());
      }
166
    }
epriestley's avatar
epriestley committed
167 168 169
    return $this->name;
  }

170 171 172 173 174 175 176 177 178 179 180 181 182
  public function setAvailability($availability) {
    $this->availability = $availability;
    return $this;
  }

  public function getAvailability() {
    return $this->availability;
  }

  public function isDisabled() {
    return ($this->getAvailability() == self::AVAILABILITY_DISABLED);
  }

epriestley's avatar
epriestley committed
183 184 185 186 187 188 189 190 191
  public function setStatus($status) {
    $this->status = $status;
    return $this;
  }

  public function getStatus() {
    return $this->status;
  }

192 193 194 195
  public function setFullName($full_name) {
    $this->fullName = $full_name;
    return $this;
  }
epriestley's avatar
epriestley committed
196

197
  public function getFullName() {
198 199 200 201
    if ($this->fullName !== null) {
      return $this->fullName;
    }
    return $this->getName();
202
  }
203

204 205 206 207 208 209 210 211 212 213 214 215 216
  public function setCommandLineObjectName($command_line_object_name) {
    $this->commandLineObjectName = $command_line_object_name;
    return $this;
  }

  public function getCommandLineObjectName() {
    if ($this->commandLineObjectName !== null) {
      return $this->commandLineObjectName;
    }

    return $this->getObjectName();
  }

217 218 219 220
  public function setTitle($title) {
    $this->title = $title;
    return $this;
  }
221

222 223 224
  public function getTitle() {
    return $this->title;
  }
225

epriestley's avatar
epriestley committed
226 227 228 229 230 231 232 233 234
  public function setType($type) {
    $this->type = $type;
    return $this;
  }

  public function getType() {
    return $this->type;
  }

epriestley's avatar
epriestley committed
235 236 237 238
  public function setImageURI($uri) {
    $this->imageURI = $uri;
    return $this;
  }
epriestley's avatar
epriestley committed
239

epriestley's avatar
epriestley committed
240 241 242
  public function getImageURI() {
    return $this->imageURI;
  }
epriestley's avatar
epriestley committed
243

244 245 246 247 248 249 250 251 252
  public function setTimestamp($timestamp) {
    $this->timestamp = $timestamp;
    return $this;
  }

  public function getTimestamp() {
    return $this->timestamp;
  }

epriestley's avatar
epriestley committed
253
  public function getTypeName() {
254 255
    if ($this->getPHIDType()) {
      return $this->getPHIDType()->getTypeName();
256 257
    }

258
    return $this->getType();
epriestley's avatar
epriestley committed
259 260
  }

261 262 263

  /**
   * Set whether or not the underlying object is complete. See
vrana's avatar
vrana committed
264
   * @{method:isComplete} for an explanation of what it means to be complete.
265 266 267 268
   *
   * @param bool True if the handle represents a complete object.
   * @return this
   */
269 270 271 272 273
  public function setComplete($complete) {
    $this->complete = $complete;
    return $this;
  }

274

275 276 277 278 279 280
  /**
   * Determine if the handle represents an object which was completely loaded
   * (i.e., the underlying object exists) vs an object which could not be
   * completely loaded (e.g., the type or data for the PHID could not be
   * identified or located).
   *
Bob Trahan's avatar
Bob Trahan committed
281
   * Basically, @{class:PhabricatorHandleQuery} gives you back a handle for
282 283 284 285 286 287 288 289 290
   * any PHID you give it, but it gives you a complete handle only for valid
   * PHIDs.
   *
   * @return bool True if the handle represents a complete object.
   */
  public function isComplete() {
    return $this->complete;
  }

291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
  public function setStateIcon($state_icon) {
    $this->stateIcon = $state_icon;
    return $this;
  }

  public function getStateIcon() {
    return $this->stateIcon;
  }

  public function setStateColor($state_color) {
    $this->stateColor = $state_color;
    return $this;
  }

  public function getStateColor() {
    return $this->stateColor;
  }

  public function setStateName($state_name) {
    $this->stateName = $state_name;
    return $this;
  }

  public function getStateName() {
    return $this->stateName;
  }

  public function renderStateIcon() {
    $icon = $this->getStateIcon();
    if ($icon === null) {
      $icon = 'fa-question-circle-o';
    }

    $color = $this->getStateColor();

    $name = $this->getStateName();
    if ($name === null) {
      $name = pht('Unknown');
    }

    return id(new PHUIIconView())
      ->setIcon($icon, $color)
      ->addSigil('has-tooltip')
      ->setMetadata(
        array(
          'tip' => $name,
        ));
  }
339

340
  public function renderLink($name = null) {
341 342 343 344
    return $this->renderLinkWithAttributes($name, array());
  }

  public function renderHovercardLink($name = null) {
345
    Javelin::initBehavior('phui-hovercards');
346 347 348 349 350 351 352 353 354 355 356 357

    $attributes = array(
      'sigil' => 'hovercard',
      'meta' => array(
        'hoverPHID' => $this->getPHID(),
      ),
    );

    return $this->renderLinkWithAttributes($name, $attributes);
  }

  private function renderLinkWithAttributes($name, array $attributes) {
358 359 360
    if ($name === null) {
      $name = $this->getLinkName();
    }
361
    $classes = array();
362
    $classes[] = 'phui-handle';
363
    $title = $this->title;
364

365
    if ($this->status != self::STATUS_OPEN) {
366
      $classes[] = 'handle-status-'.$this->status;
367 368
    }

369
    $circle = null;
370 371
    if ($this->availability != self::AVAILABILITY_FULL) {
      $classes[] = 'handle-availability-'.$this->availability;
372 373 374 375 376 377 378 379 380
      $circle = array(
        phutil_tag(
          'span',
          array(
            'class' => 'perfect-circle',
          ),
          "\xE2\x80\xA2"),
        ' ',
      );
epriestley's avatar
epriestley committed
381 382
    }

Joshua Spence's avatar
Joshua Spence committed
383
    if ($this->getType() == PhabricatorPeopleUserPHIDType::TYPECONST) {
384 385 386
      $classes[] = 'phui-link-person';
    }

387 388 389 390 391
    $uri = $this->getURI();

    $icon = null;
    if ($this->getPolicyFiltered()) {
      $icon = id(new PHUIIconView())
392
        ->setIcon('fa-lock lightgreytext');
393 394
    }

395 396 397 398 399 400 401
    $attributes = $attributes + array(
      'href'  => $uri,
      'class' => implode(' ', $classes),
      'title' => $title,
    );

    return javelin_tag(
402
      $uri ? 'a' : 'span',
403
      $attributes,
404
      array($circle, $icon, $name));
epriestley's avatar
epriestley committed
405
  }
epriestley's avatar
epriestley committed
406

407 408 409
  public function renderTag() {
    return id(new PHUITagView())
      ->setType(PHUITagView::TYPE_OBJECT)
410 411
      ->setShade($this->getTagColor())
      ->setIcon($this->getIcon())
412 413 414 415
      ->setHref($this->getURI())
      ->setName($this->getLinkName());
  }

416 417
  public function getLinkName() {
    switch ($this->getType()) {
Joshua Spence's avatar
Joshua Spence committed
418
      case PhabricatorPeopleUserPHIDType::TYPECONST:
419 420 421 422
        $name = $this->getName();
        break;
      default:
        $name = $this->getFullName();
423
        break;
424 425 426 427
    }
    return $name;
  }

428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
  protected function getPHIDType() {
    $types = PhabricatorPHIDType::getAllTypes();
    return idx($types, $this->getType());
  }


/* -(  PhabricatorPolicyInterface  )----------------------------------------- */


  public function getCapabilities() {
    return array(
      PhabricatorPolicyCapability::CAN_VIEW,
    );
  }

  public function getPolicy($capability) {
    return PhabricatorPolicies::POLICY_PUBLIC;
  }

  public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
448 449 450
    // NOTE: Handles are always visible, they just don't get populated with
    // data if the user can't see the underlying object.
    return true;
451 452
  }

453 454 455 456
  public function describeAutomaticCapability($capability) {
    return null;
  }

epriestley's avatar
epriestley committed
457
}