PhrictionEditController.php 10.7 KB
Newer Older
1
2
<?php

3
final class PhrictionEditController
4
5
  extends PhrictionController {

6
7
8
  public function handleRequest(AphrontRequest $request) {
    $viewer = $request->getViewer();
    $id = $request->getURIData('id');
9

10
    $current_version = null;
11
    if ($id) {
12
      $is_new = false;
13
      $document = id(new PhrictionDocumentQuery())
14
15
        ->setViewer($viewer)
        ->withIDs(array($id))
16
        ->needContent(true)
17
18
19
20
21
22
        ->requireCapabilities(
          array(
            PhabricatorPolicyCapability::CAN_VIEW,
            PhabricatorPolicyCapability::CAN_EDIT,
          ))
        ->executeOne();
23
24
25
      if (!$document) {
        return new Aphront404Response();
      }
epriestley's avatar
epriestley committed
26

27
28
      $current_version = $document->getContent()->getVersion();

epriestley's avatar
epriestley committed
29
30
31
32
33
34
35
36
37
38
      $revert = $request->getInt('revert');
      if ($revert) {
        $content = id(new PhrictionContent())->loadOneWhere(
          'documentID = %d AND version = %d',
          $document->getID(),
          $revert);
        if (!$content) {
          return new Aphront404Response();
        }
      } else {
39
        $content = $document->getContent();
epriestley's avatar
epriestley committed
40
      }
41
42
43

    } else {
      $slug = $request->getStr('slug');
Bob Trahan's avatar
Bob Trahan committed
44
      $slug = PhabricatorSlug::normalize($slug);
45
46
47
48
      if (!$slug) {
        return new Aphront404Response();
      }

49
      $document = id(new PhrictionDocumentQuery())
50
        ->setViewer($viewer)
51
52
53
        ->withSlugs(array($slug))
        ->needContent(true)
        ->executeOne();
54
55

      if ($document) {
56
        $content = $document->getContent();
57
        $current_version = $content->getVersion();
58
        $is_new = false;
59
      } else {
60
        $document = PhrictionDocument::initializeNewDocument($viewer, $slug);
61
        $content = $document->getContent();
62
        $is_new = true;
63
64
65
      }
    }

66
67
68
69
70
71
72
73
74
75
76
    if ($request->getBool('nodraft')) {
      $draft = null;
      $draft_key = null;
    } else {
      if ($document->getPHID()) {
        $draft_key = $document->getPHID().':'.$content->getVersion();
      } else {
        $draft_key = 'phriction:'.$content->getSlug();
      }
      $draft = id(new PhabricatorDraft())->loadOneWhere(
        'authorPHID = %s AND draftKey = %s',
77
        $viewer->getPHID(),
78
79
80
        $draft_key);
    }

81
82
83
84
85
86
87
88
89
90
91
92
    if ($draft &&
      strlen($draft->getDraft()) &&
      ($draft->getDraft() != $content->getContent())) {
      $content_text = $draft->getDraft();

      $discard = phutil_tag(
        'a',
        array(
          'href' => $request->getRequestURI()->alter('nodraft', true),
        ),
        pht('discard this draft'));

93
94
      $draft_note = new PHUIInfoView();
      $draft_note->setSeverity(PHUIInfoView::SEVERITY_NOTICE);
Joshua Spence's avatar
Joshua Spence committed
95
96
      $draft_note->setTitle(pht('Recovered Draft'));
      $draft_note->appendChild(
97
        pht('Showing a saved draft of your edits, you can %s.', $discard));
98
99
100
101
102
    } else {
      $content_text = $content->getContent();
      $draft_note = null;
    }

103
104
    require_celerity_resource('phriction-document-css');

105
    $e_title = true;
106
107
    $e_content = true;
    $validation_exception = null;
108
    $notes = null;
109
110
    $title = $content->getTitle();
    $overwrite = false;
Chad Little's avatar
Chad Little committed
111
112
    $v_cc = PhabricatorSubscribersQuery::loadSubscribersForPHID(
      $document->getPHID());
113

114
115
116
117
118
119
120
121
122
    if ($is_new) {
      $v_projects = array();
    } else {
      $v_projects = PhabricatorEdgeQuery::loadDestinationPHIDs(
        $document->getPHID(),
        PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
      $v_projects = array_reverse($v_projects);
    }

123
    if ($request->isFormPost()) {
124

125
      $title = $request->getStr('title');
126
      $content_text = $request->getStr('content');
127
      $notes = $request->getStr('description');
128
      $current_version = $request->getInt('contentVersion');
129
130
      $v_view = $request->getStr('viewPolicy');
      $v_edit = $request->getStr('editPolicy');
131
132
      $v_cc = $request->getArr('cc');
      $v_projects = $request->getArr('projects');
133
134
135

      $xactions = array();
      $xactions[] = id(new PhrictionTransaction())
136
        ->setTransactionType(PhrictionDocumentTitleTransaction::TRANSACTIONTYPE)
137
138
        ->setNewValue($title);
      $xactions[] = id(new PhrictionTransaction())
139
140
        ->setTransactionType(
          PhrictionDocumentContentTransaction::TRANSACTIONTYPE)
141
        ->setNewValue($content_text);
142
143
144
145
146
147
      $xactions[] = id(new PhrictionTransaction())
        ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
        ->setNewValue($v_view);
      $xactions[] = id(new PhrictionTransaction())
        ->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
        ->setNewValue($v_edit);
Chad Little's avatar
Chad Little committed
148
149
150
      $xactions[] = id(new PhrictionTransaction())
        ->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
        ->setNewValue(array('=' => $v_cc));
151

152
153
154
155
156
157
      $proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
      $xactions[] = id(new PhrictionTransaction())
        ->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
        ->setMetadataValue('edge:type', $proj_edge_type)
        ->setNewValue(array('=' => array_fuse($v_projects)));

158
      $editor = id(new PhrictionTransactionEditor())
159
        ->setActor($viewer)
160
161
162
163
164
165
166
167
        ->setContentSourceFromRequest($request)
        ->setContinueOnNoEffect(true)
        ->setDescription($notes)
        ->setProcessContentVersionError(!$request->getBool('overwrite'))
        ->setContentVersion($current_version);

      try {
        $editor->applyTransactions($document, $xactions);
168

169
170
171
172
        if ($draft) {
          $draft->delete();
        }

173
        $uri = PhrictionDocument::getSlugURI($document->getSlug());
174
        return id(new AphrontRedirectResponse())->setURI($uri);
175
176
      } catch (PhabricatorApplicationTransactionValidationException $ex) {
        $validation_exception = $ex;
177
        $e_title = nonempty(
178
179
          $ex->getShortMessage(
            PhrictionDocumentTitleTransaction::TRANSACTIONTYPE),
180
181
          true);
        $e_content = nonempty(
182
183
          $ex->getShortMessage(
            PhrictionDocumentContentTransaction::TRANSACTIONTYPE),
184
          true);
185
186
187
188
189
190
191

        // if we're not supposed to process the content version error, then
        // overwrite that content...!
        if (!$editor->getProcessContentVersionError()) {
          $overwrite = true;
        }

192
193
        $document->setViewPolicy($v_view);
        $document->setEditPolicy($v_edit);
194
195
196
197
      }
    }

    if ($document->getID()) {
198
      $panel_header = pht('Edit Document: %s', $content->getTitle());
199
      $page_title = pht('Edit Document');
200
      $header_icon = 'fa-pencil';
201
202
203
204
205
      if ($overwrite) {
        $submit_button = pht('Overwrite Changes');
      } else {
        $submit_button = pht('Save Changes');
      }
206
    } else {
Chad Little's avatar
Chad Little committed
207
208
      $panel_header = pht('Create New Phriction Document');
      $submit_button = pht('Create Document');
209
      $page_title = pht('Create Document');
210
      $header_icon = 'fa-plus-square';
211
212
213
214
215
216
    }

    $uri = $document->getSlug();
    $uri = PhrictionDocument::getSlugURI($uri);
    $uri = PhabricatorEnv::getProductionURI($uri);

217
218
    $cancel_uri = PhrictionDocument::getSlugURI($document->getSlug());

219
    $policies = id(new PhabricatorPolicyQuery())
220
      ->setViewer($viewer)
221
222
223
224
225
      ->setObject($document)
      ->execute();
    $view_capability = PhabricatorPolicyCapability::CAN_VIEW;
    $edit_capability = PhabricatorPolicyCapability::CAN_EDIT;

226
    $form = id(new AphrontFormView())
227
      ->setUser($viewer)
228
      ->addHiddenInput('slug', $document->getSlug())
229
      ->addHiddenInput('nodraft', $request->getBool('nodraft'))
230
      ->addHiddenInput('contentVersion', $current_version)
231
      ->addHiddenInput('overwrite', $overwrite)
232
233
      ->appendChild(
        id(new AphrontFormTextControl())
Chad Little's avatar
Chad Little committed
234
          ->setLabel(pht('Title'))
235
          ->setValue($title)
236
237
238
239
          ->setError($e_title)
          ->setName('title'))
      ->appendChild(
        id(new AphrontFormStaticControl())
Chad Little's avatar
Chad Little committed
240
          ->setLabel(pht('URI'))
241
242
          ->setValue($uri))
      ->appendChild(
243
        id(new PhabricatorRemarkupControl())
Chad Little's avatar
Chad Little committed
244
          ->setLabel(pht('Content'))
245
          ->setValue($content_text)
246
          ->setError($e_content)
247
          ->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL)
248
          ->setName('content')
249
          ->setID('document-textarea')
250
          ->setUser($viewer))
251
252
      ->appendControl(
        id(new AphrontFormTokenizerControl())
Luke081515's avatar
Luke081515 committed
253
          ->setLabel(pht('Tags'))
254
255
256
          ->setName('projects')
          ->setValue($v_projects)
          ->setDatasource(new PhabricatorProjectDatasource()))
Chad Little's avatar
Chad Little committed
257
258
259
260
261
262
263
      ->appendControl(
        id(new AphrontFormTokenizerControl())
          ->setLabel(pht('Subscribers'))
          ->setName('cc')
          ->setValue($v_cc)
          ->setUser($viewer)
          ->setDatasource(new PhabricatorMetaMTAMailableDatasource()))
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
      ->appendChild(
        id(new AphrontFormPolicyControl())
          ->setName('viewPolicy')
          ->setPolicyObject($document)
          ->setCapability($view_capability)
          ->setPolicies($policies)
          ->setCaption(
            $document->describeAutomaticCapability($view_capability)))
      ->appendChild(
        id(new AphrontFormPolicyControl())
          ->setName('editPolicy')
          ->setPolicyObject($document)
          ->setCapability($edit_capability)
          ->setPolicies($policies)
          ->setCaption(
            $document->describeAutomaticCapability($edit_capability)))
280
281
      ->appendChild(
        id(new AphrontFormTextControl())
Chad Little's avatar
Chad Little committed
282
          ->setLabel(pht('Edit Notes'))
283
          ->setValue($notes)
284
285
          ->setError(null)
          ->setName('description'))
286
287
      ->appendChild(
        id(new AphrontFormSubmitControl())
288
          ->addCancelButton($cancel_uri)
289
290
          ->setValue($submit_button));

291
    $form_box = id(new PHUIObjectBoxView())
292
      ->setHeaderText(pht('Document'))
293
      ->setValidationException($validation_exception)
294
      ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
Chad Little's avatar
Chad Little committed
295
      ->setForm($form);
296

297
    $preview = id(new PHUIRemarkupPreviewPanel())
298
      ->setHeader($content->getTitle())
299
      ->setPreviewURI('/phriction/preview/'.$document->getSlug())
300
      ->setControlID('document-textarea')
301
      ->setPreviewType(PHUIRemarkupPreviewPanel::DOCUMENT);
302

303
304
    $crumbs = $this->buildApplicationCrumbs();
    if ($document->getID()) {
305
306
307
308
      $crumbs->addTextCrumb(
        $content->getTitle(),
        PhrictionDocument::getSlugURI($document->getSlug()));
      $crumbs->addTextCrumb(pht('Edit'));
309
    } else {
310
      $crumbs->addTextCrumb(pht('Create'));
311
    }
312
    $crumbs->setBorder(true);
313

314
315
316
317
318
319
320
    $header = id(new PHUIHeaderView())
      ->setHeader($panel_header)
      ->setHeaderIcon($header_icon);

    $view = id(new PHUITwoColumnView())
      ->setHeader($header)
      ->setFooter(array(
321
        $draft_note,
Chad Little's avatar
Chad Little committed
322
        $form_box,
323
        $preview,
324
      ));
325
326
327
328
329
330

    return $this->newPage()
      ->setTitle($page_title)
      ->setCrumbs($crumbs)
      ->appendChild($view);

331
332
333
  }

}