Page MenuHomePhabricator

D13091.id31606.diff
No OneTemporary

D13091.id31606.diff

diff --git a/resources/sql/autopatches/20150601.divineredge.sql b/resources/sql/autopatches/20150601.divineredge.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20150601.divineredge.sql
@@ -0,0 +1,17 @@
+CREATE TABLE {$NAMESPACE}_diviner.edge (
+ src VARBINARY(64) NOT NULL,
+ type INT UNSIGNED NOT NULL,
+ dst VARBINARY(64) NOT NULL,
+ dateCreated INT UNSIGNED NOT NULL,
+ seq INT UNSIGNED NOT NULL,
+ dataID INT UNSIGNED,
+
+ PRIMARY KEY (src, type, dst),
+ KEY src (src, type, dateCreated, seq),
+ UNIQUE KEY key_dst (dst, type, src)
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
+
+CREATE TABLE {$NAMESPACE}_diviner.edgedata (
+ id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
+ data LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT}
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
diff --git a/resources/sql/autopatches/20150601.divineredit.sql b/resources/sql/autopatches/20150601.divineredit.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20150601.divineredit.sql
@@ -0,0 +1,6 @@
+ALTER TABLE {$NAMESPACE}_diviner.diviner_livebook
+ ADD COLUMN editPolicy VARBINARY(64) NOT NULL AFTER viewPolicy;
+
+UPDATE {$NAMESPACE}_diviner.diviner_livebook
+ SET editPolicy = 'admin'
+ WHERE editPolicy IS NULL;
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -647,12 +647,17 @@
'DivinerAtomizeWorkflow' => 'applications/diviner/workflow/DivinerAtomizeWorkflow.php',
'DivinerAtomizer' => 'applications/diviner/atomizer/DivinerAtomizer.php',
'DivinerBookController' => 'applications/diviner/controller/DivinerBookController.php',
+ 'DivinerBookEditController' => 'applications/diviner/storage/DivinerBookEditController.php',
+ 'DivinerBookEditor' => 'applications/diviner/editor/DivinerBookEditor.php',
'DivinerBookItemView' => 'applications/diviner/view/DivinerBookItemView.php',
'DivinerBookPHIDType' => 'applications/diviner/phid/DivinerBookPHIDType.php',
'DivinerBookQuery' => 'applications/diviner/query/DivinerBookQuery.php',
+ 'DivinerBookTransaction' => 'applications/diviner/storage/DivinerBookTransaction.php',
'DivinerController' => 'applications/diviner/controller/DivinerController.php',
'DivinerDAO' => 'applications/diviner/storage/DivinerDAO.php',
+ 'DivinerDefaultEditCapability' => 'applications/diviner/capability/DivinerDefaultEditCapability.php',
'DivinerDefaultRenderer' => 'applications/diviner/renderer/DivinerDefaultRenderer.php',
+ 'DivinerDefaultViewCapability' => 'applications/diviner/capability/DivinerDefaultViewCapability.php',
'DivinerDiskCache' => 'applications/diviner/cache/DivinerDiskCache.php',
'DivinerFileAtomizer' => 'applications/diviner/atomizer/DivinerFileAtomizer.php',
'DivinerFindController' => 'applications/diviner/controller/DivinerFindController.php',
@@ -3877,12 +3882,17 @@
'DivinerAtomSearchEngine' => 'PhabricatorApplicationSearchEngine',
'DivinerAtomizeWorkflow' => 'DivinerWorkflow',
'DivinerBookController' => 'DivinerController',
+ 'DivinerBookEditController' => 'DivinerController',
+ 'DivinerBookEditor' => 'PhabricatorApplicationTransactionEditor',
'DivinerBookItemView' => 'AphrontTagView',
'DivinerBookPHIDType' => 'PhabricatorPHIDType',
'DivinerBookQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
+ 'DivinerBookTransaction' => 'PhabricatorApplicationTransaction',
'DivinerController' => 'PhabricatorController',
'DivinerDAO' => 'PhabricatorLiskDAO',
+ 'DivinerDefaultEditCapability' => 'PhabricatorPolicyCapability',
'DivinerDefaultRenderer' => 'DivinerRenderer',
+ 'DivinerDefaultViewCapability' => 'PhabricatorPolicyCapability',
'DivinerFileAtomizer' => 'DivinerAtomizer',
'DivinerFindController' => 'DivinerController',
'DivinerGenerateWorkflow' => 'DivinerWorkflow',
@@ -3890,6 +3900,7 @@
'DivinerLiveBook' => array(
'DivinerDAO',
'PhabricatorPolicyInterface',
+ 'PhabricatorProjectInterface',
'PhabricatorDestructibleInterface',
),
'DivinerLivePublisher' => 'DivinerPublisher',
diff --git a/src/applications/diffusion/controller/DiffusionRepositoryController.php b/src/applications/diffusion/controller/DiffusionRepositoryController.php
--- a/src/applications/diffusion/controller/DiffusionRepositoryController.php
+++ b/src/applications/diffusion/controller/DiffusionRepositoryController.php
@@ -17,7 +17,7 @@
$crumbs = $this->buildCrumbs();
$content[] = $crumbs;
- $content[] = $this->buildPropertiesTable($drequest->getRepository());
+ $content[] = $this->buildPropertiesTable($repository);
// Before we do any work, make sure we're looking at a some content: we're
// on a valid branch, and the repository is not empty.
@@ -76,7 +76,7 @@
return $this->buildApplicationPage(
$content,
array(
- 'title' => $drequest->getRepository()->getName(),
+ 'title' => $repository->getName(),
));
}
@@ -552,7 +552,7 @@
}
$history_table->setIsHead(true);
- $callsign = $drequest->getRepository()->getCallsign();
+ $callsign = $repository->getCallsign();
$icon = id(new PHUIIconView())
->setIconFont('fa-list-alt');
diff --git a/src/applications/diviner/application/PhabricatorDivinerApplication.php b/src/applications/diviner/application/PhabricatorDivinerApplication.php
--- a/src/applications/diviner/application/PhabricatorDivinerApplication.php
+++ b/src/applications/diviner/application/PhabricatorDivinerApplication.php
@@ -39,6 +39,7 @@
'find/' => 'DivinerFindController',
),
'/book/(?P<book>[^/]+)/' => 'DivinerBookController',
+ '/book/(?P<book>[^/]+)/edit/' => 'DivinerBookEditController',
'/book/'.
'(?P<book>[^/]+)/'.
'(?P<type>[^/]+)/'.
@@ -52,6 +53,15 @@
return self::GROUP_UTILITIES;
}
+ protected function getCustomCapabilities() {
+ return array(
+ DivinerDefaultViewCapability::CAPABILITY => array(),
+ DivinerDefaultEditCapability::CAPABILITY => array(
+ 'default' => PhabricatorPolicies::POLICY_ADMIN,
+ ),
+ );
+ }
+
public function getRemarkupRules() {
return array(
new DivinerSymbolRemarkupRule(),
diff --git a/src/applications/diviner/capability/DivinerDefaultEditCapability.php b/src/applications/diviner/capability/DivinerDefaultEditCapability.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diviner/capability/DivinerDefaultEditCapability.php
@@ -0,0 +1,11 @@
+<?php
+
+final class DivinerDefaultEditCapability extends PhabricatorPolicyCapability {
+
+ const CAPABILITY = 'diviner.default.edit';
+
+ public function getCapabilityName() {
+ return pht('Default Edit Policy');
+ }
+
+}
diff --git a/src/applications/diviner/capability/DivinerDefaultViewCapability.php b/src/applications/diviner/capability/DivinerDefaultViewCapability.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diviner/capability/DivinerDefaultViewCapability.php
@@ -0,0 +1,15 @@
+<?php
+
+final class DivinerDefaultViewCapability extends PhabricatorPolicyCapability {
+
+ const CAPABILITY = 'diviner.default.view';
+
+ public function getCapabilityName() {
+ return pht('Default View Policy');
+ }
+
+ public function shouldAllowPublicPolicySetting() {
+ return true;
+ }
+
+}
diff --git a/src/applications/diviner/controller/DivinerBookController.php b/src/applications/diviner/controller/DivinerBookController.php
--- a/src/applications/diviner/controller/DivinerBookController.php
+++ b/src/applications/diviner/controller/DivinerBookController.php
@@ -13,8 +13,9 @@
}
public function processRequest() {
+ $content = array();
$request = $this->getRequest();
- $viewer = $request->getUser();
+ $viewer = $request->getUser();
$book = id(new DivinerBookQuery())
->setViewer($viewer)
@@ -31,6 +32,9 @@
$crumbs->addTextCrumb(
$book->getShortTitle(),
'/book/'.$book->getName().'/');
+ $content[] = $crumbs;
+
+ $content[] = $this->buildPropertiesTable($book);
$header = id(new PHUIHeaderView())
->setHeader($book->getTitle())
@@ -50,6 +54,7 @@
$document->setHeader($header);
$document->addClass('diviner-view');
$document->setFontKit(PHUIDocumentView::FONT_SOURCE_SANS);
+ $content[] = $document;
$atoms = id(new DivinerAtomQuery())
->setViewer($viewer)
@@ -97,13 +102,70 @@
$document->appendChild($out);
return $this->buildApplicationPage(
- array(
- $crumbs,
- $document,
- ),
+ $content,
array(
'title' => $book->getTitle(),
));
}
+ private function buildPropertiesTable(DivinerLiveBook $book) {
+ $user = $this->getRequest()->getUser();
+
+ $header = id(new PHUIHeaderView())
+ ->setHeader($book->getName())
+ ->setUser($user)
+ ->setPolicyObject($book);
+
+ $header->setStatus('fa-check', 'bluegrey', pht('Active'));
+
+ $actions = $this->buildActionList($book);
+
+ $view = id(new PHUIPropertyListView())
+ ->setUser($user);
+
+ $project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
+ $book->getPHID(),
+ PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
+ if ($project_phids) {
+ $view->addProperty(
+ pht('Projects'),
+ $user->renderHandleList($project_phids));
+ }
+
+ $view->setActionList($actions);
+
+ $box = id(new PHUIObjectBoxView())
+ ->setHeader($header)
+ ->addPropertyList($view);
+
+ return $box;
+ }
+
+ private function buildActionList(DivinerLiveBook $book) {
+ $viewer = $this->getRequest()->getUser();
+
+ $view_uri = '/book/'.$book->getName().'/';
+ $edit_uri = '/book/'.$book->getName().'/edit/';
+
+ $view = id(new PhabricatorActionListView())
+ ->setUser($viewer)
+ ->setObject($book)
+ ->setObjectURI($view_uri);
+
+ $can_edit = PhabricatorPolicyFilter::hasCapability(
+ $viewer,
+ $book,
+ PhabricatorPolicyCapability::CAN_EDIT);
+
+ $view->addAction(
+ id(new PhabricatorActionView())
+ ->setName(pht('Edit Book'))
+ ->setIcon('fa-pencil')
+ ->setHref($edit_uri)
+ ->setWorkflow(!$can_edit)
+ ->setDisabled(!$can_edit));
+
+ return $view;
+ }
+
}
diff --git a/src/applications/diviner/editor/DivinerBookEditor.php b/src/applications/diviner/editor/DivinerBookEditor.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diviner/editor/DivinerBookEditor.php
@@ -0,0 +1,22 @@
+<?php
+
+final class DivinerBookEditor extends PhabricatorApplicationTransactionEditor {
+
+ public function getEditorApplicationClass() {
+ return 'PhabricatorDivinerApplication';
+ }
+
+ public function getEditorObjectsDescription() {
+ return pht('Books');
+ }
+
+ public function getTransactionTypes() {
+ $types = parent::getTransactionTypes();
+
+ $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
+ $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
+
+ return $types;
+ }
+
+}
diff --git a/src/applications/diviner/query/DivinerBookQuery.php b/src/applications/diviner/query/DivinerBookQuery.php
--- a/src/applications/diviner/query/DivinerBookQuery.php
+++ b/src/applications/diviner/query/DivinerBookQuery.php
@@ -7,6 +7,8 @@
private $names;
private $repositoryPHIDs;
+ private $needProjectPHIDs;
+
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
@@ -27,6 +29,11 @@
return $this;
}
+ public function needProjectPHIDs($need_phids) {
+ $this->needProjectPHIDs = $need_phids;
+ return $this;
+ }
+
protected function loadPage() {
$table = new DivinerLiveBook();
$conn_r = $table->establishConnection('r');
@@ -70,6 +77,27 @@
return $books;
}
+ protected function didFilterPage(array $books) {
+ if ($this->needProjectPHIDs) {
+ $type_project = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
+
+ $edge_query = id(new PhabricatorEdgeQuery())
+ ->withSourcePHIDs(mpull($books, 'getPHID'))
+ ->withEdgeTypes(array($type_project));
+ $edge_query->execute();
+
+ foreach ($books as $book) {
+ $project_phids = $edge_query->getDestinationPHIDs(
+ array(
+ $book->getPHID(),
+ ));
+ $book->attachProjectPHIDs($project_phids);
+ }
+ }
+
+ return $books;
+ }
+
protected function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
diff --git a/src/applications/diviner/storage/DivinerBookEditController.php b/src/applications/diviner/storage/DivinerBookEditController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diviner/storage/DivinerBookEditController.php
@@ -0,0 +1,98 @@
+<?php
+
+final class DivinerBookEditController extends DivinerController {
+
+ private $bookName;
+
+ public function willProcessRequest(array $data) {
+ $this->bookName = $data['book'];
+ }
+
+ protected function processRequest() {
+ $request = $this->getRequest();
+ $user = $request->getUser();
+
+ $book = id(new DivinerBookQuery())
+ ->setViewer($user)
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->needProjectPHIDs(true)
+ ->withNames(array($this->bookName))
+ ->executeOne();
+
+ $edit_uri = '/book/'.$book->getName().'/edit/';
+
+ if (!$book) {
+ return new Aphront404Response();
+ }
+
+ $v_title = $book->getTitle();
+ $v_preface = $book->getPreface();
+ $e_name = true;
+ $errors = array();
+
+ if ($request->isFormPost()) {
+ $v_projects = $request->getArr('projectPHIDs');
+
+ $xactions = array();
+ $template = id(new DivinerBookTransaction());
+
+ $type_edge = PhabricatorTransactions::TYPE_EDGE;
+
+ $xactions[] = id(clone $template)
+ ->setTransactionType($type_edge)
+ ->setMetadataValue(
+ 'edge:type',
+ PhabricatorProjectObjectHasProjectEdgeType::EDGECONST)
+ ->setNewValue(
+ array(
+ '=' => array_fuse($v_projects),
+ ));
+
+ id(new DivinerBookEditor())
+ ->setContinueOnNoEffect(true)
+ ->setContentSourceFromRequest($request)
+ ->setActor($user)
+ ->applyTransactions($book, $xactions);
+
+ return id(new AphrontRedirectResponse())->setURI($edit_uri);
+ }
+
+ $crumbs = $this->buildApplicationCrumbs();
+ $crumbs->addTextCrumb(pht('Edit Basics'));
+
+ $title = pht('Edit %s', $book->getTitle());
+
+ $form = id(new AphrontFormView())
+ ->setUser($user)
+ ->appendControl(
+ id(new AphrontFormTokenizerControl())
+ ->setDatasource(new PhabricatorProjectDatasource())
+ ->setName('projectPHIDs')
+ ->setLabel(pht('Projects'))
+ ->setValue($book->getProjectPHIDs()))
+ ->appendChild(
+ id(new AphrontFormSubmitControl())
+ ->setValue(pht('Save'))
+ ->addCancelButton($edit_uri))
+ ->appendChild(id(new PHUIFormDividerControl()));
+
+ $object_box = id(new PHUIObjectBoxView())
+ ->setHeaderText($title)
+ ->setForm($form)
+ ->setFormErrors($errors);
+
+ return $this->buildApplicationPage(
+ array(
+ $crumbs,
+ $object_box,
+ ),
+ array(
+ 'title' => $title,
+ ));
+ }
+
+}
diff --git a/src/applications/diviner/storage/DivinerBookTransaction.php b/src/applications/diviner/storage/DivinerBookTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/diviner/storage/DivinerBookTransaction.php
@@ -0,0 +1,17 @@
+<?php
+
+final class DivinerBookTransaction extends PhabricatorApplicationTransaction {
+
+ public function getApplicationName() {
+ return 'diviner';
+ }
+
+ public function getApplicationTransactionType() {
+ return DivinerBookPHIDType::TYPECONST;
+ }
+
+ public function getApplicationTransactionCommentObject() {
+ return null;
+ }
+
+}
diff --git a/src/applications/diviner/storage/DivinerLiveBook.php b/src/applications/diviner/storage/DivinerLiveBook.php
--- a/src/applications/diviner/storage/DivinerLiveBook.php
+++ b/src/applications/diviner/storage/DivinerLiveBook.php
@@ -3,13 +3,16 @@
final class DivinerLiveBook extends DivinerDAO
implements
PhabricatorPolicyInterface,
+ PhabricatorProjectInterface,
PhabricatorDestructibleInterface {
protected $name;
protected $repositoryPHID;
protected $viewPolicy;
+ protected $editPolicy;
protected $configurationData = array();
+ private $projectPHIDs = self::ATTACHABLE;
private $repository = self::ATTACHABLE;
protected function getConfiguration() {
@@ -68,8 +71,13 @@
return idx($spec, 'name', $group);
}
- public function getRepository() {
- return $this->assertAttached($this->repository);
+ public function attachProjectPHIDs(array $project_phids) {
+ $this->projectPHIDs = $project_phids;
+ return $this;
+ }
+
+ public function getProjectPHIDs() {
+ return $this->assertAttached($this->projectPHIDs);
}
public function attachRepository(PhabricatorRepository $repository) {
@@ -77,16 +85,27 @@
return $this;
}
+ public function getRepository() {
+ return $this->assertAttached($this->repository);
+ }
+
+
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
- return PhabricatorPolicies::getMostOpenPolicy();
+ switch ($capability) {
+ case PhabricatorPolicyCapability::CAN_VIEW:
+ return $this->getViewPolicy();
+ case PhabricatorPolicyCapability::CAN_EDIT:
+ return $this->getEditPolicy();
+ }
}
public function hasAutomaticCapability($capability, PhabricatorUser $user) {

File Metadata

Mime Type
text/plain
Expires
Apr 6 2025, 3:36 AM (4 w, 5 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7720789
Default Alt Text
D13091.id31606.diff (17 KB)

Event Timeline