mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-17 12:22:42 +01:00
Add a Packages application and PackagePublisher
Summary: Ref T8116. Partially scavenged from D14152. This roughs in a new Packages application for Arcanist extensions and third-party applications, and adds a "Publisher" object. A "Publisher" represents an individual or entity who is publishing a package, like "Phacility". It's explicitly //not// necessarily the original author -- just the primary entity vouching for the safety of the code. A publisher just has a name and a unique key for now. For example, Phacility might have "Phacility" and "phacility", respectively. Unique keys are immutable, e.g., the package "phacility/arcanist" will always be exactly the same package by exactly the same publisher. Test Plan: {F1731621} Reviewers: chad Reviewed By: chad Maniphest Tasks: T8116 Differential Revision: https://secure.phabricator.com/D16314
This commit is contained in:
parent
eab74a9d7c
commit
9160da1afb
29 changed files with 1011 additions and 0 deletions
11
resources/sql/autopatches/20160721.pack.01.pub.sql
Normal file
11
resources/sql/autopatches/20160721.pack.01.pub.sql
Normal file
|
@ -0,0 +1,11 @@
|
|||
CREATE TABLE {$NAMESPACE}_packages.packages_publisher (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
phid VARBINARY(64) NOT NULL,
|
||||
name VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT},
|
||||
publisherKey VARCHAR(64) NOT NULL COLLATE {$COLLATE_SORT},
|
||||
editPolicy VARBINARY(64) NOT NULL,
|
||||
dateCreated INT UNSIGNED NOT NULL,
|
||||
dateModified INT UNSIGNED NOT NULL,
|
||||
UNIQUE KEY `key_phid` (phid),
|
||||
UNIQUE KEY `key_publisher` (publisherKey)
|
||||
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
|
19
resources/sql/autopatches/20160721.pack.02.pubxaction.sql
Normal file
19
resources/sql/autopatches/20160721.pack.02.pubxaction.sql
Normal file
|
@ -0,0 +1,19 @@
|
|||
CREATE TABLE {$NAMESPACE}_packages.packages_publishertransaction (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
phid VARBINARY(64) NOT NULL,
|
||||
authorPHID VARBINARY(64) NOT NULL,
|
||||
objectPHID VARBINARY(64) NOT NULL,
|
||||
viewPolicy VARBINARY(64) NOT NULL,
|
||||
editPolicy VARBINARY(64) NOT NULL,
|
||||
commentPHID VARBINARY(64) DEFAULT NULL,
|
||||
commentVersion INT UNSIGNED NOT NULL,
|
||||
transactionType VARCHAR(32) COLLATE {$COLLATE_TEXT} NOT NULL,
|
||||
oldValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
|
||||
newValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
|
||||
contentSource LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
|
||||
metadata LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
|
||||
dateCreated INT UNSIGNED NOT NULL,
|
||||
dateModified INT UNSIGNED NOT NULL,
|
||||
UNIQUE KEY `key_phid` (`phid`),
|
||||
KEY `key_object` (`objectPHID`)
|
||||
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
|
16
resources/sql/autopatches/20160721.pack.03.edge.sql
Normal file
16
resources/sql/autopatches/20160721.pack.03.edge.sql
Normal file
|
@ -0,0 +1,16 @@
|
|||
CREATE TABLE {$NAMESPACE}_packages.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}_packages.edgedata (
|
||||
id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
data LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT}
|
||||
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
|
|
@ -2972,6 +2972,30 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPHPASTApplication' => 'applications/phpast/application/PhabricatorPHPASTApplication.php',
|
||||
'PhabricatorPHPConfigSetupCheck' => 'applications/config/check/PhabricatorPHPConfigSetupCheck.php',
|
||||
'PhabricatorPHPMailerConfigOptions' => 'applications/config/option/PhabricatorPHPMailerConfigOptions.php',
|
||||
'PhabricatorPackagesApplication' => 'applications/packages/application/PhabricatorPackagesApplication.php',
|
||||
'PhabricatorPackagesController' => 'applications/packages/controller/PhabricatorPackagesController.php',
|
||||
'PhabricatorPackagesDAO' => 'applications/packages/storage/PhabricatorPackagesDAO.php',
|
||||
'PhabricatorPackagesEditEngine' => 'applications/packages/editor/PhabricatorPackagesEditEngine.php',
|
||||
'PhabricatorPackagesEditor' => 'applications/packages/editor/PhabricatorPackagesEditor.php',
|
||||
'PhabricatorPackagesPublisher' => 'applications/packages/storage/PhabricatorPackagesPublisher.php',
|
||||
'PhabricatorPackagesPublisherController' => 'applications/packages/controller/PhabricatorPackagesPublisherController.php',
|
||||
'PhabricatorPackagesPublisherEditConduitAPIMethod' => 'applications/packages/conduit/PhabricatorPackagesPublisherEditConduitAPIMethod.php',
|
||||
'PhabricatorPackagesPublisherEditController' => 'applications/packages/controller/PhabricatorPackagesPublisherEditController.php',
|
||||
'PhabricatorPackagesPublisherEditEngine' => 'applications/packages/editor/PhabricatorPackagesPublisherEditEngine.php',
|
||||
'PhabricatorPackagesPublisherEditor' => 'applications/packages/editor/PhabricatorPackagesPublisherEditor.php',
|
||||
'PhabricatorPackagesPublisherKeyTransaction' => 'applications/packages/xaction/publisher/PhabricatorPackagesPublisherKeyTransaction.php',
|
||||
'PhabricatorPackagesPublisherListController' => 'applications/packages/controller/PhabricatorPackagesPublisherListController.php',
|
||||
'PhabricatorPackagesPublisherNameTransaction' => 'applications/packages/xaction/publisher/PhabricatorPackagesPublisherNameTransaction.php',
|
||||
'PhabricatorPackagesPublisherPHIDType' => 'applications/packages/phid/PhabricatorPackagesPublisherPHIDType.php',
|
||||
'PhabricatorPackagesPublisherQuery' => 'applications/packages/query/PhabricatorPackagesPublisherQuery.php',
|
||||
'PhabricatorPackagesPublisherSearchConduitAPIMethod' => 'applications/packages/conduit/PhabricatorPackagesPublisherSearchConduitAPIMethod.php',
|
||||
'PhabricatorPackagesPublisherSearchEngine' => 'applications/packages/query/PhabricatorPackagesPublisherSearchEngine.php',
|
||||
'PhabricatorPackagesPublisherTransaction' => 'applications/packages/storage/PhabricatorPackagesPublisherTransaction.php',
|
||||
'PhabricatorPackagesPublisherTransactionQuery' => 'applications/packages/query/PhabricatorPackagesPublisherTransactionQuery.php',
|
||||
'PhabricatorPackagesPublisherTransactionType' => 'applications/packages/xaction/publisher/PhabricatorPackagesPublisherTransactionType.php',
|
||||
'PhabricatorPackagesPublisherViewController' => 'applications/packages/controller/PhabricatorPackagesPublisherViewController.php',
|
||||
'PhabricatorPackagesSchemaSpec' => 'applications/packages/storage/PhabricatorPackagesSchemaSpec.php',
|
||||
'PhabricatorPackagesTransactionType' => 'applications/packages/xaction/PhabricatorPackagesTransactionType.php',
|
||||
'PhabricatorPagerUIExample' => 'applications/uiexample/examples/PhabricatorPagerUIExample.php',
|
||||
'PhabricatorPassphraseApplication' => 'applications/passphrase/application/PhabricatorPassphraseApplication.php',
|
||||
'PhabricatorPasswordAuthProvider' => 'applications/auth/provider/PhabricatorPasswordAuthProvider.php',
|
||||
|
@ -7725,6 +7749,38 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPHPASTApplication' => 'PhabricatorApplication',
|
||||
'PhabricatorPHPConfigSetupCheck' => 'PhabricatorSetupCheck',
|
||||
'PhabricatorPHPMailerConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||
'PhabricatorPackagesApplication' => 'PhabricatorApplication',
|
||||
'PhabricatorPackagesController' => 'PhabricatorController',
|
||||
'PhabricatorPackagesDAO' => 'PhabricatorLiskDAO',
|
||||
'PhabricatorPackagesEditEngine' => 'PhabricatorEditEngine',
|
||||
'PhabricatorPackagesEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'PhabricatorPackagesPublisher' => array(
|
||||
'PhabricatorPackagesDAO',
|
||||
'PhabricatorPolicyInterface',
|
||||
'PhabricatorApplicationTransactionInterface',
|
||||
'PhabricatorDestructibleInterface',
|
||||
'PhabricatorSubscribableInterface',
|
||||
'PhabricatorProjectInterface',
|
||||
'PhabricatorConduitResultInterface',
|
||||
),
|
||||
'PhabricatorPackagesPublisherController' => 'PhabricatorPackagesController',
|
||||
'PhabricatorPackagesPublisherEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod',
|
||||
'PhabricatorPackagesPublisherEditController' => 'PhabricatorPackagesPublisherController',
|
||||
'PhabricatorPackagesPublisherEditEngine' => 'PhabricatorPackagesEditEngine',
|
||||
'PhabricatorPackagesPublisherEditor' => 'PhabricatorPackagesEditor',
|
||||
'PhabricatorPackagesPublisherKeyTransaction' => 'PhabricatorPackagesPublisherTransactionType',
|
||||
'PhabricatorPackagesPublisherListController' => 'PhabricatorPackagesPublisherController',
|
||||
'PhabricatorPackagesPublisherNameTransaction' => 'PhabricatorPackagesPublisherTransactionType',
|
||||
'PhabricatorPackagesPublisherPHIDType' => 'PhabricatorPHIDType',
|
||||
'PhabricatorPackagesPublisherQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhabricatorPackagesPublisherSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
|
||||
'PhabricatorPackagesPublisherSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||
'PhabricatorPackagesPublisherTransaction' => 'PhabricatorModularTransaction',
|
||||
'PhabricatorPackagesPublisherTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||
'PhabricatorPackagesPublisherTransactionType' => 'PhabricatorPackagesTransactionType',
|
||||
'PhabricatorPackagesPublisherViewController' => 'PhabricatorPackagesPublisherController',
|
||||
'PhabricatorPackagesSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
||||
'PhabricatorPackagesTransactionType' => 'PhabricatorModularTransactionType',
|
||||
'PhabricatorPagerUIExample' => 'PhabricatorUIExample',
|
||||
'PhabricatorPassphraseApplication' => 'PhabricatorApplication',
|
||||
'PhabricatorPasswordAuthProvider' => 'PhabricatorAuthProvider',
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPackagesApplication extends PhabricatorApplication {
|
||||
|
||||
public function getName() {
|
||||
return pht('Packages');
|
||||
}
|
||||
|
||||
public function getShortDescription() {
|
||||
return pht('Publish Software');
|
||||
}
|
||||
|
||||
public function getFlavorText() {
|
||||
return pht('Applications and Extensions');
|
||||
}
|
||||
|
||||
public function getBaseURI() {
|
||||
return '/packages/';
|
||||
}
|
||||
|
||||
public function getIcon() {
|
||||
return 'fa-gift';
|
||||
}
|
||||
|
||||
public function isPrototype() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getRoutes() {
|
||||
return array(
|
||||
'/package/' => array(
|
||||
'(?P<publisherKey>[^/]+)/' => array(
|
||||
'' => 'PhabricatorPackagesPublisherViewController',
|
||||
),
|
||||
),
|
||||
'/packages/' => array(
|
||||
'publisher/' => array(
|
||||
$this->getQueryRoutePattern() =>
|
||||
'PhabricatorPackagesPublisherListController',
|
||||
$this->getEditRoutePattern('edit/') =>
|
||||
'PhabricatorPackagesPublisherEditController',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPackagesPublisherEditConduitAPIMethod
|
||||
extends PhabricatorEditEngineAPIMethod {
|
||||
|
||||
public function getAPIMethodName() {
|
||||
return 'packages.publisher.edit';
|
||||
}
|
||||
|
||||
public function newEditEngine() {
|
||||
return new PhabricatorPackagesPublisherEditEngine();
|
||||
}
|
||||
|
||||
public function getMethodSummary() {
|
||||
return pht(
|
||||
'Apply transactions to create a new publisher or edit an existing one.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPackagesPublisherSearchConduitAPIMethod
|
||||
extends PhabricatorSearchEngineAPIMethod {
|
||||
|
||||
public function getAPIMethodName() {
|
||||
return 'packages.publisher.search';
|
||||
}
|
||||
|
||||
public function newSearchEngine() {
|
||||
return new PhabricatorPackagesPublisherSearchEngine();
|
||||
}
|
||||
|
||||
public function getMethodSummary() {
|
||||
return pht('Read information about publishers.');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorPackagesController extends PhabricatorController {}
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorPackagesPublisherController
|
||||
extends PhabricatorPackagesController {}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPackagesPublisherEditController
|
||||
extends PhabricatorPackagesPublisherController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
return id(new PhabricatorPackagesPublisherEditEngine())
|
||||
->setController($this)
|
||||
->buildResponse();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPackagesPublisherListController
|
||||
extends PhabricatorPackagesPublisherController {
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
return id(new PhabricatorPackagesPublisherSearchEngine())
|
||||
->setController($this)
|
||||
->buildResponse();
|
||||
}
|
||||
|
||||
protected function buildApplicationCrumbs() {
|
||||
$crumbs = parent::buildApplicationCrumbs();
|
||||
|
||||
id(new PhabricatorPackagesPublisherEditEngine())
|
||||
->setViewer($this->getViewer())
|
||||
->addActionToCrumbs($crumbs);
|
||||
|
||||
return $crumbs;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPackagesPublisherViewController
|
||||
extends PhabricatorPackagesPublisherController {
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
$publisher_key = $request->getURIData('publisherKey');
|
||||
|
||||
$publisher = id(new PhabricatorPackagesPublisherQuery())
|
||||
->setViewer($viewer)
|
||||
->withPublisherKeys(array($publisher_key))
|
||||
->executeOne();
|
||||
if (!$publisher) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
->addTextCrumb(
|
||||
pht('Publishers'),
|
||||
$this->getApplicationURI('publisher/'))
|
||||
->addTextCrumb($publisher->getName())
|
||||
->setBorder(true);
|
||||
|
||||
$header = $this->buildHeaderView($publisher);
|
||||
$curtain = $this->buildCurtain($publisher);
|
||||
|
||||
$timeline = $this->buildTransactionTimeline(
|
||||
$publisher,
|
||||
new PhabricatorPackagesPublisherTransactionQuery());
|
||||
|
||||
$publisher_view = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setCurtain($curtain)
|
||||
->setMainColumn($timeline);
|
||||
|
||||
return $this->newPage()
|
||||
->setCrumbs($crumbs)
|
||||
->setPageObjectPHIDs(
|
||||
array(
|
||||
$publisher->getPHID(),
|
||||
))
|
||||
->appendChild($publisher_view);
|
||||
}
|
||||
|
||||
|
||||
private function buildHeaderView(PhabricatorPackagesPublisher $publisher) {
|
||||
$viewer = $this->getViewer();
|
||||
$name = $publisher->getName();
|
||||
|
||||
return id(new PHUIHeaderView())
|
||||
->setViewer($viewer)
|
||||
->setHeader($name)
|
||||
->setPolicyObject($publisher)
|
||||
->setHeaderIcon('fa-paw');
|
||||
}
|
||||
|
||||
private function buildCurtain(PhabricatorPackagesPublisher $publisher) {
|
||||
$viewer = $this->getViewer();
|
||||
$curtain = $this->newCurtainView($publisher);
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
$publisher,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
|
||||
$id = $publisher->getID();
|
||||
$edit_uri = $this->getApplicationURI("publisher/edit/{$id}/");
|
||||
|
||||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName(pht('Edit Publisher'))
|
||||
->setIcon('fa-pencil')
|
||||
->setDisabled(!$can_edit)
|
||||
->setHref($edit_uri));
|
||||
|
||||
return $curtain;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorPackagesEditEngine
|
||||
extends PhabricatorEditEngine {
|
||||
|
||||
public function isEngineConfigurable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getEngineApplicationClass() {
|
||||
return 'PhabricatorPackagesApplication';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorPackagesEditor
|
||||
extends PhabricatorApplicationTransactionEditor {
|
||||
|
||||
public function getEditorApplicationClass() {
|
||||
return 'PhabricatorPasteApplication';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPackagesPublisherEditEngine
|
||||
extends PhabricatorPackagesEditEngine {
|
||||
|
||||
const ENGINECONST = 'packages.publisher';
|
||||
|
||||
public function getEngineName() {
|
||||
return pht('Package Publishers');
|
||||
}
|
||||
|
||||
public function getSummaryHeader() {
|
||||
return pht('Edit Package Publisher Configurations');
|
||||
}
|
||||
|
||||
public function getSummaryText() {
|
||||
return pht('This engine is used to edit Packages publishers.');
|
||||
}
|
||||
|
||||
protected function newEditableObject() {
|
||||
$viewer = $this->getViewer();
|
||||
return PhabricatorPackagesPublisher::initializeNewPublisher($viewer);
|
||||
}
|
||||
|
||||
protected function newObjectQuery() {
|
||||
return new PhabricatorPackagesPublisherQuery();
|
||||
}
|
||||
|
||||
protected function getObjectCreateTitleText($object) {
|
||||
return pht('Create Publisher');
|
||||
}
|
||||
|
||||
protected function getObjectCreateButtonText($object) {
|
||||
return pht('Create Publisher');
|
||||
}
|
||||
|
||||
protected function getObjectEditTitleText($object) {
|
||||
return pht('Edit Publisher: %s', $object->getName());
|
||||
}
|
||||
|
||||
protected function getObjectEditShortText($object) {
|
||||
return pht('Edit Publisher');
|
||||
}
|
||||
|
||||
protected function getObjectCreateShortText() {
|
||||
return pht('Create Publisher');
|
||||
}
|
||||
|
||||
protected function getObjectName() {
|
||||
return pht('Publisher');
|
||||
}
|
||||
|
||||
protected function getEditorURI() {
|
||||
return '/packages/publisher/edit/';
|
||||
}
|
||||
|
||||
protected function getObjectCreateCancelURI($object) {
|
||||
return '/packages/publisher/';
|
||||
}
|
||||
|
||||
protected function getObjectViewURI($object) {
|
||||
return $object->getURI();
|
||||
}
|
||||
|
||||
protected function buildCustomEditFields($object) {
|
||||
$fields = array();
|
||||
|
||||
$fields[] = id(new PhabricatorTextEditField())
|
||||
->setKey('name')
|
||||
->setLabel(pht('Name'))
|
||||
->setDescription(pht('Name of the publisher.'))
|
||||
->setTransactionType(
|
||||
PhabricatorPackagesPublisherNameTransaction::TRANSACTIONTYPE)
|
||||
->setIsRequired(true)
|
||||
->setValue($object->getName());
|
||||
|
||||
if ($this->getIsCreate()) {
|
||||
$fields[] = id(new PhabricatorTextEditField())
|
||||
->setKey('publisherKey')
|
||||
->setLabel(pht('Publisher Key'))
|
||||
->setDescription(pht('Unique key to identify the publisher.'))
|
||||
->setTransactionType(
|
||||
PhabricatorPackagesPublisherKeyTransaction::TRANSACTIONTYPE)
|
||||
->setIsRequired(true)
|
||||
->setValue($object->getPublisherKey());
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPackagesPublisherEditor
|
||||
extends PhabricatorPackagesEditor {
|
||||
|
||||
public function getEditorObjectsDescription() {
|
||||
return pht('Package Publishers');
|
||||
}
|
||||
|
||||
public function getCreateObjectTitle($author, $object) {
|
||||
return pht('%s created this publisher.', $author);
|
||||
}
|
||||
|
||||
public function getCreateObjectTitleForFeed($author, $object) {
|
||||
return pht('%s created %s.', $author, $object);
|
||||
}
|
||||
|
||||
public function getTransactionTypes() {
|
||||
$types = parent::getTransactionTypes();
|
||||
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
|
||||
return $types;
|
||||
}
|
||||
|
||||
protected function shouldPublishFeedStory(
|
||||
PhabricatorLiskDAO $object,
|
||||
array $xactions) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function getMailTo(PhabricatorLiskDAO $object) {
|
||||
return array();
|
||||
}
|
||||
|
||||
protected function didCatchDuplicateKeyException(
|
||||
PhabricatorLiskDAO $object,
|
||||
array $xactions,
|
||||
Exception $ex) {
|
||||
|
||||
$errors = array();
|
||||
$errors[] = new PhabricatorApplicationTransactionValidationError(
|
||||
PhabricatorPackagesPublisherKeyTransaction::TRANSACTIONTYPE,
|
||||
pht('Duplicate'),
|
||||
pht(
|
||||
'The publisher key "%s" is already in use by another publisher.',
|
||||
$object->getPublisherKey()),
|
||||
null);
|
||||
|
||||
throw new PhabricatorApplicationTransactionValidationException($errors);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPackagesPublisherPHIDType
|
||||
extends PhabricatorPHIDType {
|
||||
|
||||
const TYPECONST = 'PPUB';
|
||||
|
||||
public function getTypeName() {
|
||||
return pht('Package Publisher');
|
||||
}
|
||||
|
||||
public function newObject() {
|
||||
return new PhabricatorPackagesPublisher();
|
||||
}
|
||||
|
||||
public function getPHIDTypeApplicationClass() {
|
||||
return 'PhabricatorPackagesApplication';
|
||||
}
|
||||
|
||||
protected function buildQueryForObjects(
|
||||
PhabricatorObjectQuery $query,
|
||||
array $phids) {
|
||||
|
||||
return id(new PhabricatorPackagesPublisherQuery())
|
||||
->withPHIDs($phids);
|
||||
}
|
||||
|
||||
public function loadHandles(
|
||||
PhabricatorHandleQuery $query,
|
||||
array $handles,
|
||||
array $objects) {
|
||||
|
||||
foreach ($handles as $phid => $handle) {
|
||||
$publisher = $objects[$phid];
|
||||
|
||||
$name = $publisher->getName();
|
||||
$uri = $publisher->getURI();
|
||||
|
||||
$handle
|
||||
->setName($name)
|
||||
->setURI($uri);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPackagesPublisherQuery
|
||||
extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||
|
||||
private $ids;
|
||||
private $phids;
|
||||
private $publisherKeys;
|
||||
|
||||
public function withIDs(array $ids) {
|
||||
$this->ids = $ids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withPHIDs(array $phids) {
|
||||
$this->phids = $phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withPublisherKeys(array $keys) {
|
||||
$this->publisherKeys = $keys;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function newResultObject() {
|
||||
return new PhabricatorPackagesPublisher();
|
||||
}
|
||||
|
||||
protected function loadPage() {
|
||||
return $this->loadStandardPage($this->newResultObject());
|
||||
}
|
||||
|
||||
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
||||
$where = parent::buildWhereClauseParts($conn);
|
||||
|
||||
if ($this->ids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'id IN (%Ld)',
|
||||
$this->ids);
|
||||
}
|
||||
|
||||
if ($this->phids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'phid IN (%Ls)',
|
||||
$this->phids);
|
||||
}
|
||||
|
||||
if ($this->publisherKeys !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'publisherKey IN (%Ls)',
|
||||
$this->publisherKeys);
|
||||
}
|
||||
|
||||
return $where;
|
||||
}
|
||||
|
||||
public function getQueryApplicationClass() {
|
||||
return 'PhabricatorPackagesApplication';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPackagesPublisherSearchEngine
|
||||
extends PhabricatorApplicationSearchEngine {
|
||||
|
||||
public function getResultTypeDescription() {
|
||||
return pht('Package Publishers');
|
||||
}
|
||||
|
||||
public function getApplicationClassName() {
|
||||
return 'PhabricatorPackagesApplication';
|
||||
}
|
||||
|
||||
public function newQuery() {
|
||||
return id(new PhabricatorPackagesPublisherQuery());
|
||||
}
|
||||
|
||||
protected function buildQueryFromParameters(array $map) {
|
||||
$query = $this->newQuery();
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
protected function buildCustomSearchFields() {
|
||||
return array();
|
||||
}
|
||||
|
||||
protected function getURI($path) {
|
||||
return '/packages/publisher/'.$path;
|
||||
}
|
||||
|
||||
protected function getBuiltinQueryNames() {
|
||||
$names = array(
|
||||
'all' => pht('All Publishers'),
|
||||
);
|
||||
|
||||
return $names;
|
||||
}
|
||||
|
||||
public function buildSavedQueryFromBuiltin($query_key) {
|
||||
$query = $this->newSavedQuery();
|
||||
$query->setQueryKey($query_key);
|
||||
|
||||
switch ($query_key) {
|
||||
case 'all':
|
||||
return $query;
|
||||
}
|
||||
|
||||
return parent::buildSavedQueryFromBuiltin($query_key);
|
||||
}
|
||||
|
||||
protected function renderResultList(
|
||||
array $publishers,
|
||||
PhabricatorSavedQuery $query,
|
||||
array $handles) {
|
||||
|
||||
assert_instances_of($publishers, 'PhabricatorPackagesPublisher');
|
||||
|
||||
$viewer = $this->requireViewer();
|
||||
|
||||
$list = id(new PHUIObjectItemListView())
|
||||
->setViewer($viewer);
|
||||
foreach ($publishers as $publisher) {
|
||||
$item = id(new PHUIObjectItemView())
|
||||
->setObjectName($publisher->getPublisherKey())
|
||||
->setHeader($publisher->getName())
|
||||
->setHref($publisher->getURI());
|
||||
|
||||
$list->addItem($item);
|
||||
}
|
||||
|
||||
return id(new PhabricatorApplicationSearchResultView())
|
||||
->setObjectList($list)
|
||||
->setNoDataString(pht('No publishers found.'));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPackagesPublisherTransactionQuery
|
||||
extends PhabricatorApplicationTransactionQuery {
|
||||
|
||||
public function getTemplateApplicationTransaction() {
|
||||
return new PhabricatorPackagesPublisherTransaction();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorPackagesDAO extends PhabricatorLiskDAO {
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'packages';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,191 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPackagesPublisher
|
||||
extends PhabricatorPackagesDAO
|
||||
implements
|
||||
PhabricatorPolicyInterface,
|
||||
PhabricatorApplicationTransactionInterface,
|
||||
PhabricatorDestructibleInterface,
|
||||
PhabricatorSubscribableInterface,
|
||||
PhabricatorProjectInterface,
|
||||
PhabricatorConduitResultInterface {
|
||||
|
||||
protected $name;
|
||||
protected $publisherKey;
|
||||
protected $editPolicy;
|
||||
|
||||
public static function initializeNewPublisher(PhabricatorUser $actor) {
|
||||
return id(new self());
|
||||
}
|
||||
|
||||
protected function getConfiguration() {
|
||||
return array(
|
||||
self::CONFIG_AUX_PHID => true,
|
||||
self::CONFIG_COLUMN_SCHEMA => array(
|
||||
'name' => 'text64',
|
||||
'publisherKey' => 'sort64',
|
||||
),
|
||||
self::CONFIG_KEY_SCHEMA => array(
|
||||
'key_publisher' => array(
|
||||
'columns' => array('publisherKey'),
|
||||
'unique' => true,
|
||||
),
|
||||
),
|
||||
) + parent::getConfiguration();
|
||||
}
|
||||
|
||||
public function generatePHID() {
|
||||
return PhabricatorPHID::generateNewPHID(
|
||||
PhabricatorPackagesPublisherPHIDType::TYPECONST);
|
||||
}
|
||||
|
||||
public function getURI() {
|
||||
$publisher_key = $this->getPublisherKey();
|
||||
return "/package/{$publisher_key}/";
|
||||
}
|
||||
|
||||
public static function assertValidPublisherName($value) {
|
||||
$length = phutil_utf8_strlen($value);
|
||||
if (!$length) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Publisher name "%s" is not valid: publisher names are required.',
|
||||
$value));
|
||||
}
|
||||
|
||||
$max_length = 64;
|
||||
if ($length > $max_length) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Publisher name "%s" is not valid: publisher names must not be '.
|
||||
'more than %s characters long.',
|
||||
$value,
|
||||
new PhutilNumber($max_length)));
|
||||
}
|
||||
}
|
||||
|
||||
public static function assertValidPublisherKey($value) {
|
||||
$length = phutil_utf8_strlen($value);
|
||||
if (!$length) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Publisher key "%s" is not valid: publisher keys are required.',
|
||||
$value));
|
||||
}
|
||||
|
||||
$max_length = 64;
|
||||
if ($length > $max_length) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Publisher key "%s" is not valid: publisher keys must not be '.
|
||||
'more than %s characters long.',
|
||||
$value,
|
||||
new PhutilNumber($max_length)));
|
||||
}
|
||||
|
||||
if (!preg_match('/^[a-z]+\z/', $value)) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Publisher key "%s" is not valid: publisher keys may only contain '.
|
||||
'lowercase latin letters.',
|
||||
$value));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorSubscribableInterface )----------------------------------- */
|
||||
|
||||
|
||||
public function isAutomaticallySubscribed($phid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* -( Policy Interface )--------------------------------------------------- */
|
||||
|
||||
|
||||
public function getCapabilities() {
|
||||
return array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
);
|
||||
}
|
||||
|
||||
public function getPolicy($capability) {
|
||||
switch ($capability) {
|
||||
case PhabricatorPolicyCapability::CAN_VIEW:
|
||||
return PhabricatorPolicies::getMostOpenPolicy();
|
||||
case PhabricatorPolicyCapability::CAN_EDIT:
|
||||
return $this->getEditPolicy();
|
||||
}
|
||||
}
|
||||
|
||||
public function hasAutomaticCapability($capability, PhabricatorUser $user) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorDestructibleInterface )----------------------------------- */
|
||||
|
||||
|
||||
public function destroyObjectPermanently(
|
||||
PhabricatorDestructionEngine $engine) {
|
||||
$this->delete();
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
|
||||
|
||||
|
||||
public function getApplicationTransactionEditor() {
|
||||
return new PhabricatorPackagesPublisherEditor();
|
||||
}
|
||||
|
||||
public function getApplicationTransactionObject() {
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getApplicationTransactionTemplate() {
|
||||
return new PhabricatorPackagesPublisherTransaction();
|
||||
}
|
||||
|
||||
public function willRenderTimeline(
|
||||
PhabricatorApplicationTransactionView $timeline,
|
||||
AphrontRequest $request) {
|
||||
return $timeline;
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorConduitResultInterface )---------------------------------- */
|
||||
|
||||
|
||||
public function getFieldSpecificationsForConduit() {
|
||||
return array(
|
||||
id(new PhabricatorConduitSearchFieldSpecification())
|
||||
->setKey('name')
|
||||
->setType('string')
|
||||
->setDescription(pht('The name of the publisher.')),
|
||||
id(new PhabricatorConduitSearchFieldSpecification())
|
||||
->setKey('publisherKey')
|
||||
->setType('string')
|
||||
->setDescription(pht('The unique key of the publisher.')),
|
||||
);
|
||||
}
|
||||
|
||||
public function getFieldValuesForConduit() {
|
||||
return array(
|
||||
'name' => $this->getName(),
|
||||
'publisherKey' => $this->getPublisherKey(),
|
||||
);
|
||||
}
|
||||
|
||||
public function getConduitSearchAttachments() {
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPackagesPublisherTransaction
|
||||
extends PhabricatorModularTransaction {
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'packages';
|
||||
}
|
||||
|
||||
public function getApplicationTransactionType() {
|
||||
return PhabricatorPackagesPublisherPHIDType::TYPECONST;
|
||||
}
|
||||
|
||||
public function getBaseTransactionClass() {
|
||||
return 'PhabricatorPackagesPublisherTransactionType';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPackagesSchemaSpec
|
||||
extends PhabricatorConfigSchemaSpec {
|
||||
|
||||
public function buildSchemata() {
|
||||
$this->buildEdgeSchemata(new PhabricatorPackagesPublisher());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorPackagesTransactionType
|
||||
extends PhabricatorModularTransactionType {}
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPackagesPublisherKeyTransaction
|
||||
extends PhabricatorPackagesPublisherTransactionType {
|
||||
|
||||
const TRANSACTIONTYPE = 'packages.publisher.key';
|
||||
|
||||
public function generateOldValue($object) {
|
||||
return $object->getPublisherKey();
|
||||
}
|
||||
|
||||
public function applyInternalEffects($object, $value) {
|
||||
$object->setPublisherKey($value);
|
||||
}
|
||||
|
||||
public function validateTransactions($object, array $xactions) {
|
||||
$errors = array();
|
||||
|
||||
if ($this->isEmptyTextTransaction($object->getName(), $xactions)) {
|
||||
$errors[] = $this->newRequiredError(
|
||||
pht('Publishers must have a unique publisher key.'));
|
||||
}
|
||||
|
||||
if (!$this->isNewObject()) {
|
||||
foreach ($xactions as $xaction) {
|
||||
$errors[] = $this->newInvalidError(
|
||||
pht('Once a publisher is created, its key can not be changed.'),
|
||||
$xaction);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($xactions as $xaction) {
|
||||
$value = $xaction->getNewValue();
|
||||
try {
|
||||
PhabricatorPackagesPublisher::assertValidPublisherKey($value);
|
||||
} catch (Exception $ex) {
|
||||
$errors[] = $this->newInvalidError($ex->getMessage(), $xaction);
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPackagesPublisherNameTransaction
|
||||
extends PhabricatorPackagesPublisherTransactionType {
|
||||
|
||||
const TRANSACTIONTYPE = 'packages.publisher.name';
|
||||
|
||||
public function generateOldValue($object) {
|
||||
return $object->getName();
|
||||
}
|
||||
|
||||
public function applyInternalEffects($object, $value) {
|
||||
$object->setName($value);
|
||||
}
|
||||
|
||||
public function getTitle() {
|
||||
return pht(
|
||||
'%s changed the name of this publisher from %s to %s.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderOldValue(),
|
||||
$this->renderNewValue());
|
||||
}
|
||||
|
||||
public function getTitleForFeed() {
|
||||
return pht(
|
||||
'%s updated the name for %s from %s to %s.',
|
||||
$this->renderAuthor(),
|
||||
$this->renderObject(),
|
||||
$this->renderOldValue(),
|
||||
$this->renderNewValue());
|
||||
}
|
||||
|
||||
public function validateTransactions($object, array $xactions) {
|
||||
$errors = array();
|
||||
|
||||
if ($this->isEmptyTextTransaction($object->getName(), $xactions)) {
|
||||
$errors[] = $this->newRequiredError(
|
||||
pht('Publishers must have a name.'));
|
||||
}
|
||||
|
||||
foreach ($xactions as $xaction) {
|
||||
$value = $xaction->getNewValue();
|
||||
try {
|
||||
PhabricatorPackagesPublisher::assertValidPublisherName($value);
|
||||
} catch (Exception $ex) {
|
||||
$errors[] = $this->newInvalidError($ex->getMessage(), $xaction);
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
|
||||
abstract class PhabricatorPackagesPublisherTransactionType
|
||||
extends PhabricatorPackagesTransactionType {}
|
|
@ -111,6 +111,7 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
|
|||
'db.spaces' => array(),
|
||||
'db.phurl' => array(),
|
||||
'db.badges' => array(),
|
||||
'db.packages' => array(),
|
||||
'0000.legacy.sql' => array(
|
||||
'legacy' => 0,
|
||||
),
|
||||
|
|
Loading…
Reference in a new issue