~ubuntu-branches/ubuntu/wily/phabricator/wily

« back to all changes in this revision

Viewing changes to src/workflow/ArcanistFlagWorkflow.php

  • Committer: Package Import Robot
  • Author(s): Richard Sellam
  • Date: 2014-11-01 23:20:06 UTC
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: package-import@ubuntu.com-20141101232006-mvlnp0cil67tsboe
Tags: upstream-0~git20141101/arcanist
Import upstream version 0~git20141101, component arcanist

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
 
 
3
final class ArcanistFlagWorkflow extends ArcanistWorkflow {
 
4
 
 
5
  private static $colorMap = array(
 
6
    0 => 'red',     // Red
 
7
    1 => 'yellow',  // Orange
 
8
    2 => 'yellow',  // Yellow
 
9
    3 => 'green',   // Green
 
10
    4 => 'blue',    // Blue
 
11
    5 => 'magenta', // Pink
 
12
    6 => 'magenta', // Purple
 
13
    7 => 'default', // Checkered
 
14
  );
 
15
 
 
16
  private static $colorSpec = array(
 
17
    'red' => 0,       'r' => 0,   0 => 0,
 
18
    'orange' => 1,    'o' => 1,   1 => 1,
 
19
    'yellow' => 2,    'y' => 2,   2 => 2,
 
20
    'green' => 3,     'g' => 3,   3 => 3,
 
21
    'blue' => 4,      'b' => 4,   4 => 4,
 
22
    'pink' => 5,      'p' => 5,   5 => 5,
 
23
    'purple' => 6,    'v' => 6,   6 => 6,
 
24
    'checkered' => 7, 'c' => 7,   7 => 7,
 
25
  );
 
26
 
 
27
  public function getWorkflowName() {
 
28
    return 'flag';
 
29
  }
 
30
 
 
31
  public function getCommandSynopses() {
 
32
    return phutil_console_format(<<<EOTEXT
 
33
      **flag** [__object__ ...]
 
34
      **flag** __object__ --clear
 
35
      **flag** __object__ [--edit] [--color __color__] [--note __note__]
 
36
EOTEXT
 
37
      );
 
38
  }
 
39
 
 
40
  public function getCommandHelp() {
 
41
    return phutil_console_format(<<<EOTEXT
 
42
          In the first form, list objects you've flagged. You can provide the
 
43
          names of one or more objects (Maniphest tasks T#\##, Differential
 
44
          revisions D###, Diffusion references rXXX???, or PHIDs PHID-XXX-???)
 
45
          to print only flags for those objects.
 
46
 
 
47
          In the second form, clear an existing flag on one object.
 
48
 
 
49
          In the third form, create or update a flag on one object. Color
 
50
          defaults to blue and note to empty, but if you omit both you must
 
51
          pass --edit.
 
52
EOTEXT
 
53
      );
 
54
  }
 
55
 
 
56
  public function getArguments() {
 
57
    return array(
 
58
      '*' => 'objects',
 
59
      'clear' => array(
 
60
        'help' => 'Delete the flag on an object.',
 
61
      ),
 
62
      'edit' => array(
 
63
        'help' => 'Edit the flag on an object.',
 
64
      ),
 
65
      'color' => array(
 
66
        'param' => 'color',
 
67
        'help' => 'Set the color of a flag.',
 
68
      ),
 
69
      'note' => array(
 
70
        'param' => 'note',
 
71
        'help' => 'Set the note on a flag.',
 
72
      ),
 
73
    );
 
74
  }
 
75
 
 
76
  public function requiresConduit() {
 
77
    return true;
 
78
  }
 
79
 
 
80
  public function requiresAuthentication() {
 
81
    return true;
 
82
  }
 
83
 
 
84
  private static function flagWasEdited($flag, $verb) {
 
85
    $color = idx(self::$colorMap, $flag['color'], 'cyan');
 
86
    $note = $flag['note'];
 
87
    if ($note) {
 
88
      // Make sure notes that are long or have line breaks in them or
 
89
      // whatever don't mess up the formatting.
 
90
      $note = implode(' ', preg_split('/\s+/', $note));
 
91
      $note = ' ('.
 
92
        id(new PhutilUTF8StringTruncator())
 
93
        ->setMaximumGlyphs(40)
 
94
        ->setTerminator('...')
 
95
        ->truncateString($note).
 
96
        ')';
 
97
    }
 
98
    echo phutil_console_format(
 
99
      "<fg:{$color}>%s</fg> flag%s $verb!\n",
 
100
      $flag['colorName'],
 
101
      $note);
 
102
  }
 
103
 
 
104
  public function run() {
 
105
    $conduit = $this->getConduit();
 
106
    $objects = $this->getArgument('objects', array());
 
107
    $phids = array();
 
108
 
 
109
    $clear = $this->getArgument('clear');
 
110
    $edit = $this->getArgument('edit');
 
111
    // I don't trust PHP to distinguish 0 (red) from null.
 
112
    $color = $this->getArgument('color', -1);
 
113
    $note = $this->getArgument('note');
 
114
    $editing = $edit || ($color != -1) || $note;
 
115
 
 
116
    if ($editing && $clear) {
 
117
      throw new ArcanistUsageException("You can't both edit and clear a flag.");
 
118
    }
 
119
    if (($editing || $clear) && count($objects) != 1) {
 
120
      throw new ArcanistUsageException('Specify exactly one object.');
 
121
    }
 
122
 
 
123
    if (!empty($objects)) {
 
124
      // First off, convert the passed objects to PHIDs.
 
125
      $handles = $conduit->callMethodSynchronous(
 
126
        'phid.lookup',
 
127
        array(
 
128
          'names' => $objects,
 
129
        ));
 
130
      foreach ($objects as $object) {
 
131
        if (isset($handles[$object])) {
 
132
          $phids[$object] = $handles[$object]['phid'];
 
133
        } else {
 
134
          echo phutil_console_format("**%s** doesn't exist.\n", $object);
 
135
        }
 
136
      }
 
137
      if (empty($phids)) {
 
138
        // flag.query treats an empty objectPHIDs parameter as "don't use this
 
139
        // constraint". However, if the user gives a list of objects but none
 
140
        // of them exist and have flags, we shouldn't dump the full list on
 
141
        // them after telling them that. Conveniently, we already told them,
 
142
        // so we can go quit now.
 
143
        return 0;
 
144
      }
 
145
    }
 
146
 
 
147
    if ($clear) {
 
148
      // All right, we're going to clear a flag. First clear it. Then tell the
 
149
      // user we cleared it. Step four: profit!
 
150
      $flag = $conduit->callMethodSynchronous(
 
151
        'flag.delete',
 
152
        array(
 
153
          'objectPHID' => head($phids),
 
154
        ));
 
155
      if (!$flag) {
 
156
        echo phutil_console_format("**%s** has no flag to clear.\n", $object);
 
157
      } else {
 
158
        self::flagWasEdited($flag, 'deleted');
 
159
      }
 
160
    } else if ($editing) {
 
161
      // Let's set some flags. Just like Minesweeper, but less distracting.
 
162
      $flag_params = array(
 
163
        'objectPHID' => head($phids),
 
164
      );
 
165
      if (isset(self::$colorSpec[$color])) {
 
166
        $flag_params['color'] = self::$colorSpec[strtolower($color)];
 
167
      }
 
168
      if ($note) {
 
169
        $flag_params['note'] = $note;
 
170
      }
 
171
      $flag = $conduit->callMethodSynchronous(
 
172
        'flag.edit',
 
173
        $flag_params);
 
174
      self::flagWasEdited($flag, $flag['new'] ? 'created' : 'edited');
 
175
    } else {
 
176
      // Okay, list mode. Let's find the flags, which we didn't need to do
 
177
      // otherwise because Conduit does it for us.
 
178
      $flags = ipull(
 
179
        $this->getConduit()->callMethodSynchronous(
 
180
          'flag.query',
 
181
          array(
 
182
            'ownerPHIDs' => array($this->getUserPHID()),
 
183
            'objectPHIDs' => array_values($phids),
 
184
          )),
 
185
        null,
 
186
        'objectPHID');
 
187
      foreach ($phids as $object => $phid) {
 
188
        if (!isset($flags[$phid])) {
 
189
          echo phutil_console_format("**%s** has no flag.\n", $object);
 
190
        }
 
191
      }
 
192
 
 
193
      if (empty($flags)) {
 
194
        // If the user passed no object names, then we should print the full
 
195
        // list, but it's empty, so tell the user they have no flags.
 
196
        // If the user passed object names, we already told them all their
 
197
        // objects are nonexistent or unflagged.
 
198
        if (empty($objects)) {
 
199
          echo "You have no flagged objects.\n";
 
200
        }
 
201
      } else {
 
202
        // Print ALL the flags. With fancy formatting. Because fancy formatting
 
203
        // is _cool_.
 
204
        $name_len = 1 + max(array_map('strlen', ipull($flags, 'colorName')));
 
205
        foreach ($flags as $flag) {
 
206
          $color = idx(self::$colorMap, $flag['color'], 'cyan');
 
207
          echo phutil_console_format(
 
208
            "[<fg:{$color}>%s</fg>] %s\n",
 
209
            str_pad($flag['colorName'], $name_len),
 
210
            $flag['handle']['fullname']);
 
211
          if ($flag['note']) {
 
212
            $note = phutil_console_wrap($flag['note'], $name_len + 3);
 
213
            echo rtrim($note)."\n";
 
214
          }
 
215
        }
 
216
      }
 
217
    }
 
218
  }
 
219
 
 
220
}