Skip to content

Commit 4fb3b27

Browse files
committedJul 10, 2013
Legalpad - add signature page
Summary: Fixes T3481. Sort of - this thing be very ugly. Also it assumes that you'll "always" want to sign terms. I was thinking in a future diff that should be optional as well as configurable, though it was unclear to me if either was worth pursuing... Generally very hideous as the three main elements (PHUIDocument, AphrontErrorView, and AphrontForm with an AphrontFormInset) have never really played together before. Test Plan: agreed to some test terms. noted UI displayed nicely. reloaded and noted UI told me I had signed it already. Went to different terms and filled them out wrong and got sensical errors. Reviewers: epriestley Reviewed By: epriestley CC: aran, Korvin Maniphest Tasks: T3481 Differential Revision: https://secure.phabricator.com/D6399
1 parent d467c49 commit 4fb3b27

10 files changed

+260
-9
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER TABLE {$NAMESPACE}_legalpad.legalpad_documentsignature
2+
ADD signatureData LONGTEXT NOT NULL COLLATE utf8_bin AFTER signerPHID;

‎src/__phutil_library_map__.php

+2
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,7 @@
644644
'LegalpadDocumentPreviewController' => 'applications/legalpad/controller/LegalpadDocumentPreviewController.php',
645645
'LegalpadDocumentQuery' => 'applications/legalpad/query/LegalpadDocumentQuery.php',
646646
'LegalpadDocumentSearchEngine' => 'applications/legalpad/query/LegalpadDocumentSearchEngine.php',
647+
'LegalpadDocumentSignController' => 'applications/legalpad/controller/LegalpadDocumentSignController.php',
647648
'LegalpadDocumentSignature' => 'applications/legalpad/storage/LegalpadDocumentSignature.php',
648649
'LegalpadDocumentViewController' => 'applications/legalpad/controller/LegalpadDocumentViewController.php',
649650
'LegalpadMockMailReceiver' => 'applications/legalpad/mail/LegalpadMockMailReceiver.php',
@@ -2573,6 +2574,7 @@
25732574
'LegalpadDocumentPreviewController' => 'LegalpadController',
25742575
'LegalpadDocumentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
25752576
'LegalpadDocumentSearchEngine' => 'PhabricatorApplicationSearchEngine',
2577+
'LegalpadDocumentSignController' => 'LegalpadController',
25762578
'LegalpadDocumentSignature' => 'LegalpadDAO',
25772579
'LegalpadDocumentViewController' => 'LegalpadController',
25782580
'LegalpadMockMailReceiver' => 'PhabricatorObjectMailReceiver',

‎src/applications/legalpad/application/PhabricatorApplicationLegalpad.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public function isBeta() {
4040

4141
public function getRoutes() {
4242
return array(
43-
'/L(?P<id>\d+)/' => 'LegalpadDocumentViewController',
43+
'/L(?P<id>\d+)' => 'LegalpadDocumentSignController',
4444
'/legalpad/' => array(
4545
'' => 'LegalpadDocumentListController',
4646
'(query/(?P<queryKey>[^/]+)/)?' => 'LegalpadDocumentListController',

‎src/applications/legalpad/controller/LegalpadDocumentListController.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ public function renderResultsList(
3737
$list->setUser($user);
3838
foreach ($documents as $document) {
3939
$last_updated = phabricator_date($document->getDateModified(), $user);
40-
$updater = $this->getHandle(
41-
reset($document->getRecentContributorPHIDs()))->renderLink();
40+
$recent_contributors = $document->getRecentContributorPHIDs();
41+
$updater = $this->getHandle(reset($recent_contributors))->renderLink();
4242

4343
$title = $document->getTitle();
4444

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
<?php
2+
3+
/**
4+
* @group legalpad
5+
*/
6+
final class LegalpadDocumentSignController extends LegalpadController {
7+
8+
private $id;
9+
10+
public function willProcessRequest(array $data) {
11+
$this->id = $data['id'];
12+
}
13+
14+
public function processRequest() {
15+
$request = $this->getRequest();
16+
$user = $request->getUser();
17+
18+
$document = id(new LegalpadDocumentQuery())
19+
->setViewer($user)
20+
->withIDs(array($this->id))
21+
->needDocumentBodies(true)
22+
->executeOne();
23+
24+
if (!$document) {
25+
return new Aphront404Response();
26+
}
27+
28+
$signature = id(new LegalpadDocumentSignature())
29+
->loadOneWhere(
30+
'documentPHID = %s AND documentVersion = %d AND signerPHID = %s',
31+
$document->getPHID(),
32+
$document->getVersions(),
33+
$user->getPHID());
34+
35+
if (!$signature) {
36+
$has_signed = false;
37+
$error_view = null;
38+
$signature = id(new LegalpadDocumentSignature())
39+
->setSignerPHID($user->getPHID())
40+
->setDocumentPHID($document->getPHID())
41+
->setDocumentVersion($document->getVersions());
42+
$data = array(
43+
'name' => $user->getRealName(),
44+
'email' => $user->loadPrimaryEmailAddress());
45+
$signature->setSignatureData($data);
46+
} else {
47+
$has_signed = true;
48+
$error_view = id(new AphrontErrorView())
49+
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
50+
->setTitle(pht('You have already agreed to these terms.'));
51+
$data = $signature->getSignatureData();
52+
}
53+
54+
$e_name = true;
55+
$e_email = true;
56+
$e_address_1 = true;
57+
$errors = array();
58+
if ($request->isFormPost()) {
59+
$name = $request->getStr('name');
60+
$email = $request->getStr('email');
61+
$address_1 = $request->getStr('address_1');
62+
$address_2 = $request->getStr('address_2');
63+
$phone = $request->getStr('phone');
64+
$agree = $request->getExists('agree');
65+
66+
if (!$name) {
67+
$e_name = pht('Required');
68+
$errors[] = pht('Name field is required.');
69+
}
70+
$data['name'] = $name;
71+
72+
if (!$email) {
73+
$e_email = pht('Required');
74+
$errors[] = pht('Email field is required.');
75+
} else {
76+
$addr_obj = new PhutilEmailAddress($email);
77+
$domain = $addr_obj->getDomainName();
78+
if (!$domain) {
79+
$e_email = pht('Invalid');
80+
$errors[] = pht('A valid email is required.');
81+
}
82+
}
83+
$data['email'] = $email;
84+
85+
if (!$address_1) {
86+
$e_address_1 = pht('Required');
87+
$errors[] = pht('Address line 1 field is required.');
88+
}
89+
$data['address_1'] = $address_1;
90+
$data['address_2'] = $address_2;
91+
$data['phone'] = $phone;
92+
$signature->setSignatureData($data);
93+
94+
if (!$agree) {
95+
$errors[] = pht(
96+
'You must check "I agree to the terms laid forth above."');
97+
}
98+
99+
if (!$errors) {
100+
$signature->save();
101+
$has_signed = true;
102+
$error_view = id(new AphrontErrorView())
103+
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
104+
->setTitle(pht('Signature successful. Thank you.'));
105+
} else {
106+
$error_view = id(new AphrontErrorView())
107+
->setTitle(pht('Error in submission.'))
108+
->setErrors($errors);
109+
}
110+
}
111+
112+
$document_body = $document->getDocumentBody();
113+
$engine = id(new PhabricatorMarkupEngine())
114+
->setViewer($user);
115+
$engine->addObject(
116+
$document_body,
117+
LegalpadDocumentBody::MARKUP_FIELD_TEXT);
118+
$engine->process();
119+
120+
$title = $document_body->getTitle();
121+
122+
$header = id(new PhabricatorHeaderView())
123+
->setHeader($title);
124+
125+
$content = array(
126+
id(new PHUIDocumentView())
127+
->setHeader($header)
128+
->appendChild($this->buildDocument($engine, $document_body)),
129+
$error_view,
130+
$this->buildSignatureForm(
131+
$document_body,
132+
$signature,
133+
$has_signed,
134+
$e_name,
135+
$e_email,
136+
$e_address_1));
137+
138+
return $this->buildApplicationPage(
139+
$content,
140+
array(
141+
'title' => $title,
142+
'device' => true,
143+
'dust' => true,
144+
'pageObjects' => array($document->getPHID()),
145+
));
146+
}
147+
148+
private function buildDocument(
149+
PhabricatorMarkupEngine
150+
$engine, LegalpadDocumentBody $body) {
151+
152+
require_celerity_resource('legalpad-documentbody-css');
153+
154+
return phutil_tag(
155+
'div',
156+
array(
157+
'class' => 'legalpad-documentbody'
158+
),
159+
$engine->getOutput($body, LegalpadDocumentBody::MARKUP_FIELD_TEXT));
160+
161+
}
162+
163+
private function buildSignatureForm(
164+
LegalpadDocumentBody $body,
165+
LegalpadDocumentSignature $signature,
166+
$has_signed = false,
167+
$e_name = true,
168+
$e_email = true,
169+
$e_address_1 = true) {
170+
171+
$user = $this->getRequest()->getUser();
172+
if ($has_signed) {
173+
$instructions = pht('Thank you for signing and agreeing.');
174+
} else {
175+
$instructions = pht('Please enter the following information.');
176+
}
177+
178+
$data = $signature->getSignatureData();
179+
$form = id(new AphrontFormView())
180+
->setUser($user)
181+
->setFlexible(true)
182+
->appendChild(
183+
id(new AphrontFormInsetView())
184+
->setTitle(pht('Sign and Agree'))
185+
->setDescription($instructions)
186+
->setContent(phutil_tag('br', array()))
187+
->appendChild(
188+
id(new AphrontFormTextControl())
189+
->setLabel(pht('Name'))
190+
->setValue(idx($data, 'name', ''))
191+
->setName('name')
192+
->setError($e_name)
193+
->setDisabled($has_signed))
194+
->appendChild(
195+
id(new AphrontFormTextControl())
196+
->setLabel(pht('Email'))
197+
->setValue(idx($data, 'email', ''))
198+
->setName('email')
199+
->setError($e_email)
200+
->setDisabled($has_signed))
201+
->appendChild(
202+
id(new AphrontFormTextControl())
203+
->setLabel(pht('Address line 1'))
204+
->setValue(idx($data, 'address_1', ''))
205+
->setName('address_1')
206+
->setError($e_address_1)
207+
->setDisabled($has_signed))
208+
->appendChild(
209+
id(new AphrontFormTextControl())
210+
->setLabel(pht('Address line 2'))
211+
->setValue(idx($data, 'address_2', ''))
212+
->setName('address_2')
213+
->setDisabled($has_signed))
214+
->appendChild(
215+
id(new AphrontFormTextControl())
216+
->setLabel(pht('Phone'))
217+
->setValue(idx($data, 'phone', ''))
218+
->setName('phone')
219+
->setDisabled($has_signed))
220+
->appendChild(
221+
id(new AphrontFormCheckboxControl())
222+
->addCheckbox(
223+
'agree',
224+
'agree',
225+
pht('I agree to the terms laid forth above.'),
226+
$has_signed)
227+
->setDisabled($has_signed))
228+
->appendChild(
229+
id(new AphrontFormSubmitControl())
230+
->setValue(pht('Sign and Agree'))
231+
->setDisabled($has_signed)));
232+
233+
return $form;
234+
}
235+
236+
}

‎src/applications/legalpad/controller/LegalpadDocumentViewController.php

-3
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,6 @@ public function processRequest() {
4747

4848
$engine = id(new PhabricatorMarkupEngine())
4949
->setViewer($user);
50-
$engine->addObject(
51-
$document_body,
52-
LegalpadDocumentBody::MARKUP_FIELD_TITLE);
5350
$engine->addObject(
5451
$document_body,
5552
LegalpadDocumentBody::MARKUP_FIELD_TEXT);

‎src/applications/legalpad/editor/LegalpadDocumentEditor.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ protected function buildMailBody(
169169

170170
$body->addTextSection(
171171
pht('DOCUMENT DETAIL'),
172-
PhabricatorEnv::getProductionURI('/L'.$object->getID()));
172+
PhabricatorEnv::getProductionURI('/legalpad/view/'.$object->getID().'/'));
173173

174174
return $body;
175175
}

‎src/applications/legalpad/storage/LegalpadDocumentBody.php

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ final class LegalpadDocumentBody extends LegalpadDAO
77
implements
88
PhabricatorMarkupInterface {
99

10-
const MARKUP_FIELD_TITLE = 'markup:title';
1110
const MARKUP_FIELD_TEXT = 'markup:text ';
1211

1312
protected $phid;

‎src/applications/legalpad/storage/LegalpadDocumentSignature.php

+12-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,18 @@
66
final class LegalpadDocumentSignature extends LegalpadDAO {
77

88
protected $documentPHID;
9-
protected $documentversion;
9+
protected $documentVersion;
1010
protected $signerPHID;
11+
protected $signatureData = array();
12+
13+
public function getConfiguration() {
14+
return array(
15+
self::CONFIG_SERIALIZATION => array(
16+
'signatureData' => self::SERIALIZATION_JSON,
17+
),
18+
) + parent::getConfiguration();
19+
}
20+
21+
1122

1223
}

‎src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php

+4
Original file line numberDiff line numberDiff line change
@@ -1430,6 +1430,10 @@ public function getPatches() {
14301430
'type' => 'php',
14311431
'name' => $this->getPatchPath('20130703.legalpaddocdenorm.php'),
14321432
),
1433+
'20130709.legalpadsignature.sql' => array(
1434+
'type' => 'sql',
1435+
'name' => $this->getPatchPath('20130709.legalpadsignature.sql'),
1436+
),
14331437
'20130709.droptimeline.sql' => array(
14341438
'type' => 'sql',
14351439
'name' => $this->getPatchPath('20130709.droptimeline.sql'),

0 commit comments

Comments
 (0)
Failed to load comments.